Skip to content

chore: 🐝 Update SDK - Generate SDK 0.5.0#163

Open
mattapperson wants to merge 1 commit into
mainfrom
speakeasy-sdk-regen-1776877485
Open

chore: 🐝 Update SDK - Generate SDK 0.5.0#163
mattapperson wants to merge 1 commit into
mainfrom
speakeasy-sdk-regen-1776877485

Conversation

@mattapperson

@mattapperson mattapperson commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

SDK update

Versioning

Version Bump Type: [minor] - 🤖 (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.

Go SDK Changes:

  • OpenRouter.Chat.Send():
    • request Changed (Breaking ⚠️)
    • response Changed
    • error Changed
  • OpenRouter.VideoGeneration.Generate():
    • request.Request Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Beta.Responses.Send():
    • request Changed (Breaking ⚠️)
    • response Changed (Breaking ⚠️)
    • error Changed
  • OpenRouter.Rerank.Rerank():
    • request.Request Changed (Breaking ⚠️)
    • response.Results[].Document Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Models.ListForUser():
    • response.Data[] Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Models.List():
    • request Changed (Breaking ⚠️)
    • response.Data[] Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Generations.GetGeneration():
    • response.Data Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Endpoints.List():
    • response.Data Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Endpoints.ListZdrEndpoints():
    • response.Data[].ProviderName Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Embeddings.ListModels():
    • response.Data[] Changed (Breaking ⚠️)
    • error.OpenrouterMetadata Added
  • OpenRouter.Embeddings.Generate():
    • request.Request Changed (Breaking ⚠️)
    • response.Usage.PromptTokensDetails.FileTokens Added
    • error.OpenrouterMetadata Added
  • OpenRouter.Observability.Create(): Added
  • OpenRouter.Guardrails.Delete(): error.OpenrouterMetadata Added
  • OpenRouter.Files.Upload(): Added
  • OpenRouter.Files.Delete(): Added
  • OpenRouter.Files.Retrieve(): Added
  • OpenRouter.Files.Download(): Added
  • OpenRouter.Models.Get(): Added
  • OpenRouter.Observability.List(): Added
  • OpenRouter.Beta.Analytics.GetAnalyticsMeta(): Added
  • OpenRouter.Observability.Delete(): Added
  • OpenRouter.Observability.Get(): Added
  • OpenRouter.Observability.Update(): Added
  • OpenRouter.Presets.List(): Added
  • OpenRouter.Presets.Get(): Added
  • OpenRouter.Presets.CreatePresetsChatCompletions(): Added
  • OpenRouter.Presets.CreatePresetsMessages(): Added
  • OpenRouter.Presets.CreatePresetsResponses(): Added
  • OpenRouter.Presets.ListVersions(): Added
  • OpenRouter.Presets.GetVersion(): Added
  • OpenRouter.Analytics.GetUserActivity(): error.OpenrouterMetadata Added
  • OpenRouter.Tts.CreateSpeech():
    • request.Request.Provider.Options Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.OAuth.ExchangeAuthCodeForApiKey(): error.OpenrouterMetadata Added
  • OpenRouter.OAuth.CreateAuthCode():
    • request.Request.WorkspaceId Added
    • error Changed
  • OpenRouter.Datasets.GetRankingsDaily(): Added
  • OpenRouter.Credits.GetCredits(): error.OpenrouterMetadata Added
  • OpenRouter.Datasets.GetBenchmarksDesignArena(): Added
  • OpenRouter.Datasets.GetBenchmarksArtificialAnalysis(): Added
  • OpenRouter.Datasets.GetAppRankings(): Added
  • OpenRouter.Byok.Update(): Added
  • OpenRouter.Byok.Get(): Added
  • OpenRouter.Generations.ListGenerationContent(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.List():
    • response.Data[] Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.Create():
    • request.Request Changed
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Files.List(): Added
  • OpenRouter.Guardrails.Get():
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.Update():
    • request.UpdateGuardrailRequest Changed
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.ListGuardrailKeyAssignments(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.BulkAssignKeys(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.BulkUnassignKeys(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.ListGuardrailMemberAssignments(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.BulkAssignMembers(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.BulkUnassignMembers(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.ListKeyAssignments(): error.OpenrouterMetadata Added
  • OpenRouter.Guardrails.ListMemberAssignments(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.GetCurrentKeyMetadata(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.List(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.Create(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.Delete(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.Get(): error.OpenrouterMetadata Added
  • OpenRouter.ApiKeys.Update(): error.OpenrouterMetadata Added
  • OpenRouter.Byok.Delete(): Added
  • OpenRouter.Models.Count(): error.OpenrouterMetadata Added
  • OpenRouter.Byok.Create(): Added
  • OpenRouter.Organization.ListMembers(): error.OpenrouterMetadata Added
  • OpenRouter.Providers.List(): error.OpenrouterMetadata Added
  • OpenRouter.Byok.List(): Added
  • OpenRouter.Stt.CreateTranscription(): Added
  • OpenRouter.Beta.Analytics.QueryAnalytics(): Added
  • OpenRouter.VideoGeneration.GetGeneration(): error.OpenrouterMetadata Added
  • OpenRouter.VideoGeneration.GetVideoContent(): error.OpenrouterMetadata Added
  • OpenRouter.VideoGeneration.ListVideosModels():
    • response.Data[] Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.List():
    • response.Data[] Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.Create():
    • request.Request Changed
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.Delete(): error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.Get():
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.Update():
    • request.UpdateWorkspaceRequest Changed
    • response.Data Changed
    • error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.BulkAddMembers(): error.OpenrouterMetadata Added
  • OpenRouter.Workspaces.BulkRemoveMembers(): error.OpenrouterMetadata Added

View full SDK changelog

OpenAPI Change Summary
├─┬Paths
│ ├──[+] path (21864:3)
│ ├──[+] path (24045:3)
│ ├──[+] path (24879:3)
│ ├──[+] path (22037:3)
│ ├──[+] path (28149:3)
│ ├──[+] path (28905:3)
│ ├──[+] path (28715:3)
│ ├──[+] path (29268:3)
│ ├──[+] path (29361:3)
│ ├──[+] path (22793:3)
│ ├──[+] path (22379:3)
│ ├──[+] path (24667:3)
│ ├──[+] path (29452:3)
│ ├──[+] path (29821:3)
│ ├──[+] path (29701:3)
│ ├──[+] path (23628:3)
│ ├──[+] path (23840:3)
│ ├──[+] path (25031:3)
│ ├──[+] path (29577:3)
│ ├──[+] path (23057:3)
│ ├──[+] path (23924:3)
│ ├──[+] path (29932:3)
│ ├─┬/workspaces/{id}
│ │ ├─┬GET
│ │ │ └─┬Responses
│ │ │   └─┬200
│ │ │     └─┬application/json
│ │ │       └──[🔀] example (31700:17)
│ │ └─┬PATCH
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (31781:17)
│ ├─┬/models/user
│ │ └─┬GET
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (28641:17)
│ ├─┬/messages
│ │ └─┬POST
│ │   ├──[+] parameters (27966:9)
│ │   └─┬Responses
│ │     ├─┬403
│ │     │ ├──[🔀] description (28086:24)
│ │     │ └─┬application/json
│ │     │   ├──[-] example (19043:17)
│ │     │   ├──[+] examples (28079:19)
│ │     │   ├──[+] examples (28044:19)
│ │     │   └─┬Schema
│ │     │     └──[🔀] $ref (7693:20)❌ 
│ │     └─┬200
│ │       └─┬text/event-stream
│ │         └─┬Schema
│ │           └──[🔀] $ref (12039:9)❌ 
│ ├─┬/audio/speech
│ │ └─┬POST
│ │   ├──[🔀] description (22248:20)
│ │   ├─┬Responses
│ │   │ └─┬200
│ │   │   └─┬audio/*
│ │   │     └─┬Schema
│ │   │       └──[🔀] description (22268:30)
│ │   └─┬Extensions
│ │     └──[+] x-speakeasy-max-method-params (22377:38)
│ ├─┬/embeddings
│ │ └─┬POST
│ │   ├─┬Responses
│ │   │ └─┬200
│ │   │   └─┬application/json
│ │   │     └─┬Schema
│ │   │       └─┬usage
│ │   │         └─┬prompt_tokens_details
│ │   │           ├──[+] properties (24359:27)
│ │   │           ├─┬video_tokens
│ │   │           │ ├──[🔀] description (24367:42)
│ │   │           │ └──[+] example (24368:38)
│ │   │           ├─┬image_tokens
│ │   │           │ ├──[🔀] description (24360:42)
│ │   │           │ └──[-] example (15824:38)
│ │   │           └─┬text_tokens
│ │   │             ├──[🔀] description (24363:42)
│ │   │             └──[🔀] example (24364:38)
│ │   └─┬Requestbody
│ │     └─┬application/json
│ │       └─┬Schema
│ │         └─┬input
│ │           └─┬ANYOF
│ │             └─┬Schema
│ │               └─┬content
│ │                 └─┬Schema
│ │                   ├──[+] oneOf (6345:7)
│ │                   ├──[+] oneOf (6379:7)
│ │                   └──[+] oneOf (6362:7)
│ ├─┬/guardrails/{id}
│ │ └─┬PATCH
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (25722:17)
│ ├─┬/rerank
│ │ └─┬POST
│ │   ├─┬Responses
│ │   │ └─┬200
│ │   │   └─┬application/json
│ │   │     └─┬Schema
│ │   │       └─┬results
│ │   │         └─┬Schema
│ │   │           └─┬document
│ │   │             ├──[-] required (20312:31)❌ 
│ │   │             ├──[🔀] description (30740:40)
│ │   │             ├──[+] properties (30742:29)
│ │   │             └─┬text
│ │   │               ├──[🔀] description (30743:44)
│ │   │               └──[🔀] example (30744:40)
│ │   └─┬Requestbody
│ │     └─┬application/json
│ │       └─┬Schema
│ │         └─┬documents
│ │           ├──[+] minItems (30669:29)❌ 
│ │           ├──[🔀] description (30646:32)
│ │           └─┬Schema
│ │             ├──[-] type (20234:27)❌ 
│ │             ├──[+] description (30667:34)
│ │             ├──[+] anyOf (30653:25)
│ │             └──[+] anyOf (30654:25)
│ ├─┬/auth/keys/code
│ │ └─┬POST
│ │   ├─┬Responses
│ │   │ └──[+] codes (22760:11)
│ │   └─┬Requestbody
│ │     └─┬application/json
│ │       └─┬Schema
│ │         ├──[+] properties (22687:17)
│ │         └─┬callback_url
│ │           └──[🔀] description (22633:32)
│ ├─┬/responses
│ │ └─┬POST
│ │   ├──[+] parameters (30906:9)
│ │   └─┬Responses
│ │     ├──[+] codes (30985:11)
│ │     └─┬200
│ │       └─┬text/event-stream
│ │         └─┬Schema
│ │           └──[🔀] $ref (19125:9)❌ 
│ ├─┬/videos/{jobId}
│ │ └─┬GET
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (31247:17)
│ ├─┬/workspaces
│ │ ├─┬GET
│ │ │ └─┬Responses
│ │ │   └─┬200
│ │ │     └─┬application/json
│ │ │       └──[🔀] example (31464:17)
│ │ └─┬POST
│ │   └─┬Responses
│ │     └─┬201
│ │       └─┬application/json
│ │         └──[🔀] example (31541:17)
│ ├─┬/chat/completions
│ │ └─┬POST
│ │   ├──[+] parameters (23278:9)
│ │   └─┬Responses
│ │     ├──[+] codes (23370:11)
│ │     └─┬200
│ │       └─┬text/event-stream
│ │         └─┬Schema
│ │           └──[🔀] $ref (5445:9)❌ 
│ ├─┬/embeddings/models
│ │ └─┬GET
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (24507:17)
│ ├─┬/models
│ │ └─┬GET
│ │   ├──[+] parameters (28389:17)❌ 
│ │   ├──[+] parameters (28379:17)❌ 
│ │   ├──[+] parameters (28278:17)❌ 
│ │   ├──[+] parameters (28313:17)❌ 
│ │   ├──[+] parameters (28323:17)❌ 
│ │   ├──[+] parameters (28333:17)❌ 
│ │   ├──[+] parameters (28343:17)❌ 
│ │   ├──[+] parameters (28359:17)❌ 
│ │   ├──[+] parameters (28367:17)❌ 
│ │   ├──[+] parameters (28297:17)❌ 
│ │   ├──[+] parameters (28305:17)❌ 
│ │   ├──[+] parameters (28351:17)❌ 
│ │   └─┬Responses
│ │     └─┬200
│ │       └─┬application/json
│ │         └──[🔀] example (28402:17)
│ └─┬/guardrails
│   └─┬POST
│     ├─┬Responses
│     │ └─┬201
│     │   └─┬application/json
│     │     └──[🔀] example (25496:17)
│     └─┬Requestbody
│       └─┬application/json
│         └──[🔀] example (25473:15)
├─┬Tags
│ └─┬Extensions
│   └──[+] x-displayname (32086:20)
├─┬Tags
│ └──[+] Files (32061:5)
├─┬Tags
│ └──[+] Datasets (32055:5)
├─┬Tags
│ └──[+] Presets (32075:5)
├─┬Tags
│ └──[+] STT (32081:5)
├─┬Tags
│ └──[+] beta.Analytics (32091:5)
├─┬Tags
│ └──[+] BYOK (32049:5)
├─┬Tags
│ └──[+] Observability (32071:5)
├─┬Components
│ ├──[+] schemas (16999:7)
│ ├──[+] schemas (2218:7)
│ ├──[-] schemas (1150:7)❌ 
│ ├──[-] schemas (1176:7)❌ 
│ ├──[+] schemas (16318:7)
│ ├──[+] schemas (14206:7)
│ ├──[+] schemas (2771:7)
│ ├──[+] schemas (15148:7)
│ ├──[+] schemas (2399:7)
│ ├──[+] schemas (8252:7)
│ ├──[+] schemas (6237:7)
│ ├──[+] schemas (7497:7)
│ ├──[+] schemas (19181:7)
│ ├──[+] schemas (7380:7)
│ ├──[+] schemas (2329:7)
│ ├──[+] schemas (19152:7)
│ ├──[+] schemas (7031:7)
│ ├──[+] schemas (3924:7)
│ ├──[+] schemas (19416:7)
│ ├──[+] schemas (2482:7)
│ ├──[+] schemas (18377:7)
│ ├──[+] schemas (1249:7)
│ ├──[+] schemas (5968:7)
│ ├──[+] schemas (9647:7)
│ ├──[+] schemas (10393:7)
│ ├──[+] schemas (6345:7)
│ ├──[+] schemas (13077:7)
│ ├──[+] schemas (15046:7)
│ ├──[+] schemas (10420:7)
│ ├──[+] schemas (10448:7)
│ ├──[+] schemas (7552:7)
│ ├──[+] schemas (8153:7)
│ ├──[+] schemas (10684:7)
│ ├──[+] schemas (19533:7)
│ ├──[+] schemas (15762:7)
│ ├──[+] schemas (14096:7)
│ ├──[+] schemas (19313:7)
│ ├──[+] schemas (19167:7)
│ ├──[+] schemas (20010:7)
│ ├──[+] schemas (8101:7)
│ ├──[+] schemas (16365:7)
│ ├──[+] schemas (10475:7)
│ ├──[+] schemas (6282:7)
│ ├──[+] schemas (6516:7)
│ ├──[+] schemas (3571:7)
│ ├──[+] schemas (281:7)
│ ├──[+] schemas (10273:7)
│ ├──[+] schemas (4250:7)
│ ├──[+] schemas (8077:7)
│ ├──[+] schemas (303:7)
│ ├──[+] schemas (7092:7)
│ ├──[+] schemas (14442:7)
│ ├──[+] schemas (19266:7)
│ ├──[+] schemas (9863:7)
│ ├──[+] schemas (19993:7)
│ ├──[+] schemas (19124:7)
│ ├──[+] schemas (6749:7)
│ ├──[+] schemas (3761:7)
│ ├──[+] schemas (6463:7)
│ ├──[+] schemas (184:7)
│ ├──[+] schemas (7513:7)
│ ├──[+] schemas (2446:7)
│ ├──[+] schemas (13179:7)
│ ├──[+] schemas (13007:7)
│ ├──[+] schemas (19550:7)
│ ├──[+] schemas (12733:7)
│ ├──[+] schemas (2422:7)
│ ├──[+] schemas (10246:7)
│ ├──[+] schemas (19383:7)
│ ├──[+] schemas (3611:7)
│ ├──[+] schemas (14411:7)
│ ├──[+] schemas (6159:7)
│ ├──[+] schemas (8395:7)
│ ├──[+] schemas (11006:7)
│ ├──[+] schemas (10213:7)
│ ├──[+] schemas (21211:7)
│ ├──[+] schemas (8284:7)
│ ├──[+] schemas (9976:7)
│ ├──[+] schemas (12952:7)
│ ├──[+] schemas (13591:7)
│ ├──[+] schemas (4158:7)
│ ├──[+] schemas (19497:7)
│ ├──[+] schemas (3851:7)
│ ├──[+] schemas (13684:7)
│ ├──[+] schemas (17043:7)
│ ├──[+] schemas (8960:7)
│ ├──[+] schemas (19890:7)
│ ├──[+] schemas (5444:7)
│ ├──[+] schemas (2183:7)
│ ├──[+] schemas (8376:7)
│ ├──[+] schemas (19906:7)
│ ├──[+] schemas (20585:7)
│ ├──[+] schemas (7931:7)
│ ├──[+] schemas (16914:7)
│ ├──[+] schemas (20374:7)
│ ├──[+] schemas (6167:7)
│ ├──[+] schemas (13999:7)
│ ├──[+] schemas (6176:7)
│ ├──[+] schemas (15161:7)
│ ├──[+] schemas (19567:7)
│ ├──[+] schemas (20:7)
│ ├──[+] schemas (8125:7)
│ ├──[+] schemas (6138:7)
│ ├──[+] schemas (6223:7)
│ ├──[+] schemas (19362:7)
│ ├──[+] schemas (20631:7)
│ ├──[+] schemas (6396:7)
│ ├──[+] schemas (8049:7)
│ ├──[+] schemas (19961:7)
│ ├──[+] schemas (17052:7)
│ ├──[+] schemas (15714:7)
│ ├──[+] schemas (202:7)
│ ├──[+] schemas (8875:7)
│ ├──[+] schemas (5293:7)
│ ├──[+] schemas (12246:7)
│ ├──[+] schemas (6856:7)
│ ├──[+] schemas (8934:7)
│ ├──[+] schemas (19583:7)
│ ├──[+] schemas (2414:7)
│ ├──[+] schemas (3642:7)
│ ├──[+] schemas (6379:7)
│ ├──[+] schemas (15236:7)
│ ├──[+] schemas (16435:7)
│ ├──[+] schemas (7245:7)
│ ├──[+] schemas (20032:7)
│ ├──[+] schemas (12038:7)
│ ├──[+] schemas (18408:7)
│ ├──[+] schemas (19516:7)
│ ├──[+] schemas (21227:7)
│ ├──[+] schemas (2360:7)
│ ├──[+] schemas (15200:7)
│ ├──[+] schemas (2238:7)
│ ├──[+] schemas (6830:7)
│ ├──[+] schemas (16878:7)
│ ├──[+] schemas (10332:7)
│ ├──[+] schemas (3623:7)
│ ├──[+] schemas (19485:7)
│ ├──[+] schemas (3689:7)
│ ├──[+] schemas (2377:7)
│ ├──[+] schemas (19425:7)
│ ├──[+] schemas (17163:7)
│ ├──[+] schemas (21473:7)
│ ├──[+] schemas (12631:7)
│ ├──[+] schemas (2297:7)
│ ├──[+] schemas (146:7)
│ ├──[+] schemas (163:7)
│ ├──[+] schemas (6200:7)
│ ├──[+] schemas (13387:7)
│ ├──[+] schemas (3732:7)
│ ├──[+] schemas (8016:7)
│ ├──[+] schemas (7044:7)
│ ├──[+] schemas (20049:7)
│ ├──[+] schemas (7121:7)
│ ├──[+] schemas (8992:7)
│ ├──[+] schemas (12473:7)
│ ├──[+] schemas (7221:7)
│ ├──[+] schemas (15566:7)
│ ├──[+] schemas (6126:7)
│ ├──[+] schemas (13281:7)
│ ├──[+] schemas (20417:7)
│ ├──[+] schemas (21170:7)
│ ├──[+] schemas (12524:7)
│ ├──[+] schemas (13879:7)
│ ├──[+] schemas (10510:7)
│ ├──[+] schemas (326:7)
│ ├──[+] schemas (3588:7)
│ ├──[+] schemas (7397:7)
│ ├──[+] schemas (8217:7)
│ ├──[+] schemas (18352:7)
│ ├──[+] schemas (2267:7)
│ ├──[+] schemas (6362:7)
│ ├──[+] schemas (21183:7)
│ ├──[+] schemas (13781:7)
│ ├──[+] schemas (12846:7)
│ ├──[+] schemas (13488:7)
│ ├──[+] schemas (12318:7)
│ ├──[+] schemas (3601:7)
│ ├──[+] schemas (17263:7)
│ ├──[+] schemas (2337:7)
│ ├──[+] schemas (14313:7)
│ ├──[+] schemas (6441:7)
│ ├──[+] schemas (15455:7)
│ ├──[+] schemas (19940:7)
│ ├──[+] schemas (19135:7)
│ ├──[+] schemas (2742:7)
│ ├──[+] schemas (12056:7)
│ ├──[+] schemas (19402:7)
│ ├──[+] schemas (7059:7)
│ ├──[+] schemas (8185:7)
│ ├──[+] schemas (16944:7)
│ ├─┬ImageGenerationServerTool_OpenRouter
│ │ └──[🔀] example (9381:9)
│ ├─┬NotFoundResponse
│ │ ├──[+] properties (12493:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (12495:13)❌ 
│ │   └──[🔀] type (12497:17)❌ 
│ ├─┬BaseResponsesResult
│ │ └─┬output
│ │   └─┬Schema
│ │     ├──[+] oneOf (15911:7)
│ │     ├──[+] oneOf (15714:7)
│ │     ├──Discriminator
│ │     ├─┬ONEOF
│ │     │ └──[🔀] $ref (15763:9)❌ 
│ │     ├─┬ONEOF
│ │     │ └──[🔀] $ref (16049:9)❌ 
│ │     └─┬ONEOF
│ │       └──[🔀] $ref (15845:9)❌ 
│ ├─┬CreateWorkspaceResponse
│ │ └──[🔀] example (6960:9)
│ ├─┬Guardrail
│ │ ├──[🔀] example (9080:9)
│ │ ├──[+] properties (9126:9)
│ │ ├──[+] properties (9137:9)
│ │ ├──[+] properties (9163:9)
│ │ ├──[+] properties (9168:9)
│ │ ├──[+] properties (9173:9)
│ │ ├──[+] properties (9178:9)
│ │ ├─┬updated_at
│ │ │ ├──[+] format (9187:19)❌ 
│ │ │ ├──[🔀] description (9185:24)
│ │ │ ├──[-] nullable (6345:21)❌ 
│ │ │ └──[🔀] example (9186:20)
│ │ ├─┬workspace_id
│ │ │ ├──[+] items (9194:13)❌ 
│ │ │ ├──[🔀] type (9196:17)❌ 
│ │ │ ├──[🔀] description (9190:24)
│ │ │ ├──[+] nullable (9195:21)❌ 
│ │ │ └──[🔀] example (9192:13)
│ │ ├─┬created_at
│ │ │ ├──[+] items (9134:13)❌ 
│ │ │ ├──[🔀] type (9136:17)❌ 
│ │ │ ├──[🔀] description (9127:24)
│ │ │ ├──[+] nullable (9135:21)❌ 
│ │ │ └──[🔀] example (9130:13)
│ │ ├─┬name
│ │ │ ├──[🔀] type (9177:17)❌ 
│ │ │ ├──[🔀] description (9174:24)
│ │ │ ├──[+] nullable (9176:21)❌ 
│ │ │ └──[🔀] example (9175:20)
│ │ ├─┬ignored_models
│ │ │ ├──[-] items (6319:13)❌ 
│ │ │ ├──[🔀] type (9162:17)❌ 
│ │ │ ├──[🔀] description (9158:24)
│ │ │ ├──[🔀] example (9160:20)
│ │ │ └──[+] deprecated (9157:23)
│ │ ├─┬id
│ │ │ ├──[-] format (6312:19)❌ 
│ │ │ ├──[🔀] description (9152:24)
│ │ │ ├──[+] nullable (9154:21)❌ 
│ │ │ └──[🔀] example (9153:20)
│ │ ├─┬enforce_zdr
│ │ │ ├──[🔀] type (9150:17)❌ 
│ │ │ ├──[🔀] description (9148:24)
│ │ │ ├──[-] nullable (6307:21)❌ 
│ │ │ └──[🔀] example (9149:20)
│ │ ├─┬reset_interval
│ │ │ └──[🔀] $ref (9179:11)❌ 
│ │ ├─┬limit_usd
│ │ │ ├──[🔀] type (9172:17)❌ 
│ │ │ ├──[-] format (6333:19)❌ 
│ │ │ ├──[🔀] description (9169:24)
│ │ │ └──[🔀] example (9170:20)
│ │ ├─┬description
│ │ │ ├──[+] items (9144:13)❌ 
│ │ │ ├──[🔀] type (9146:17)❌ 
│ │ │ ├──[🔀] description (9138:24)
│ │ │ └──[🔀] example (9140:13)
│ │ └─┬ignored_providers
│ │   ├──[-] items (6327:13)❌ 
│ │   ├──[🔀] type (9167:17)❌ 
│ │   ├──[🔀] description (9164:24)
│ │   └──[🔀] example (9165:20)
│ ├─┬ChatResult
│ │ ├──[+] properties (5254:9)
│ │ ├─┬usage
│ │ │ └──[🔀] $ref (5262:11)❌ 
│ │ ├─┬system_fingerprint
│ │ │ ├──[🔀] description (5257:24)
│ │ │ └──[🔀] example (5258:20)
│ │ └─┬service_tier
│ │   └──[🔀] $ref (15047:9)❌ 
│ ├─┬MessagesResult
│ │ ├──[🔀] example (11772:9)
│ │ └─┬ALLOF
│ │   ├──[+] properties (11734:13)
│ │   ├─┬provider
│ │   │ └──[🔀] $ref (15047:9)❌ 
│ │   └─┬usage
│ │     └──[🔀] $ref (17173:9)❌ 
│ ├─┬AnthropicDocumentBlock
│ │ └──[-] required (854:11)❌ 
│ ├─┬OutputApplyPatchServerToolItem
│ │ ├──[🔀] description (15271:20)
│ │ ├──[🔀] example (15274:9)
│ │ ├──[+] properties (15286:9)
│ │ ├──[-] properties (9638:9)❌ 
│ │ ├──[+] properties (15290:9)
│ │ └──[-] properties (9642:9)❌ 
│ ├─┬OutputItemFunctionCall
│ │ ├──[+] properties (15886:9)
│ │ ├─┬status
│ │ │ ├──[+] type (15888:17)❌ 
│ │ │ ├──[+] description (15887:24)
│ │ │ ├──[-] anyOf (10061:15)❌ 
│ │ │ ├──[-] anyOf (10064:15)❌ 
│ │ │ └──[-] anyOf (10067:15)❌ 
│ │ └─┬type
│ │   ├──[-] enum (10072:15)❌ 
│ │   ├──[-] type (10073:17)❌ 
│ │   ├──[+] anyOf (15891:15)
│ │   ├──[+] anyOf (15894:15)
│ │   └──[+] anyOf (15897:15)
│ ├─┬OutputWebSearchServerToolItem
│ │ ├──[🔀] example (16567:9)
│ │ ├──[+] properties (16574:9)
│ │ ├─┬status
│ │ │ └──[🔀] $ref (16603:11)❌ 
│ │ ├─┬type
│ │ │ └──[🔀] $ref (20165:9)❌ 
│ │ └─┬id
│ │   ├──[+] required (16599:15)❌ 
│ │   ├──[+] required (16600:15)❌ 
│ │   ├──[🔀] type (16601:17)❌ 
│ │   ├──[+] description (16575:24)
│ │   ├──[+] properties (16578:13)
│ │   ├──[+] properties (16580:13)
│ │   └──[+] properties (16594:13)
│ ├─┬GetWorkspaceResponse
│ │ └──[🔀] example (9013:9)
│ ├─┬AnthropicCacheControlDirective
│ │ └──[+] description (501:20)
│ ├─┬EdgeNetworkTimeoutResponse
│ │ ├──[+] properties (7349:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (7351:13)❌ 
│ │   └──[🔀] type (7353:17)❌ 
│ ├─┬RequestTimeoutResponse
│ │ ├──[+] properties (18754:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (18756:13)❌ 
│ │   └──[🔀] type (18758:17)❌ 
│ ├─┬ListGuardrailsResponse
│ │ └──[🔀] example (10122:9)
│ ├─┬ChatStreamChunk
│ │ ├──[+] properties (5383:9)
│ │ ├─┬usage
│ │ │ └──[🔀] $ref (5391:11)❌ 
│ │ ├─┬service_tier
│ │ │ └──[🔀] $ref (15047:9)❌ 
│ │ └─┬system_fingerprint
│ │   ├──[🔀] description (5386:24)
│ │   ├──[+] nullable (5388:21)❌ 
│ │   └──[🔀] example (5387:20)
│ ├─┬TooManyRequestsResponse
│ │ ├──[+] properties (20212:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (20214:13)❌ 
│ │   └──[🔀] type (20216:17)❌ 
│ ├─┬Preview_20250311_WebSearchServerTool
│ │ └─┬max_results
│ │   └──[🔀] description (17094:24)
│ ├─┬ChatRequest
│ │ ├──[+] properties (4992:9)
│ │ ├──[+] properties (5079:9)
│ │ ├──[+] properties (5094:9)
│ │ ├──[+] properties (5155:9)
│ │ ├──[+] properties (5182:9)
│ │ ├──[+] properties (5189:9)
│ │ ├─┬tool_choice
│ │ │ └──[🔀] $ref (19485:20)❌ 
│ │ ├─┬models
│ │ │ └──[🔀] $ref (12314:20)❌ 
│ │ ├─┬model
│ │ │ └──[🔀] $ref (5000:11)❌ 
│ │ ├─┬stream_options
│ │ │ └──[🔀] $ref (5140:11)❌ 
│ │ ├─┬stop
│ │ │ ├──[+] type (5125:17)❌ 
│ │ │ ├──[🔀] description (5122:24)
│ │ │ ├──[+] nullable (5124:21)❌ 
│ │ │ ├──[🔀] example (5123:20)
│ │ │ ├──[-] anyOf (3949:15)❌ 
│ │ │ ├──[-] anyOf (3950:15)❌ 
│ │ │ └──[-] anyOf (3954:15)❌ 
│ │ ├─┬seed
│ │ │ ├──[🔀] type (5100:17)❌ 
│ │ │ ├──[+] format (5098:19)❌ 
│ │ │ ├──[🔀] description (5095:24)
│ │ │ └──[🔀] example (5097:20)
│ │ ├─┬parallel_tool_calls
│ │ │ └──[🔀] $ref (4876:20)❌ 
│ │ ├─┬response_format
│ │ │ ├──[-] discriminator (3907:13)❌ 
│ │ │ ├──[+] type (5078:17)❌ 
│ │ │ ├──[🔀] description (5057:24)
│ │ │ ├──[🔀] example (5059:13)
│ │ │ ├──[+] properties (5062:13)
│ │ │ ├──[+] properties (5076:13)
│ │ │ ├──[-] oneOf (3553:7)❌ 
│ │ │ ├──[-] oneOf (5613:7)❌ 
│ │ │ ├──[-] oneOf (3517:7)❌ 
│ │ │ ├──[-] oneOf (3499:7)❌ 
│ │ │ └──[-] oneOf (3541:7)❌ 
│ │ ├─┬trace
│ │ │ └──[🔀] $ref (5659:9)❌ 
│ │ ├─┬presence_penalty
│ │ │ ├──[+] items (5025:13)❌ 
│ │ │ ├──[🔀] type (5047:17)❌ 
│ │ │ ├──[-] format (3876:19)❌ 
│ │ │ ├──[🔀] description (5023:24)
│ │ │ ├──[-] nullable (3877:21)❌ 
│ │ │ └──[-] example (3875:20)
│ │ ├─┬temperature
│ │ │ ├──[-] type (3970:17)❌ 
│ │ │ ├──[-] format (3968:19)❌ 
│ │ │ ├──[🔀] description (5152:24)
│ │ │ ├──[-] nullable (3969:21)❌ 
│ │ │ ├──[🔀] example (5154:13)
│ │ │ ├──[+] anyOf (5146:15)
│ │ │ ├──[+] anyOf (5147:15)
│ │ │ └──[+] anyOf (5151:15)
│ │ ├─┬session_id
│ │ │ └──[🔀] description (5140:24)
│ │ ├─┬top_logprobs
│ │ │ └──[🔀] $ref (5463:20)❌ 
│ │ ├─┬stream
│ │ │ ├──[+] enum (5129:15)
│ │ │ ├──[+] enum (5130:15)
│ │ │ ├──[+] enum (5131:15)
│ │ │ ├──[+] enum (5132:15)
│ │ │ ├──[+] enum (5133:15)
│ │ │ ├──[+] enum (5134:15)
│ │ │ ├──[🔀] type (5137:17)❌ 
│ │ │ ├──[🔀] description (5127:24)
│ │ │ ├──[-] default (3959:20)❌ 
│ │ │ ├──[+] nullable (5136:21)❌ 
│ │ │ ├──[🔀] example (5135:20)
│ │ │ └─┬Extensions
│ │ │   └──[+] x-speakeasy-unknown-values (5138:39)
│ │ ├─┬top_p
│ │ │ ├──[🔀] description (5165:24)
│ │ │ └──[🔀] example (5166:20)
│ │ ├─┬cache_control
│ │ │ └──[🔀] $ref (501:20)❌ 
│ │ ├─┬user
│ │ │ ├──[+] items (5180:13)❌ 
│ │ │ ├──[🔀] type (5181:17)❌ 
│ │ │ ├──[🔀] description (5173:24)
│ │ │ └──[🔀] example (5175:13)
│ │ ├─┬route
│ │ │ └──[🔀] $ref (5080:11)❌ 
│ │ ├─┬modalities
│ │ │ ├──[-] items (3834:13)❌ 
│ │ │ ├──[🔀] type (4998:17)❌ 
│ │ │ ├──[+] format (4996:19)❌ 
│ │ │ ├──[🔀] description (4993:24)
│ │ │ ├──[+] nullable (4997:21)❌ 
│ │ │ └──[🔀] example (4995:20)
│ │ ├─┬provider
│ │ │ └──[🔀] $ref (5049:11)❌ 
│ │ ├─┬service_tier
│ │ │ ├──[-] enum (3932:15)❌ 
│ │ │ ├──[-] enum (3933:15)❌ 
│ │ │ ├──[-] enum (3934:15)❌ 
│ │ │ ├──[-] enum (3935:15)❌ 
│ │ │ ├──[-] enum (3936:15)❌ 
│ │ │ ├──[-] enum (3937:15)❌ 
│ │ │ ├──[+] discriminator (5104:13)❌ 
│ │ │ ├──[-] type (3940:17)❌ 
│ │ │ ├──[🔀] description (5102:24)
│ │ │ ├──[-] nullable (3939:21)❌ 
│ │ │ ├──[🔀] example (5112:13)
│ │ │ ├──[+] oneOf (4716:7)
│ │ │ ├──[+] oneOf (7732:7)
│ │ │ ├──[+] oneOf (4680:7)
│ │ │ ├──[+] oneOf (4662:7)
│ │ │ ├──[+] oneOf (4704:7)
│ │ │ └─┬Extensions
│ │ │   └──[-] x-speakeasy-unknown-values (3941:39)❌ 
│ │ ├─┬tools
│ │ │ ├──[-] items (3981:13)❌ 
│ │ │ ├──[🔀] type (5161:17)❌ 
│ │ │ ├──[🔀] description (5159:24)
│ │ │ ├──[+] default (5158:20)❌ 
│ │ │ └──[🔀] example (5160:20)
│ │ ├─┬reasoning
│ │ │ └──[🔀] $ref (17770:29)❌ 
│ │ └─┬plugins
│ │   ├──[-] items (3854:13)❌ 
│ │   ├──[🔀] type (5021:17)❌ 
│ │   ├──[🔀] description (5017:24)
│ │   ├──[+] nullable (5020:21)❌ 
│ │   └──[+] example (5019:20)
│ ├─┬Model
│ │ ├──[+] required (12179:11)❌ 
│ │ ├──[🔀] example (12066:9)
│ │ ├──[+] properties (12103:9)
│ │ ├──[+] properties (12158:9)
│ │ ├─┬created
│ │ │ ├──[🔀] description (12110:24)
│ │ │ ├──[+] nullable (12112:21)❌ 
│ │ │ └──[🔀] example (12111:20)
│ │ ├─┬name
│ │ │ └──[🔀] $ref (12302:20)❌ 
│ │ ├─┬top_provider
│ │ │ └──[🔀] $ref (12154:11)❌ 
│ │ ├─┬id
│ │ │ ├──[🔀] description (12130:24)
│ │ │ ├──[+] nullable (12132:21)❌ 
│ │ │ └──[🔀] example (12131:20)
│ │ ├─┬hugging_face_id
│ │ │ ├──[🔀] description (12125:24)
│ │ │ └──[🔀] example (12126:20)
│ │ ├─┬default_parameters
│ │ │ └──[🔀] $ref (12115:11)❌ 
│ │ ├─┬description
│ │ │ └──[🔀] $ref (7185:29)❌ 
│ │ ├─┬context_length
│ │ │ ├──[🔀] type (12108:17)❌ 
│ │ │ ├──[🔀] description (12106:24)
│ │ │ ├──[-] nullable (8699:21)❌ 
│ │ │ └──[🔀] example (12107:20)
│ │ ├─┬knowledge_cutoff
│ │ │ ├──[🔀] description (12135:24)
│ │ │ ├──[-] nullable (8728:21)❌ 
│ │ │ └──[🔀] example (12136:20)
│ │ ├─┬per_request_limits
│ │ │ └──[🔀] $ref (12146:11)❌ 
│ │ ├─┬pricing
│ │ │ └──[🔀] $ref (16859:20)❌ 
│ │ ├─┬expiration_date
│ │ │ ├──[🔀] description (12121:24)
│ │ │ ├──[-] nullable (8714:21)❌ 
│ │ │ └──[🔀] example (12122:20)
│ │ ├─┬supported_parameters
│ │ │ └──[🔀] $ref (18271:20)❌ 
│ │ ├─┬links
│ │ │ └──[🔀] $ref (12139:11)❌ 
│ │ └─┬canonical_slug
│ │   └──[🔀] $ref (12246:20)❌ 
│ ├─┬Preview_WebSearchServerTool
│ │ └─┬max_results
│ │   └──[🔀] description (17119:24)
│ ├─┬CreateGuardrailRequest
│ │ ├──[🔀] example (6576:9)
│ │ ├──[+] properties (6618:9)
│ │ ├──[+] properties (6628:9)
│ │ ├──[+] properties (6651:9)
│ │ ├──[+] properties (6656:9)
│ │ ├──[+] properties (6661:9)
│ │ ├──[+] properties (6666:9)
│ │ ├─┬description
│ │ │ ├──[+] items (6625:13)❌ 
│ │ │ ├──[🔀] type (6627:17)❌ 
│ │ │ ├──[-] maxLength (4994:22)❌ 
│ │ │ ├──[🔀] description (6619:24)
│ │ │ └──[🔀] example (6622:13)
│ │ ├─┬ignored_models
│ │ │ ├──[-] items (5007:13)❌ 
│ │ │ ├──[🔀] type (6643:17)❌ 
│ │ │ ├──[+] maxLength (6641:22)❌ 
│ │ │ ├──[-] minItems (5008:21)❌ 
│ │ │ ├──[🔀] description (6639:24)
│ │ │ └──[🔀] example (6640:20)
│ │ ├─┬reset_interval
│ │ │ └──[🔀] $ref (6662:11)❌ 
│ │ ├─┬workspace_id
│ │ │ ├──[🔀] type (6671:17)❌ 
│ │ │ ├──[-] format (5037:19)❌ 
│ │ │ ├──[🔀] description (6667:24)
│ │ │ ├──[+] nullable (6670:21)❌ 
│ │ │ └──[🔀] example (6669:20)
│ │ ├─┬enforce_zdr
│ │ │ ├──[+] items (6635:13)❌ 
│ │ │ ├──[🔀] type (6637:17)❌ 
│ │ │ ├──[🔀] description (6629:24)
│ │ │ └──[🔀] example (6631:13)
│ │ ├─┬ignored_providers
│ │ │ ├──[-] items (5016:13)❌ 
│ │ │ ├──[🔀] type (6650:17)❌ 
│ │ │ ├──[-] minItems (5017:21)❌ 
│ │ │ ├──[🔀] description (6646:24)
│ │ │ ├──[🔀] example (6648:20)
│ │ │ └──[+] deprecated (6645:23)
│ │ ├─┬name
│ │ │ ├──[🔀] type (6660:17)❌ 
│ │ │ ├──[-] maxLength (5029:22)❌ 
│ │ │ ├──[-] minLength (5030:22)❌ 
│ │ │ ├──[🔀] description (6657:24)
│ │ │ ├──[+] nullable (6659:21)❌ 
│ │ │ └──[🔀] example (6658:20)
│ │ └─┬limit_usd
│ │   ├──[🔀] type (6655:17)❌ 
│ │   ├──[-] format (5023:19)❌ 
│ │   ├──[🔀] description (6652:24)
│ │   └──[🔀] example (6653:20)
│ ├─┬WebSearchConfig
│ │ ├──[+] properties (21305:9)
│ │ ├─┬max_total_results
│ │ │ ├──[🔀] description (21316:24)
│ │ │ └──[🔀] example (21318:20)
│ │ ├─┬allowed_domains
│ │ │ └──[🔀] description (21292:24)
│ │ ├─┬search_context_size
│ │ │ └──[🔀] $ref (21316:11)❌ 
│ │ ├─┬excluded_domains
│ │ │ └──[🔀] description (21300:24)
│ │ ├─┬user_location
│ │ │ └──[🔀] $ref (19205:20)❌ 
│ │ └─┬max_results
│ │   ├──[🔀] description (21306:24)
│ │   └──[🔀] example (21308:20)
│ ├─┬SpeechRequest
│ │ └─┬provider
│ │   └─┬options
│ │     └──[🔀] $ref (17263:20)❌ 
│ ├─┬PayloadTooLargeResponse
│ │ ├──[+] properties (16677:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (16679:13)❌ 
│ │   └──[🔀] type (16681:17)❌ 
│ ├─┬ChatToolChoice
│ │ └──[+] anyOf (5293:7)
│ ├─┬AnthropicMessageUsageIteration
│ │ └─┬ALLOF
│ │   ├──[+] properties (1232:13)
│ │   └─┬type
│ │     └──[-] enum (1030:19)❌ 
│ ├─┬BaseInputs
│ │ └─┬ANYOF
│ │   └─┬Schema
│ │     ├──[+] anyOf (14411:7)
│ │     ├──[+] anyOf (14442:7)
│ │     ├──[+] anyOf (2183:7)
│ │     └──[+] anyOf (2297:7)
│ ├─┬GenerationResponse
│ │ ├──[🔀] example (8555:9)
│ │ └─┬data
│ │   ├──[+] required (8856:15)❌ 
│ │   ├──[+] required (8844:15)❌ 
│ │   ├──[+] required (8869:15)❌ 
│ │   ├──[+] required (8864:15)❌ 
│ │   ├──[+] properties (8633:13)
│ │   ├──[+] properties (8715:13)
│ │   ├──[+] properties (8744:13)
│ │   ├──[+] properties (8765:13)
│ │   ├──[+] properties (8774:13)
│ │   ├─┬request_id
│ │   │ ├──[🔀] description (8745:28)
│ │   │ └──[🔀] example (8746:24)
│ │   ├─┬tokens_completion
│ │   │ ├──[🔀] type (8768:21)❌ 
│ │   │ ├──[🔀] description (8766:28)
│ │   │ └──[-] example (6089:24)
│ │   ├─┬is_byok
│ │   │ ├──[🔀] type (8664:21)❌ 
│ │   │ ├──[🔀] description (8662:28)
│ │   │ └──[🔀] example (8663:24)
│ │   ├─┬native_tokens_prompt
│ │   │ ├──[🔀] description (8701:28)
│ │   │ └──[🔀] example (8702:24)
│ │   ├─┬moderation_latency
│ │   │ ├──[🔀] type (8678:21)❌ 
│ │   │ ├──[-] format (6000:23)❌ 
│ │   │ ├──[🔀] description (8676:28)
│ │   │ ├──[-] nullable (6001:25)❌ 
│ │   │ └──[🔀] example (8677:24)
│ │   ├─┬user_agent
│ │   │ ├──[🔀] type (8797:21)❌ 
│ │   │ ├──[🔀] description (8794:28)
│ │   │ └──[+] example (8795:24)
│ │   ├─┬latency
│ │   │ ├──[🔀] type (8668:21)❌ 
│ │   │ ├──[-] format (5990:23)❌ 
│ │   │ ├──[🔀] description (8666:28)
│ │   │ ├──[-] nullable (5991:25)❌ 
│ │   │ └──[🔀] example (8667:24)
│ │   ├─┬web_search_engine
│ │   │ ├──[🔀] type (8802:21)❌ 
│ │   │ ├──[+] format (8801:23)❌ 
│ │   │ ├──[🔀] description (8799:28)
│ │   │ ├──[-] nullable (6125:25)❌ 
│ │   │ └──[🔀] example (8800:24)
│ │   ├─┬provider_responses
│ │   │ ├──[-] items (6065:17)❌ 
│ │   │ ├──[🔀] type (8743:21)❌ 
│ │   │ ├──[🔀] description (8741:28)
│ │   │ ├──[-] nullable (6066:25)❌ 
│ │   │ └──[+] example (8742:24)
│ │   ├─┬total_cost
│ │   │ ├──[🔀] type (8778:21)❌ 
│ │   │ ├──[-] format (6100:23)❌ 
│ │   │ ├──[🔀] description (8775:28)
│ │   │ ├──[+] nullable (8777:25)❌ 
│ │   │ └──[🔀] example (8776:24)
│ │   ├─┬usage
│ │   │ ├──[🔀] type (8792:21)❌ 
│ │   │ ├──[-] format (6116:23)❌ 
│ │   │ ├──[🔀] description (8789:28)
│ │   │ ├──[+] nullable (8791:25)❌ 
│ │   │ └──[🔀] example (8790:24)
│ │   ├─┬native_tokens_completion
│ │   │ ├──[🔀] description (8691:28)
│ │   │ └──[🔀] example (8692:24)
│ │   ├─┬upstream_inference_cost
│ │   │ ├──[🔀] type (8787:21)❌ 
│ │   │ ├──[-] format (6110:23)❌ 
│ │   │ ├──[🔀] description (8784:28)
│ │   │ └──[🔀] example (8785:24)
│ │   ├─┬num_search_results
│ │   │ ├──[🔀] description (8726:28)
│ │   │ └──[🔀] example (8727:24)
│ │   ├─┬id
│ │   │ ├──[🔀] description (8658:28)
│ │   │ ├──[+] nullable (8659:25)❌ 
│ │   │ └──[-] example (5981:24)
│ │   ├─┬provider_name
│ │   │ ├──[🔀] type (8739:21)❌ 
│ │   │ ├──[🔀] description (8736:28)
│ │   │ └──[🔀] example (8737:24)
│ │   ├─┬router
│ │   │ ├──[🔀] description (8750:28)
│ │   │ └──[🔀] example (8751:24)
│ │   ├─┬model
│ │   │ ├──[🔀] type (8674:21)❌ 
│ │   │ ├──[+] format (8672:23)❌ 
│ │   │ ├──[🔀] description (8670:28)
│ │   │ ├──[+] nullable (8673:25)❌ 
│ │   │ └──[🔀] example (8671:24)
│ │   ├─┬native_tokens_reasoning
│ │   │ ├──[🔀] description (8706:28)
│ │   │ └──[🔀] example (8707:24)
│ │   ├─┬generation_time
│ │   │ ├──[🔀] type (8650:21)❌ 
│ │   │ ├──[-] format (5972:23)❌ 
│ │   │ ├──[🔀] description (8647:28)
│ │   │ └──[🔀] example (8648:24)
│ │   ├─┬external_user
│ │   │ ├──[+] enum (8636:19)
│ │   │ ├──[+] enum (8637:19)
│ │   │ ├──[🔀] description (8634:28)
│ │   │ ├──[-] nullable (5962:25)❌ 
│ │   │ ├──[🔀] example (8638:24)
│ │   │ └─┬Extensions
│ │   │   └──[+] x-speakeasy-unknown-values (8640:43)
│ │   ├─┬streamed
│ │   │ ├──[🔀] type (8764:21)❌ 
│ │   │ ├──[🔀] description (8761:28)
│ │   │ └──[🔀] example (8762:24)
│ │   ├─┬native_tokens_completion_images
│ │   │ ├──[🔀] description (8696:28)
│ │   │ └──[🔀] example (8697:24)
│ │   ├─┬session_id
│ │   │ ├──[+] items (8757:17)❌ 
│ │   │ ├──[🔀] type (8759:21)❌ 
│ │   │ └──[🔀] description (8755:28)
│ │   ├─┬num_media_completion
│ │   │ └──[🔀] description (8716:28)
│ │   ├─┬tokens_prompt
│ │   │ ├──[🔀] type (8773:21)❌ 
│ │   │ ├──[🔀] description (8770:28)
│ │   │ └──[🔀] example (8771:24)
│ │   ├─┬finish_reason
│ │   │ ├──[🔀] description (8642:28)
│ │   │ └──[🔀] example (8643:24)
│ │   ├─┬num_media_prompt
│ │   │ ├──[🔀] description (8721:28)
│ │   │ └──[🔀] example (8722:24)
│ │   ├─┬api_type
│ │   │ ├──[+] enum (8606:19)
│ │   │ └──[+] enum (8608:19)
│ │   ├─┬http_referer
│ │   │ ├──[🔀] type (8656:21)❌ 
│ │   │ ├──[+] format (8654:23)❌ 
│ │   │ ├──[🔀] description (8652:28)
│ │   │ └──[+] example (8653:24)
│ │   ├─┬origin
│ │   │ ├──[🔀] type (8734:21)❌ 
│ │   │ ├──[🔀] description (8731:28)
│ │   │ ├──[+] nullable (8733:25)❌ 
│ │   │ └──[🔀] example (8732:24)
│ │   ├─┬native_tokens_cached
│ │   │ ├──[🔀] type (8689:21)❌ 
│ │   │ ├──[🔀] description (8686:28)
│ │   │ └──[🔀] example (8687:24)
│ │   ├─┬upstream_id
│ │   │ ├──[🔀] description (8780:28)
│ │   │ └──[-] example (6104:24)
│ │   ├─┬num_input_audio_prompt
│ │   │ ├──[🔀] description (8711:28)
│ │   │ └──[🔀] example (8712:24)
│ │   └─┬native_finish_reason
│ │     ├──[🔀] type (8684:21)❌ 
│ │     ├──[+] format (8682:23)❌ 
│ │     ├──[🔀] description (8680:28)
│ │     └──[🔀] example (8681:24)
│ ├─┬VideoGenerationRequest
│ │ ├──[+] properties (20844:9)
│ │ ├─┬input_references
│ │ │ ├──[🔀] description (20867:24)
│ │ │ └─┬Schema
│ │ │   └──[🔀] $ref (9647:20)❌ 
│ │ ├─┬duration
│ │ │ ├──[🔀] type (20849:17)❌ 
│ │ │ ├──[-] minimum (13655:20)❌ 
│ │ │ ├──[+] format (20848:19)❌ 
│ │ │ ├──[🔀] description (20845:24)
│ │ │ └──[🔀] example (20847:20)
│ │ ├─┬generate_audio
│ │ │ ├──[+] items (20859:13)❌ 
│ │ │ ├──[🔀] type (20860:17)❌ 
│ │ │ ├──[🔀] description (20856:24)
│ │ │ └──[-] example (13666:20)
│ │ ├─┬model
│ │ │ ├──[+] items (20870:13)❌ 
│ │ │ ├──[🔀] type (20871:17)❌ 
│ │ │ └──[+] description (20867:24)
│ │ ├─┬aspect_ratio
│ │ │ ├──[+] enum (20837:15)
│ │ │ └──[+] enum (20838:15)
│ │ ├─┬frame_images
│ │ │ ├──[-] items (13661:13)❌ 
│ │ │ ├──[🔀] type (20854:17)❌ 
│ │ │ ├──[+] minimum (20853:20)❌ 
│ │ │ ├──[🔀] description (20851:24)
│ │ │ └──[+] example (20852:20)
│ │ ├─┬resolution
│ │ │ ├──[-] enum (14126:15)❌ 
│ │ │ ├──[-] enum (14121:15)❌ 
│ │ │ ├──[-] enum (14122:15)❌ 
│ │ │ ├──[-] enum (14123:15)❌ 
│ │ │ ├──[-] enum (14124:15)❌ 
│ │ │ ├──[-] enum (14125:15)❌ 
│ │ │ ├──[🔀] type (20886:17)❌ 
│ │ │ ├──[🔀] description (20877:24)
│ │ │ ├──[-] example (14127:20)
│ │ │ ├──[+] properties (20879:13)
│ │ │ └─┬Extensions
│ │ │   └──[-] x-speakeasy-unknown-values (14129:39)❌ 
│ │ ├─┬seed
│ │ │ ├──[+] enum (20894:15)
│ │ │ ├──[+] enum (20895:15)
│ │ │ ├──[+] enum (20890:15)
│ │ │ ├──[+] enum (20891:15)
│ │ │ ├──[+] enum (20892:15)
│ │ │ ├──[+] enum (20893:15)
│ │ │ ├──[🔀] type (20897:17)❌ 
│ │ │ ├──[🔀] description (20888:24)
│ │ │ ├──[+] example (20896:20)
│ │ │ └─┬Extensions
│ │ │   └──[+] x-speakeasy-unknown-values (20898:39)
│ │ ├─┬provider
│ │ │ └─┬options
│ │ │   ├──[-] type (14116:21)❌ 
│ │ │   ├──[-] description (13681:28)
│ │ │   ├──[-] example (13684:17)
│ │ │   ├──[-] properties (13688:17)❌ 
│ │ │   ├──[-] properties (13692:17)❌ 
│ │ │   ├──[-] properties (13696:17)❌ 
│ │ │   ├──[-] properties (13700:17)❌ 
│ │ │   ├──[-] properties (13704:17)❌ 
│ │ │   ├──[-] properties (13708:17)❌ 
│ │ │   ├──[-] properties (13712:17)❌ 
│ │ │   ├──[-] properties (13716:17)❌ 
│ │ │   ├──[-] properties (13720:17)❌ 
│ │ │   ├──[-] properties (13724:17)❌ 
│ │ │   ├──[-] properties (13728:17)❌ 
│ │ │   ├──[-] properties (13732:17)❌ 
│ │ │   ├──[-] properties (13736:17)❌ 
│ │ │   ├──[-] properties (13740:17)❌ 
│ │ │   ├──[-] properties (13744:17)❌ 
│ │ │   ├──[-] properties (13748:17)❌ 
│ │ │   ├──[-] properties (13752:17)❌ 
│ │ │   ├──[-] properties (13756:17)❌ 
│ │ │   ├──[-] properties (13760:17)❌ 
│ │ │   ├──[-] properties (13764:17)❌ 
│ │ │   ├──[-] properties (13768:17)❌ 
│ │ │   ├──[-] properties (13772:17)❌ 
│ │ │   ├──[-] properties (13776:17)❌ 
│ │ │   ├──[-] properties (13780:17)❌ 
│ │ │   ├──[-] properties (13784:17)❌ 
│ │ │   ├──[-] properties (13788:17)❌ 
│ │ │   ├──[-] properties (13792:17)❌ 
│ │ │   ├──[-] properties (13796:17)❌ 
│ │ │   ├──[-] properties (13800:17)❌ 
│ │ │   ├──[-] properties (13804:17)❌ 
│ │ │   ├──[-] properties (13808:17)❌ 
│ │ │   ├──[-] properties (13812:17)❌ 
│ │ │   ├──[-] properties (13816:17)❌ 
│ │ │   ├──[-] properties (13820:17)❌ 
│ │ │   ├──[-] properties (13824:17)❌ 
│ │ │   ├──[-] properties (13828:17)❌ 
│ │ │   ├──[-] properties (13832:17)❌ 
│ │ │   ├──[-] properties (13836:17)❌ 
│ │ │   ├──[-] properties (13840:17)❌ 
│ │ │   ├──[-] properties (13844:17)❌ 
│ │ │   ├──[-] properties (13848:17)❌ 
│ │ │   ├──[-] properties (13852:17)❌ 
│ │ │   ├──[-] properties (13856:17)❌ 
│ │ │   ├──[-] properties (13860:17)❌ 
│ │ │   ├──[-] properties (13864:17)❌ 
│ │ │   ├──[-] properties (13868:17)❌ 
│ │ │   ├──[-] properties (13872:17)❌ 
│ │ │   ├──[-] properties (13876:17)❌ 
│ │ │   ├──[-] properties (13880:17)❌ 
│ │ │   ├──[-] properties (13884:17)❌ 
│ │ │   ├──[-] properties (13888:17)❌ 
│ │ │   ├──[-] properties (13892:17)❌ 
│ │ │   ├──[-] properties (13896:17)❌ 
│ │ │   ├──[-] properties (13900:17)❌ 
│ │ │   ├──[-] properties (13904:17)❌ 
│ │ │   ├──[-] properties (13908:17)❌ 
│ │ │   ├──[-] properties (13912:17)❌ 
│ │ │   ├──[-] properties (13916:17)❌ 
│ │ │   ├──[-] properties (13920:17)❌ 
│ │ │   ├──[-] properties (13924:17)❌ 
│ │ │   ├──[-] properties (13928:17)❌ 
│ │ │   ├──[-] properties (13932:17)❌ 
│ │ │   ├──[-] properties (13936:17)❌ 
│ │ │   ├──[-] properties (13940:17)❌ 
│ │ │   ├──[-] properties (13944:17)❌ 
│ │ │   ├──[-] properties (13948:17)❌ 
│ │ │   ├──[-] properties (13952:17)❌ 
│ │ │   ├──[-] properties (13956:17)❌ 
│ │ │   ├──[-] properties (13960:17)❌ 
│ │ │   ├──[-] properties (13964:17)❌ 
│ │ │   ├──[-] properties (13968:17)❌ 
│ │ │   ├──[-] properties (13972:17)❌ 
│ │ │   ├──[-] properties (13976:17)❌ 
│ │ │   ├──[-] properties (13980:17)❌ 
│ │ │   ├──[-] properties (13984:17)❌ 
│ │ │   ├──[-] properties (13988:17)❌ 
│ │ │   ├──[-] properties (13992:17)❌ 
│ │ │   ├──[-] properties (13996:17)❌ 
│ │ │   ├──[-] properties (14000:17)❌ 
│ │ │   ├──[-] properties (14004:17)❌ 
│ │ │   ├──[-] properties (14008:17)❌ 
│ │ │   ├──[-] properties (14012:17)❌ 
│ │ │   ├──[-] properties (14016:17)❌ 
│ │ │   ├──[-] properties (14020:17)❌ 
│ │ │   ├──[-] properties (14024:17)❌ 
│ │ │   ├──[-] properties (14028:17)❌ 
│ │ │   ├──[-] properties (14032:17)❌ 
│ │ │   ├──[-] properties (14036:17)❌ 
│ │ │   ├──[-] properties (14040:17)❌ 
│ │ │   ├──[-] properties (14044:17)❌ 
│ │ │   ├──[-] properties (14048:17)❌ 
│ │ │   ├──[-] properties (14052:17)❌ 
│ │ │   ├──[-] properties (14056:17)❌ 
│ │ │   ├──[-] properties (14060:17)❌ 
│ │ │   ├──[-] properties (14064:17)❌ 
│ │ │   ├──[-] properties (14068:17)❌ 
│ │ │   ├──[-] properties (14072:17)❌ 
│ │ │   ├──[-] properties (14076:17)❌ 
│ │ │   ├──[-] properties (14080:17)❌ 
│ │ │   ├──[-] properties (14084:17)❌ 
│ │ │   ├──[-] properties (14088:17)❌ 
│ │ │   ├──[-] properties (14092:17)❌ 
│ │ │   ├──[-] properties (14096:17)❌ 
│ │ │   ├──[-] properties (14100:17)❌ 
│ │ │   ├──[-] properties (14104:17)❌ 
│ │ │   ├──[-] properties (14108:17)❌ 
│ │ │   ├──[-] properties (14112:17)❌ 
│ │ │   ├──[+] allOf (17263:7)
│ │ │   └──[+] allOf (20882:19)
│ │ └─┬size
│ │   ├──[🔀] type (20902:17)❌ 
│ │   ├──[🔀] description (20900:24)
│ │   └──[-] example (14137:20)
│ ├─┬Legacy_WebSearchServerTool
│ │ └─┬max_results
│ │   └──[🔀] description (9960:24)
│ ├─┬ListWorkspacesResponse
│ │ └──[🔀] example (10300:9)
│ ├─┬OutputWebFetchServerToolItem
│ │ ├──[🔀] example (16524:9)
│ │ ├──[+] properties (16533:9)
│ │ ├──[+] properties (16536:9)
│ │ ├─┬id
│ │ │ └──[+] description (16534:24)
│ │ ├─┬status
│ │ │ └──[🔀] $ref (16537:11)❌ 
│ │ └─┬type
│ │   └──[🔀] $ref (20165:9)❌ 
│ ├─┬ServiceUnavailableResponse
│ │ ├──[+] properties (19235:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (19237:13)❌ 
│ │   └──[🔀] type (19239:17)❌ 
│ ├─┬MessagesRequest
│ │ ├──[+] properties (11363:9)
│ │ ├──[+] properties (11440:9)
│ │ ├─┬session_id
│ │ │ ├──[-] maxLength (8074:22)❌ 
│ │ │ └──[-] description (8072:24)
│ │ ├─┬speed
│ │ │ ├──[+] type (11429:17)❌ 
│ │ │ ├──[+] maxLength (11428:22)❌ 
│ │ │ ├──[+] description (11426:24)
│ │ │ ├──[-] allOf (1214:7)❌ 
│ │ │ └──[-] allOf (8079:15)❌ 
│ │ ├─┬plugins
│ │ │ └──[🔀] $ref (11195:20)❌ 
│ │ ├─┬thinking
│ │ │ ├──[+] anyOf (11446:15)
│ │ │ ├──[+] anyOf (11447:15)
│ │ │ ├──[-] oneOf (8099:15)❌ 
│ │ │ ├──[-] oneOf (8112:15)❌ 
│ │ │ └──[-] oneOf (8120:15)❌ 
│ │ ├─┬output_config
│ │ │ └──[🔀] $ref (11388:11)❌ 
│ │ ├─┬metadata
│ │ │ ├──[+] items (11376:13)❌ 
│ │ │ ├──[🔀] type (11378:17)❌ 
│ │ │ ├──[+] nullable (11377:21)❌ 
│ │ │ └──[-] properties (8027:13)❌ 
│ │ ├─┬model
│ │ │ ├──[🔀] type (11384:17)❌ 
│ │ │ └──[+] properties (11381:13)
│ │ ├─┬provider
│ │ │ └──[🔀] $ref (11394:11)❌ 
│ │ ├─┬service_tier
│ │ │ └──[🔀] $ref (7268:19)❌ 
│ │ ├─┬max_tokens
│ │ │ ├──[+] items (11369:13)❌ 
│ │ │ ├──[🔀] type (11371:17)❌ 
│ │ │ ├──[+] description (11364:24)
│ │ │ ├──[+] nullable (11370:21)❌ 
│ │ │ └──[+] example (11367:13)
│ │ ├─┬stream
│ │ │ ├──[+] items (11438:13)❌ 
│ │ │ └──[🔀] type (11439:17)❌ 
│ │ ├─┬top_p
│ │ │ ├──[+] items (11531:13)❌ 
│ │ │ ├──[🔀] type (11696:17)❌ 
│ │ │ └──[-] format (8313:19)❌ 
│ │ ├─┬tool_choice
│ │ │ ├──[+] type (11452:17)❌ 
│ │ │ ├──[+] format (11451:19)❌ 
│ │ │ ├──[-] oneOf (8132:15)❌ 
│ │ │ ├──[-] oneOf (8142:15)❌ 
│ │ │ ├──[-] oneOf (8152:15)❌ 
│ │ │ └──[-] oneOf (8160:15)❌ 
│ │ ├─┬temperature
│ │ │ ├──[🔀] type (11443:17)❌ 
│ │ │ └──[-] format (8095:19)❌ 
│ │ ├─┬user
│ │ │ ├──[🔀] type (11701:17)❌ 
│ │ │ ├──[-] maxLength (8320:22)❌ 
│ │ │ ├──[+] format (11700:19)❌ 
│ │ │ └──[-] description (8318:24)
│ │ ├─┬tools
│ │ │ └─┬Schema
│ │ │   ├──[+] anyOf (5277:7)
│ │ │   ├──[+] anyOf (21211:7)
│ │ │   ├──[+] anyOf (15095:7)
│ │ │   ├──[+] anyOf (11688:17)
│ │ │   ├─┬ANYOF
│ │ │   │ └─┬allowed_callers
│ │ │   │   └──[🔀] $ref (327:9)❌ 
│ │ │   ├─┬ANYOF
│ │ │   │ └──[🔀] $ref (11654:17)❌ 
│ │ │   ├─┬ANYOF
│ │ │   │ └──[🔀] $ref (3571:20)❌ 
│ │ │   ├─┬ANYOF
│ │ │   │ └──[🔀] $ref (7159:20)❌ 
│ │ │   └─┬ANYOF
│ │ │     └──[🔀] $ref (9379:20)❌ 
│ │ ├─┬system
│ │ │ └──[🔀] $ref (19485:20)❌ 
│ │ ├─┬trace
│ │ │ └──[🔀] $ref (11698:11)❌ 
│ │ ├─┬route
│ │ │ └──[🔀] $ref (17770:29)❌ 
│ │ ├─┬models
│ │ │ ├──[-] items (8035:13)❌ 
│ │ │ └──[🔀] type (11386:17)❌ 
│ │ ├─┬stop_sequences
│ │ │ ├──[-] items (8084:13)❌ 
│ │ │ ├──[-] type (8085:17)❌ 
│ │ │ ├──[+] allOf (1390:7)
│ │ │ └──[+] allOf (11433:15)
│ │ ├─┬messages
│ │ │ ├──[-] items (8022:13)❌ 
│ │ │ ├──[🔀] type (11373:17)❌ 
│ │ │ └──[-] nullable (8023:21)❌ 
│ │ └─┬top_k
│ │   ├──[-] type (8311:17)❌ 
│ │   ├──[+] oneOf (11488:15)
│ │   ├──[+] oneOf (11498:15)
│ │   ├──[+] oneOf (11508:15)
│ │   └──[+] oneOf (11516:15)
│ ├─┬InputImage
│ │ └─┬detail
│ │   └──[+] enum (9575:15)
│ ├─┬ChatFunctionTool
│ │ ├──[+] anyOf (20032:7)
│ │ ├──[+] anyOf (21211:7)
│ │ ├──[+] anyOf (15095:7)
│ │ ├──[+] anyOf (5806:7)
│ │ ├─┬ANYOF
│ │ │ └──[🔀] $ref (184:20)❌ 
│ │ ├─┬ANYOF
│ │ │ └──[🔀] $ref (3571:20)❌ 
│ │ ├─┬ANYOF
│ │ │ └──[🔀] $ref (7159:20)❌ 
│ │ ├─┬ANYOF
│ │ │ └──[🔀] $ref (9379:20)❌ 
│ │ └─┬ANYOF
│ │   └──[🔀] $ref (5277:20)❌ 
│ ├─┬PublicEndpoint
│ │ └─┬pricing
│ │   └─┬discount
│ │     └──[+] format (18168:23)❌ 
│ ├─┬ChatWebSearchShorthand
│ │ ├──[+] properties (5824:9)
│ │ ├─┬max_total_results
│ │ │ ├──[🔀] description (5830:24)
│ │ │ └──[🔀] example (5832:20)
│ │ ├─┬parameters
│ │ │ └──[🔀] $ref (5835:11)❌ 
│ │ ├─┬user_location
│ │ │ └──[🔀] $ref (5844:11)❌ 
│ │ ├─┬excluded_domains
│ │ │ └──[🔀] description (5819:24)
│ │ ├─┬max_results
│ │ │ ├──[🔀] description (5825:24)
│ │ │ └──[🔀] example (5827:20)
│ │ ├─┬allowed_domains
│ │ │ └──[🔀] description (5811:24)
│ │ ├─┬type
│ │ │ └──[🔀] $ref (19205:20)❌ 
│ │ └─┬search_context_size
│ │   └──[🔀] $ref (21288:9)❌ 
│ ├─┬AnthropicCitationsConfig
│ │ └──[+] default (757:16)❌ 
│ ├─┬WebSearchEngineEnum
│ │ ├──[+] enum (21363:11)
│ │ └──[🔀] description (21356:20)
│ ├─┬GoneResponse
│ │ ├──[+] properties (9047:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (9049:13)❌ 
│ │   └──[🔀] type (9051:17)❌ 
│ ├─┬BadRequestResponse
│ │ ├──[+] properties (2596:9)
│ │ └─┬user_id
│ │   ├──[+] additionalProperties (2598:13)❌ 
│ │   └──[🔀] type (2600:17)❌ 
│ ├─┬WebSearchServerTool
│ │ └─┬max_results
│ │   └──[🔀] description (21441:24)
│ ├─┬OutputItemWebSearchCall
│ │ └──[-] required (10269:11)❌ 
│ ├─┬MessagesContentBlockStartEvent
│ │ └─┬content_block
│ │   ├──[+] anyOf (10835:15)
│ │   ├─┬ANYOF
│ │   │ └──[🔀] $ref (15162:9)❌ 
│ │   └─┬ANYOF
│ │     └──[🔀] $ref (304:9)❌ 
│ ├─┬Inputs
│ │ └─┬ANYOF
│ │   └─┬Schema
│ │     ├──[+] anyOf (15625:7)
│ │     ├──[+] anyOf (15358:7)
│ │     ├──[+] anyOf (15407:7)
│ │     ├──[+] anyOf (15488:7)
│ │     ├──[+] anyOf (16565:7)
│ │     ├──[+] anyOf (15374:7)
│ │     ├──[+] anyOf (15529:7)
│ │     ├──[+] anyOf (15635:7)
│ │     ├──[+] anyOf (15334:7)
│ │     ├──[+] anyOf (15303:7)
│ │     ├──[+] anyOf (16469:7)
│ │     ├──[+] anyOf (15271:7)
│ │     ├──[+] anyOf (16522:7)
│ │     ├──[+] anyOf (16500:7)
│ │     ├──[+] anyOf (16141:7)
│ │     ├──[+] anyOf (16116:7)
│ │     ├──[+] anyOf (16292:7)
│ │     ├──[+] anyOf (15200:7)
│ │     ├──[+] anyOf (16435:7)
│ │     ├──[+] anyOf (10332:7)
│ │     ├──[+] anyOf (10393:7)
│ │     ├──[+] anyOf (19266:7)
│ │     ├──[+] anyOf (19313:7)
│ │     ├──[+] anyOf (10510:7)
│ │     ├──[+] anyOf (10420:7)
│ │     ├──[+] anyOf (10448:7)
│ │     ├──[+] anyOf (10475:7)
│ │     ├──[+] anyOf (7059:7)
│ │     ├──[+] anyOf (7092:7)
│ │     ├──[+] anyOf (5968:7)
│ │     ├──[+] anyOf (9863:7)
│ │     ├─┬ANYOF
│ │     │ └──[🔀] $ref (2183:20)❌ 
│ │     ├─┬ANYOF
│ │     │ └──[🔀] $ref (2297:20)❌ 
│ │     ├─┬ANYOF
│ │     │ └──[🔀] $ref (9675:17)❌ 
│ │     ├─┬ANYOF
│ │     │ └──[🔀] $ref (9698:17)...

@mattapperson mattapperson added the patch Patch version bump label Apr 22, 2026
@mattapperson mattapperson force-pushed the speakeasy-sdk-regen-1776877485 branch 7 times, most recently from f7fda73 to 132f840 Compare April 28, 2026 15:24
@mattapperson mattapperson force-pushed the speakeasy-sdk-regen-1776877485 branch 14 times, most recently from a9d26b0 to 7064f71 Compare May 6, 2026 22:49
@mattapperson mattapperson force-pushed the speakeasy-sdk-regen-1776877485 branch 8 times, most recently from 0318849 to 4030c20 Compare May 13, 2026 04:52
@mattapperson mattapperson force-pushed the speakeasy-sdk-regen-1776877485 branch 4 times, most recently from 040e86b to 450bd26 Compare June 2, 2026 03:57
perry-the-pr-reviewer[bot]

This comment was marked as outdated.

@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

SDK 0.4.2 regeneration via Speakeasy — adds BYOK, Observability, Presets, STT, and Datasets endpoints, plus breaking changes across Chat, Responses, VideoGeneration, and Guardrails.

Verdict: 🔁 Needs changes

Details

CI: no checks configured ✅

Findings (see inline comments for full context):

  • 🟡 byok.go:242 — pagination Next() never terminates when limit is nil
  • 🟡 observability.go:241 — same pagination bug as above
  • 🟡 docs/sdks/chat/README.md:58res.ChatStreamingResponse field doesn't exist; should be res.EventStream
  • nit: README.md:351 already has an open Perry thread for the same ChatStreamingResponse issue — skipped to avoid duplicate

Codex (openai/gpt-5.5): timed out at 60s (still reading files) — no additional findings merged

Research: Speakeasy pagination docs confirm: when limit input is omitted, Next() must return nil on empty array only (len(arr) == 0), not on len(arr) < 0. The if len(arr) < l check is the correct termination when l > 0; the nil-limit branch is missing entirely.

Security: no concerns — no secrets, no auth changes, standard BYOK key routing through existing PopulateSecurity() pattern

Test coverage: no tests cover the new BYOK, Observability, or pagination endpoints; this is the existing pattern for Speakeasy-generated SDKs

Unresolved threads: 1 existing open Perry thread on README.md:351 (same ChatStreamingResponse field issue — deduped this review)

Scope: first review (full)
Tier: large (65757 LoC)

Comment thread byok.go
if limit != nil {
l = int(*limit)
}
if len(arr) < l {

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] pagination Next() never terminates when limit is nil — len(arr) < 0 is always false

Suggested change
if len(arr) < l {
if len(arr) == 0 || (l > 0 && len(arr) < l) {
Details

Why: When limit is nil, l = 0, making len(arr) < 0 always false for any non-negative count. Per Speakeasy pagination docs, when no limit is configured the termination condition is len(arr) == 0 (empty page signals last page). The current code will loop infinitely as long as the API returns any results, recursively calling s.List() until the goroutine stack exhausts.

Fix: Change if len(arr) < l to if len(arr) == 0 || (l > 0 && len(arr) < l). The same fix is needed in observability.go at the equivalent line.

Ref: Speakeasy pagination termination — "next() returns null when length equals zero when limit is omitted"

Prompt for agents
In `byok.go` line 242, the pagination termination check `if len(arr) < l` is buggy when `limit` is nil. When `limit` is nil, `l` is 0 so `len(arr) < 0` is always false — `Next()` recurses indefinitely on any non-empty page. Fix: change `if len(arr) < l {` to `if len(arr) == 0 || (l > 0 && len(arr) < l) {`. Apply the identical fix at `observability.go` line ~241.

Reviewed at 2893036

Comment thread observability.go
if limit != nil {
l = int(*limit)
}
if len(arr) < l {

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] same pagination termination bug as byok.go:242len(arr) < l never fires when limit is nil

Suggested change
if len(arr) < l {
if len(arr) == 0 || (l > 0 && len(arr) < l) {
Details

Identical to the byok.go issue: l = 0 when limit is nil, so len(arr) < 0 is never true.

Reviewed at 2893036

Comment thread docs/sdks/chat/README.md
if err != nil {
log.Fatal(err)
}
if res != nil {
defer res.Object.Close()
defer res.ChatStreamingResponse.Close()

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] res.ChatStreamingResponse — field does not exist on *operations.SendChatCompletionRequestResponse; correct field is res.EventStream

Suggested change
defer res.ChatStreamingResponse.Close()
defer res.EventStream.Close()
Details

Why: SendChatCompletionRequestResponse is a union type with field EventStream *stream.EventStream[components.ChatStreamingResponse]. ChatStreamingResponse is the type parameter of the generic, not the field name. Accessing res.ChatStreamingResponse will fail to compile with res.ChatStreamingResponse undefined.

Lines 60–61 need the same fix: res.ChatStreamingResponse.Next()res.EventStream.Next() and res.ChatStreamingResponse.Value()res.EventStream.Value().

The same issue affects README.md:351–354 (open Perry thread) and docs/sdks/chat/README.md:113–116.

Fix: Replace all three occurrences in this file and the three in README.md.

Prompt for agents
In `docs/sdks/chat/README.md` lines 58, 60, 61, 113, 115, 116 and in `README.md` lines 351, 353, 354, replace every occurrence of `res.ChatStreamingResponse` with `res.EventStream`. The struct `SendChatCompletionRequestResponse` has a field named `EventStream` (of type `*stream.EventStream[components.ChatStreamingResponse]`) — `ChatStreamingResponse` is only the generic type parameter, not the field name. The code currently won't compile.

Reviewed at 2893036

@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

SDK 0.4.2 regeneration via Speakeasy — adds BYOK, Observability, Presets, Datasets, STT endpoints, and brings new server-tool types (AdvisorServerTool, WebFetch), plus breaking changes across Chat, Responses, and core model types.

Verdict: 🔁 Needs changes

Details

CI: no checks configured ✅

Findings (see inline comments for full context):

  • 🔴 chat.go:37Chat.Send adds new required xOpenRouterExperimentalMetadata parameter, breaking all existing callers
  • 🔴 responses.go:38Responses.Send same new required parameter, breaking all existing callers
  • 🔴 models/components/chatrequest.go:338Reasoning type renamed to ChatRequestReasoning; Effort renamed to ChatRequestEffort — breaking type change without compatibility aliases
  • 🟡 README.md:351res.ChatStreamingResponse field doesn't exist (open prior Perry thread) — still unresolved; see existing inline comment
  • 🟡 docs/sdks/chat/README.md:58 — same res.ChatStreamingResponse bug in generated SDK docs (open prior Perry thread) — still unresolved

Codex (openai/gpt-5.5): 5 findings — confirmed 3 new blockers (Chat.Send/Responses.Send breaking params, Reasoning type rename); 2 server-tool type constructor gaps are pre-existing Speakeasy pattern (not new in this PR)

Research: Speakeasy marks 8 operations as "Breaking ⚠️" in the PR description, correctly documenting the API changes. Go SemVer for v0.x.y is pre-release (no compat guarantee), so a patch bump with breaking changes is technically permitted but unusual — callers should be notified. The README streaming bug (res.ChatStreamingResponse) is a Speakeasy codegen docs issue that persists across this regeneration.

Security: no concerns — BYOK credential handling follows existing PopulateSecurity() pattern, no new auth paths introduced

Test coverage: no tests cover new BYOK, Observability, Presets, Datasets, or STT endpoints — consistent with the existing no-tests pattern for Speakeasy-generated SDKs

Unresolved threads: 4 from prior review — 2 on README streaming (still unresolved in current code), 2 on pagination (code is correct: len(arr)==0 check present; prior finding was incorrect)

Scope: first review (full)
Tier: large (65782 LoC)

Comment thread chat.go Outdated
// Send - Create a chat completion
// Sends a request for a model response for the given chat conversation. Supports both streaming and non-streaming modes.
func (s *Chat) Send(ctx context.Context, request components.ChatRequest, opts ...operations.Option) (*operations.SendChatCompletionRequestResponse, error) {
func (s *Chat) Send(ctx context.Context, chatRequest components.ChatRequest, xOpenRouterExperimentalMetadata *components.MetadataLevel, opts ...operations.Option) (*operations.SendChatCompletionRequestResponse, error) {

This comment was marked as outdated.

Comment thread responses.go Outdated
@@ -35,7 +35,12 @@ func newResponses(rootSDK *OpenRouter, sdkConfig config.SDKConfiguration, hooks

// Send - Create a response
// Creates a streaming or non-streaming response using OpenResponses API format
func (s *Responses) Send(ctx context.Context, request components.ResponsesRequest, opts ...operations.Option) (*operations.CreateResponsesResponse, error) {
func (s *Responses) Send(ctx context.Context, responsesRequest components.ResponsesRequest, xOpenRouterExperimentalMetadata *components.MetadataLevel, opts ...operations.Option) (*operations.CreateResponsesResponse, error) {

This comment was marked as outdated.

// Reasoning - Configuration options for reasoning models
type Reasoning struct {
// ChatRequestReasoning - Configuration options for reasoning models
type ChatRequestReasoning struct {

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] Reasoning type renamed to ChatRequestReasoning; Effort renamed to ChatRequestEffort — breaking type change without compatibility aliases

Details

Why: Two types were renamed:

  • components.Reasoningcomponents.ChatRequestReasoning
  • components.Effort (and its constants EffortHigh, EffortMedium, EffortLow) → components.ChatRequestEffort (with constants ChatRequestEffortHigh, ChatRequestEffortMedium, ChatRequestEffortLow)

Any caller that uses components.Reasoning{}, components.EffortHigh, etc. will fail to compile. No type alias or compatibility shim was generated.

Fix for callers:

// Before
chatRequest.Reasoning = &components.Reasoning{
    Effort: optionalnullable.From(components.EffortHigh),
}
// After
chatRequest.Reasoning = &components.ChatRequestReasoning{
    Effort: optionalnullable.From(components.ChatRequestEffortHigh),
}

Ref: PR description — ChatRequest.Reasoning field Changed (Breaking ⚠️)

Prompt for agents
In `models/components/chatrequest.go`, two types were renamed as part of the SDK regeneration: `Reasoning` → `ChatRequestReasoning` (line 338) and `Effort` → `ChatRequestEffort` (line 311), along with all associated constants (`EffortHigh` → `ChatRequestEffortHigh`, etc.). Any caller that references `components.Reasoning`, `components.Effort`, `components.EffortHigh`, `components.EffortMedium`, or `components.EffortLow` must be updated to use the new names. Search for these old names and replace with the new ones.

Reviewed at bf5fcad

@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-generated Go SDK bump to v0.4.2 — adds BYOK, Observability, Presets, STT endpoints, new model components, and threading OpenRouterMetadata through openrouter_metadata response fields.

Verdict: 🔁 Needs changes

Details

CI: no checks registered ✅

Findings (see inline comments for full context):

Previously raised blockers (7 unresolved threads — code unchanged):

  • 🔴 chat.go:37Chat.Send new required xOpenRouterExperimentalMetadata parameter breaks all existing callers
  • 🔴 responses.go:38Responses.Send same breaking required parameter
  • 🔴 models/components/chatrequest.go:338Reasoning type renamed to ChatRequestReasoning; Effort renamed to ChatRequestEffort — compile break for existing callers
  • 🟡 README.md:351 — example uses non-existent res.ChatStreamingResponse field (correct: res.EventStream)
  • 🟡 byok.go:242 — pagination Next() never terminates when limit is nil
  • 🟡 observability.go:241 — same pagination termination bug

New finding this review:

  • 🟡 byok.go:88 / observability.go:87defer cancel() fires when List() returns, leaving the ctx captured by Next() closure already cancelled; pagination with a configured timeout fails on the second page with context.Canceled

Codex (openai/gpt-5.5): independently flagged the ctx-cancellation bug in byok.go and observability.go (finding confirmed)

Research: Go module semantic versioning — adding required parameters to exported function signatures is a breaking change. At v0.x, SemVer allows breaking changes, but existing go get users are not shielded. The pointer parameter *MetadataLevel already makes this optional at the Go type level, so the breaking change is specifically the new required positional argument in the call site.

Security: no concerns — no credential patterns in diff; openrouter_metadata is routing metadata only

Test coverage: no new tests for new endpoints (STT, BYOK, Observability, Presets, Datasets); pagination logic is hand-editable despite generated status

Unresolved threads: 7 — all from prior Perry review, none addressed

Scope: first review (full) · Tier: large (65795 LoC)

Comment thread byok.go
if timeout != nil {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, *timeout)
defer cancel()

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] defer cancel() fires when List returns, cancelling the ctx captured by the Next() closure — pagination with a timeout configured fails with context.Canceled on the second page

Details

Why: At line 87 ctx is reassigned to a timeout-derived context, and defer cancel() at line 88 is scheduled to fire when List returns. The res.Next closure (line 208) captures this shadowed ctx. By the time a caller invokes res.Next(), List() has returned, the defer has fired, and the captured context is already cancelled. The recursive s.List(ctx, ...) inside Next() immediately returns context.Canceled.

Fix: Capture the original context before the timeout branch and pass it to the recursive call:

origCtx := ctx    // capture before timeout wrapping
if timeout != nil {
    ctx, cancel = context.WithTimeout(ctx, *timeout)
    defer cancel()
}
// ... inside res.Next closure:
return s.List(origCtx, ...)

Ref: Go context blog — contexts should be passed explicitly, not captured from an outer scope that owns the cancellation.

Prompt for agents
In byok.go the res.Next closure (line 208) captures ctx, which was shadowed at line 87 by context.WithTimeout and cancelled by defer cancel() at line 88 when List() returns. The same pattern exists in observability.go at lines 86/207. Fix: add origCtx := ctx immediately before the timeout branch in both files, then change the recursive s.List(ctx, ...) call inside each res.Next closure to s.List(origCtx, ...). This allows pagination to succeed even when the SDK is configured with a per-call timeout.

Reviewed at 5ba2e1c

@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-generated Go SDK bump to v0.4.2 — adds BYOK, Observability, Presets, STT endpoints and new model components. This is a force-push with the same content as the prior reviewed commit; all 8 unresolved findings from previous reviews remain unaddressed.

Verdict: 🔁 Needs changes

Details

CI: no checks registered ✅

Findings: All findings previously raised as inline review comments — 3 blockers and 5 suggestions — remain unresolved. See the existing inline review threads on this PR for full details.

Blockers:

  • Breaking Chat.Send signature change (new required xOpenRouterMetadata parameter, all callers compile-break)
  • Breaking Responses.Send signature change (same)
  • Type rename: ReasoningChatRequestReasoning, EffortChatRequestEffort (compile break for existing callers)

Suggestions:

  • README and docs examples reference non-existent res.ChatStreamingResponse field (should be res.EventStream)
  • byok.go and observability.go pagination Next() infinite loop when limit is nil
  • defer cancel() in List() fires before Next() can run — timeout-configured pagination fails with context.Canceled on second page

Codex (openai/gpt-5.5): confirmed the defer cancel() pagination context cancellation bug; also surfaced the same pre-existing pattern in streaming endpoints

Research: Go semver at v0.x permits breaking signature changes but all existing callers require a nil argument addition at every invocation. No migration shim provided.

Security: no concerns — no credential patterns; openrouter_metadata is routing metadata only

Test coverage: no tests for any new endpoints (STT, BYOK, Observability, Presets, Datasets)

Unresolved threads: 8 — all from prior Perry reviews, none addressed in this push

Scope: incremental — 0 new lines since prior review (force-push, same content) · Tier: large (67738 LoC)

@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-regenerated SDK update (v0.4.1→0.4.2) adding 5 new endpoint groups (BYOK, Datasets, Observability, Presets, STT), new plugins (Fusion, WebFetch), ForbiddenResponseError (403) handling, and OpenrouterMetadata field on all error types. The PR flags multiple breaking API changes.

Verdict: 🔁 Needs changes

Details

CI: no checks configured

Findings (see inline comments for full context):

  • 🔴 models/components/chatrequest.go:311EffortChatRequestEffort and ReasoningChatRequestReasoning type renames break existing callers
  • 🟡 byok.go:87 — pagination Next() closure captures cancelled context; fails with context.Canceled when timeout is configured
  • 🟡 README.md:351res.ChatStreamingResponse field doesn't exist; correct field is res.EventStream
  • 🟡 Version bump 0.4.1→0.4.2 (patch) contains breaking API changes; semver convention for pre-v1 modules recommends minor bump (0.5.0) for breaking changes

Codex (openai/gpt-5.5): confirmed context cancellation bug in byok.go and observability.go; flagged Accept header q=0 for SSE (pre-existing pattern, not new in this PR)

Research: Speakeasy's automatic versioning bumps on document checksum only — does not analyze semantic breakage. Community convention: breaking changes in pre-v1 warrant a minor bump, not patch. (semver.org, Speakeasy versioning docs)

Security: BYOK endpoints don't expose raw key values (encrypted at rest per API docs). Category 1 (provider API key handling) TOUCHED but safeguard intact. No secrets found in diff. No concerns.

Test coverage: 2 test files in repo. No coverage for 5 new endpoint groups or pagination/context bugs. Pre-existing gap.

Unresolved threads: 6 active prior Perry threads (type renames, context cancellation, README field name, pagination termination) all remain unaddressed at current HEAD.

// Effort - Constrains effort on reasoning for reasoning models
type Effort string
// ChatRequestEffort - Constrains effort on reasoning for reasoning models
type ChatRequestEffort string

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] Effort renamed to ChatRequestEffort — all callers referencing components.Effort, components.EffortHigh, components.EffortMedium, etc. will fail to compile

Details

Why: The type Effort and all its constants (EffortXhigh, EffortHigh, EffortMedium, EffortLow, EffortMinimal, EffortNone) have been renamed to ChatRequestEffort / ChatRequestEffortXhigh, etc. The companion struct Reasoning was also renamed to ChatRequestReasoning (line 338). No type aliases or compatibility shims were generated, so any existing code using these types will not compile against v0.4.2.

Fix:

// Before v0.4.2
chatRequest.Reasoning = &components.Reasoning{
    Effort: optionalnullable.From(components.EffortHigh),
}
// After v0.4.2
chatRequest.Reasoning = &components.ChatRequestReasoning{
    Effort: optionalnullable.From(components.ChatRequestEffortHigh),
}

Ref: PR description — ChatRequest.Reasoning field Changed (Breaking ⚠️)

Prompt for agents
In `models/components/chatrequest.go`, the types `Effort` and `Reasoning` were renamed to `ChatRequestEffort` and `ChatRequestReasoning`. All callers using the old names will fail to compile. Add type aliases for backward compatibility: `type Effort = ChatRequestEffort` and `type Reasoning = ChatRequestReasoning`, plus constant aliases for all `Effort*` constants. Alternatively, bump the version to 0.5.0 to signal a minor breaking change per semver convention.

Reviewed at d23a8c4

Comment thread byok.go

if timeout != nil {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, *timeout)

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] defer cancel() fires when List() returns, cancelling the ctx captured by the Next() closure — calling res.Next() with a timeout configured fails with context.Canceled

Details

Why: At line 87 ctx is reassigned to a timeout-derived context. defer cancel() at line 88 fires when List() returns. The res.Next closure (line 209) captures this shadowed ctx. By the time a caller invokes res.Next(), the cancel has already been called, so stream.EventStream.Next() immediately returns false with context.Canceled. The same bug exists in observability.go at the equivalent lines.

Fix: Save the original context before the timeout branch and use it in the recursive call:

origCtx := ctx  // capture before timeout wrapping
if timeout != nil {
    var cancel context.CancelFunc
    ctx, cancel = context.WithTimeout(ctx, *timeout)
    defer cancel()
}
// ... inside res.Next closure:
return s.List(origCtx, ...)

Ref: Go context docs

Prompt for agents
In `byok.go` line 87, add `origCtx := ctx` immediately before the timeout branch (before `if timeout != nil`). In the `res.Next` closure at line 248, change the recursive `s.List(ctx, ...)` call to `s.List(origCtx, ...)`. Apply the identical fix in `observability.go` at the equivalent lines (~85 and ~246). This ensures pagination calls get a fresh, non-cancelled context even when the initial `List()` call was configured with a per-request timeout.

Reviewed at d23a8c4

Comment thread README.md Outdated
}
if res != nil {
defer res.Object.Close()
defer res.ChatStreamingResponse.Close()

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] res.ChatStreamingResponse — field does not exist on *operations.SendChatCompletionRequestResponse; correct field is res.EventStream

Suggested change
defer res.ChatStreamingResponse.Close()
defer res.EventStream.Close()
Details

The struct SendChatCompletionRequestResponse has two fields: ChatResult *components.ChatResult and EventStream *stream.EventStream[components.ChatStreamingResponse]. The README uses res.ChatStreamingResponse at lines 351–354, but no such field or method exists — these examples will fail to compile. The same issue appears in docs/sdks/chat/README.md at lines 58–61 and 113–116.

Fix: Replace all occurrences of res.ChatStreamingResponse with res.EventStream across README.md and docs/sdks/chat/README.md.

Reviewed at d23a8c4

@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-generated SDK bump to v0.4.2 — adds BYOK, Datasets, Observability, Presets, and STT endpoint groups; adds Fusion streaming events; adds ForbiddenResponseError (403) handling and OpenrouterMetadata field on all error types.

Verdict: 🔁 Needs changes

Details

CI: no checks configured

Findings (see inline comments for full context):

  • 🔴 chat.go:79defer cancel() cancels the streaming context before the caller reads the EventStream
  • 🔴 responses.go:80 — same defer cancel() streaming context bug
  • 🔴 docs/sdks/responses/README.md:41res.ResponsesStreamingResponse field doesn't exist; correct field is res.EventStream
  • nit: version 0.4.2 contains multiple breaking API changes; pre-v1 semver convention suggests a minor bump (0.5.0)

Still open (unresolved threads from prior reviews):

  • ReasoningChatRequestReasoning and EffortChatRequestEffort type renames break callers
  • res.ChatStreamingResponse field doesn't exist in README examples
  • defer cancel() in pagination closures in byok.go and observability.go

Note: The pagination len(arr) < l finding in prior Perry threads is a false positive per Speakeasy pagination docs — when limit is omitted, termination on empty page only is intentional.

Codex (openai/gpt-5.5): confirmed defer cancel() streaming context bug; identical issue in pagination closures (already in prior threads)

Research: Go context docsdefer cancel() fires on function return; storing that context in a returned EventStream violates Go's context lifecycle. Fix: attach cancel to EventStream.Close().

Security: BYOK credential management handled correctly. Category 1 (provider API key handling) TOUCHED; ForbiddenResponseError (Category 7) added correctly. No secrets in diff.

Test coverage: no tests added for 5 new endpoint groups. Pre-existing gap.

Unresolved threads: 9 open from prior reviews; 2 are outdated; 7 remain active.

Scope: incremental — 1154 new lines since prior review
Tier: large (68764 LoC)

Comment thread chat.go
bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, false, "ChatRequest", "json", `request:"mediaType=application/json"`)
if err != nil {
return nil, err
}

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] defer cancel() cancels the streaming context before the caller can read the EventStream — any configured SDK or operation timeout silently breaks streaming

Details

Why: context.WithTimeout creates a child context; defer cancel() fires the moment Chat.Send() returns. The EventStream created downstream captures ctx internally. When the caller subsequently calls res.EventStream.Next(), it immediately sees ctx.Done() fired and returns false with context.Canceled — the timeout has already elapsed from the perspective of the stream, even if the actual timeout duration has not passed.

This affects all users who set an SDK-level timeout (openrouter.WithTimeout(...)) or per-call timeout (operations.WithTimeout(...)) AND use streaming. Non-streaming callers are unaffected since the full response body is read before the function returns.

Fix: Move ownership of cancel into the returned EventStream so it fires when Close() is called, not when Send() returns. If stream.NewEventStream supports a callback option, pass cancel there. Otherwise, add a WithClose functional option to EventStream and call cancel inside Close().

Ref: Go context docs — contexts should not be stored in structs

Prompt for agents
In `chat.go` around line 87-91 (the `context.WithTimeout` + `defer cancel()` block), the deferred cancel fires when `Chat.Send()` returns — before the caller can read the returned EventStream. The EventStream captures `ctx` internally and checks `ctx.Done()` in `Next()`. Fix: remove `defer cancel()` and instead pass `cancel` to the EventStream so it is called in `EventStream.Close()`. If `stream.NewEventStream` does not accept a close callback, add one (e.g. `stream.WithClose(cancel)` functional option in `types/stream/stream.go`). Apply the identical fix in `responses.go` at the equivalent `defer cancel()` block.

Reviewed at 0e82f46

Comment thread responses.go
@@ -69,7 +74,7 @@ func (s *Responses) Send(ctx context.Context, request components.ResponsesReques
OAuth2Scopes: nil,
SecuritySource: s.sdkConfiguration.Security,
}
bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, false, "Request", "json", `request:"mediaType=application/json"`)
bodyReader, reqContentType, err := utils.SerializeRequestBody(ctx, request, false, false, "ResponsesRequest", "json", `request:"mediaType=application/json"`)
if err != nil {
return nil, err
}

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] defer cancel() — same streaming context cancellation bug as chat.goEventStream.Next() immediately fails with context.Canceled when a timeout is configured

Details

Why: Same root cause as chat.go: defer cancel() fires when Responses.Send() returns, cancelling the context captured by the EventStream. Any SDK or per-call timeout configured by the caller breaks streaming responses.

Fix: Same as chat.go — move cancel ownership into the EventStream.Close() path.

Prompt for agents
In `responses.go` around line 88-90, `defer cancel()` fires when `Responses.Send()` returns, cancelling the context captured by the returned EventStream. Calling `res.EventStream.Next()` immediately fails with `context.Canceled` when a timeout is configured. Fix: remove `defer cancel()` and pass `cancel` to `stream.NewEventStream` so it fires in `Close()` instead. The identical fix is needed in `chat.go`.

Reviewed at 0e82f46

if err != nil {
log.Fatal(err)
}
if res != nil {
defer res.Object.Close()
defer res.ResponsesStreamingResponse.Close()

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] res.ResponsesStreamingResponse field does not exist on *operations.CreateResponsesResponse — this example will not compile

Suggested change
defer res.ResponsesStreamingResponse.Close()
defer res.EventStream.Close()
Details

CreateResponsesResponse has field EventStream *stream.EventStream[components.ResponsesStreamingResponse]. ResponsesStreamingResponse is the generic type parameter, not the field name. Lines 43-44 and lines 77-80 need the same fix.

Ref: models/operations/createresponses.go:20

Reviewed at 0e82f46

@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

Auto-generated Go SDK update (v0.4.1 → v0.4.2) adding BYOK, Datasets, Observability, Presets, and STT endpoints plus Fusion and WebFetch plugins. All 14 unresolved findings from the prior review remain open and unaddressed in this push.

Verdict: 🔁 Needs changes

Details

CI: no CI configured for this repo

Open findings (carry-forward — see prior inline comments):

  • 2 blockers: type renames (Effort → ChatRequestEffort, Reasoning → ChatRequestReasoning) without semver minor bump; defer cancel() cancels streaming context before caller reads EventStream
  • 3 suggestions: pagination termination bug when limit is nil (byok.go, observability.go); res.ChatStreamingResponse field name wrong in README (should be res.EventStream)
  • All findings are already in active unresolved Perry review threads — no new inline comments added to avoid duplication

Codex (openai/gpt-5.5): 2 findings surfaced — pagination context capture in byok/observability Next(); POST retry without idempotency key on BYOK/Observability Create (pre-existing SDK pattern, not new)

Research: Speakeasy breaking-changes guide confirms 0.5.0 is the correct version for exported type renames in a pre-v1 SDK. Context cancellation on EventStream return is a Go idiom violation with no upstream Speakeasy tracking.

Security: no concerns — auth plumbing unchanged, no credential logging

Test coverage: no SDK-level tests; doc examples non-compilable (res.ChatStreamingResponse field name)

Unresolved threads: 14 open Perry threads from prior review, all still unresolved

Scope: incremental — 58 new lines since prior review (1 new doc file: docs/models/components/dataregion.md)
Tier: large (68808 LoC)

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

@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 regeneration bumping the Go SDK 0.4.1 → 0.4.2: adds BYOK, Datasets (app-rankings/daily-rankings), Observability, Presets, beta-analytics & STT endpoints, a new 403 Forbidden response path, and several breaking request/response signature changes.

Verdict: 🔁 Needs changes

Details

CI: no checks configured/run on this commit (combined status empty) — not a gate on this verdict.

State of prior review: Perry's last review (12cc087) requested changes and 17 threads remain unresolved. This push (the delta 12cc087..b2f3e1d) adds the Datasets service + app-rankings models and a new Models.List sort param, but does not address any of the previously-raised blockers. They all still reproduce at b2f3e1d:

  • 🔴 Streaming context-cancellation (open threads on the chat & responses send methods). The defer cancel() guarding the per-call timeout cancels the context that the returned event stream captures. Confirmed against the stream runtime: Next() selects on the context's Done() channel, and cancel() fires the instant Send() returns — so the first stream read immediately fails with context.Canceled whenever an SDK/operation timeout is set. A real runtime bug on every streaming call configured with a timeout.
  • 🔴 Alias-less breaking type renames (open thread on the chat-request component). EffortChatRequestEffort and ReasoningChatRequestReasoning were renamed with no compatibility aliases (verified absent), so every caller of the old components.Effort* constants breaks at compile time.
  • 🟡 Generator config (open thread on the gen config). maxMethodParams: 4 is the documented root cause of the recurring breaking-signature churn; setting it to 0 always emits a request object and lets params evolve without signature breaks.

New this push (in-scope):

  • 🟡 The new Datasets GetAppRankings repeats the pagination defer cancel() footgun (same class as the existing BYOK / Observability pagination threads) — posted inline.

Codex (HEAVY_SECONDARY_MODEL): 2 findings on the Datasets service, both verified as generated-pattern artifacts with negligible practical impact under the documented usage (the example passes a fresh request literal): (1) a nil request pointer would deref-panic during query-param population — but no documented path passes nil; (2) the pagination closure mutates the caller-supplied request offset in place rather than a copy. Noted for the generator, not posted inline.

Research: Speakeasy pagination docs and Go context-cancellation methodology confirm the deferred-cancel-captured-context pattern breaks streaming and pagination reads. The Speakeasy maxMethodParams reference confirms setting maxMethodParams to 0 is the documented fix for signature stability across regens.

Security: no concerns — no secrets in the diff; auth header handling unchanged from the generated template; the new 403 Forbidden path is well-formed (added to the status-code matcher, has a matching case handler, and the ForbiddenResponseError type exists).

Build/vet: the package builds cleanly. go vet warnings (unreachable code, unexported deleted json-tag) are pre-existing Speakeasy generator patterns that also appear in files not in this diff — not introduced here.

Test coverage: none — generated SDK ships no unit tests; consistent with prior state, not a regression.

Unresolved threads: 17 open (all Perry-authored across prior rounds). The streaming context-cancellation blocker and the alias-less type renames should be resolved (ideally upstream in the spec / generator config) before this is mergeable.

Scope: first review (full) — no prior snapshot artifact on disk
Review: tier=large · model=claude-opus-latest · score=795.7

Comment thread datasets.go
if timeout != nil {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, *timeout)
defer cancel()

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] defer cancel() cancels the ctx captured by the Next() pagination closure — GetAppRankings paginated with a configured timeout fails with context.Canceled

Details

Why: When a per-call or SDK-level Timeout is set, line 102-103 wraps ctx in context.WithTimeout and defer cancel()s it. The res.Next closure (line 223) captures that same ctx and re-invokes s.GetAppRankings(ctx, …) (line 263). But cancel() runs the instant the outer GetAppRankings returns — i.e. before the caller ever calls res.Next(). So the first Next() issues its request on an already-cancelled context and fails with context.Canceled. This is the same class of bug already flagged on byok.go:87 and observability.go pagination; datasets.go is new in this push and repeats it.

Fix: This is generator-driven — the durable fix is upstream (Speakeasy pagination + context handling), not a hand-edit to generated output. Either (a) don't bind the per-request timeout to the paginating context, or (b) re-derive a fresh timeout context inside each Next() invocation rather than reusing the cancelled parent.

Ref: Speakeasy pagination docs · Go context cancellation methodology

Prompt for agents
In `datasets.go`, `GetAppRankings` (line ~100) wraps the request context with `context.WithTimeout` + `defer cancel()`. The `res.Next` pagination closure at line ~223 captures this same `ctx` and reuses it when calling `s.GetAppRankings(ctx, request, opts...)` at line ~263. Because `cancel()` fires when the outer call returns, any `res.Next()` invoked by the caller hits an already-cancelled context and fails with context.Canceled whenever a timeout is configured. This is generated code, so fix it at the source: in the Speakeasy SDK config / generator, ensure paginated operations either do not bind the per-call timeout to the context captured by the Next closure, or re-establish a fresh timeout context per Next() call. The same pattern also affects byok.go and observability.go pagination.

Reviewed at b2f3e1d

@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-generated Go SDK regen (0.4.1 to 0.4.2): 293 generated Go files plus 644 docs plus Speakeasy lock/config, driven by an updated upstream OpenAPI spec. Adds preset-version endpoints, new server-tool types (fusion, web-fetch, shell, apply-patch), observability destinations, and assorted provider slugs and aspect ratios.

Verdict: 🔁 Needs changes

Details

Re-review note: This is a re-review of the latest push. Rather than re-post the 14 still-open inline findings from prior rounds, I verified the regen end-to-end and confirmed those findings remain valid against the current HEAD (42986f6) and are still not addressed. They are visible as existing unresolved review threads — I have intentionally not duplicated them inline (anti-re-review-spam).

Build and tests: go build passes, go test passes, go vet reports the usual Speakeasy generated-code patterns (unexported const JSON fields, unreachable post-return code) — all pre-existing on main (46 same-class findings on the base commit), not a regression from this push. All 293 changed Go files carry the "Code generated by Speakeasy" header — pure regen, zero hand-edits.

Still-open blockers (already posted inline in prior rounds; unaddressed):

  • 🔴 chat.go and responses.go — Send() gained a required positional xOpenRouterMetadata argument, breaking every existing caller. Root cause is maxMethodParams set to 4 in the Speakeasy gen config; Speakeasy's own guidance is to set it to 0 so new fields stay additive on a request object (gen.yaml reference, handling breaking changes).
  • 🔴 chat.go and responses.go (streaming) — defer cancel() tears down the timeout context the moment Send() returns, before the caller reads the returned EventStream, so streaming with any configured SDK or operation timeout fails with context.Canceled. This is the classic Speakeasy SSE plus WithTimeout footgun (Speakeasy SSE docs, Go context).
  • 🔴 chatrequest.go — the Effort, Reasoning, and a FunctionCallOutputItem type were renamed (Effort to ChatRequestEffort, Reasoning to ChatRequestReasoning) with no compatibility aliases — breaking for any caller referencing the old names.

Still-open suggestions (already posted inline; unaddressed):

  • 🟡 byok.go, datasets.go, observability.go — the same defer cancel() cancels the context captured by the Next() pagination closure, so a second-page fetch under a configured timeout fails.
  • 🟡 byok.go and observability.go — pagination Next() final-page handling: the len(arr) less-than-limit check is dead code when limit is nil; the len(arr)==0 guard prevents an infinite loop but an extra empty fetch remains.
  • 🟡 observability.go — the retry path runs AfterSuccess for final 4xx/5xx responses; AfterError hooks are skipped whenever retries are configured.
  • 🟡 Doc examples (the chat and responses README streaming snippets) reference res.ChatStreamingResponse and res.ResponsesStreamingResponse, but the generated struct field is res.EventStream — the examples won't compile.

Codex (gpt-5.5) — one new observation (prose only, not raised inline):

  • byok.go CreateBYOKKey retries a non-idempotent POST on 5XX. If the server processed the create but the response was lost, a retry can duplicate the BYOK credential. This is the spec-level x-speakeasy-retries policy applied uniformly to every method (not specific to this file), so the correct fix is in the upstream OpenAPI retry config, not in this generated PR. Noted for awareness; not raised as a blocker on a generated artifact.

Research: Confirmed the maxMethodParams breaking-signature mechanism and Speakeasy's recommendation to set it to 0; confirmed the defer cancel() plus streaming EventStream cancellation as a documented Go and Speakeasy-SSE pitfall.

Security: No secrets in the diff. No auth, API-key-handling, or tenant-isolation logic changed (generated provider-slug maps and DTOs only) — no concerns.

Test coverage: The SDK ships only internal/utils and optionalnullable unit tests; none exercise the generated client, streaming, or pagination paths. The streaming defer cancel() and pagination-termination bugs would be caught by even a minimal client-level test against a mock server — worth adding in the generator's test target upstream.

Unresolved threads: 14 active (non-outdated) plus 4 outdated from prior rounds — all Perry-authored, all still applicable, none re-posted here.

Scope: first review (full) — no prior diff snapshot persisted; reviewed the full diff (941 files, +71430 / -13528)
Review: tier=large · model=claude-opus-latest · score=849.6

@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 regen bumping the Go SDK 0.4.1 → 0.4.2, adding the Design Arena benchmarks endpoint (GetBenchmarksDesignArena) plus Presets/Observability/BYOK surface — but shipping a wave of breaking method-signature and type-rename changes under a patch version bump.

Verdict: 🔁 Needs changes

Details

Scope: incremental re-review of the new push (head 5132639). The delta since my last review (42986f6) is 28 files / +1797 / -54 — almost entirely the new Design Arena benchmark types and the GetBenchmarksDesignArena method on the datasets service. That new endpoint is generated cleanly: correct numeric typing on win_rate/elo, standard retry+error-hook handling, and a non-paginated GET (no Next() closure, so the defer-cancel pagination footgun does not apply to it). No new findings on the added code.

Why this still needs changes: the new push did not address the outstanding blockers from prior reviews — they remain live as unresolved review threads on the current code (14 non-outdated unresolved threads). The headline issue is unchanged:

  • This is a patch bump (0.4.1 → 0.4.2), but the generated release notes flag many changes as Breaking ⚠️ — Chat.Send / Beta.Responses.Send gained a new required positional parameter; Reasoning → ChatRequestReasoning, Effort → ChatRequestEffort, and FunctionCallOutputItemOutputType were renamed with no compatibility aliases. Every existing caller fails to compile after a routine go get -u within the 0.4.x line.
  • Root cause (already raised inline on the gen.yaml thread): maxMethodParams=4 makes Speakeasy emit positional params instead of a request object, so any added field reshapes the method signature. Speakeasy's automatic versioning only inspects info.version + the document checksum — it does not analyze content for breaking changes — so signature/type breaks register as a patch unless the bump is overridden.

Recommended remedy (no need to re-litigate the existing inline threads — they cover the specifics):

  1. Set maxMethodParams=0 in gen.yaml so methods take an evolvable request object and future field additions stop breaking signatures.
  2. For this release, force the correct bump (SPEAKEASY_BUMP_OVERRIDE=major, or a PR "major" label). Note: for a pre-1.0 Go SDK Speakeasy downgrades an automatic major to minor, and crossing 1.0 later requires a "/v2" import-path change — so decide the versioning story deliberately rather than letting it ship silent as a patch.

Pre-existing generator footguns also still open (flagged inline previously, unchanged by this push): defer cancel() cancelling the streaming/pagination context before the caller reads it (chat/responses/byok/datasets), the "len(arr) < l" pagination terminator that never fires when limit is nil, the retry path invoking AfterSuccess on final 4xx/5xx, and two doc examples referencing response fields that don't exist on the generated types.

CI: no checks configured on this repo — nothing to report (not a gate on the verdict).

Codex (gpt-5.5): one finding surfaced (datasets.go Next() nil-deref); discarded after verification — GetAppRankings documents request as required and the usage example passes a non-nil value, so the premise was false.

Research: Speakeasy versioning + breaking-changes docs — confirmed auto-versioning keys only on info.version/checksum (not content), and maxMethodParams=0 plus SPEAKEASY_BUMP_OVERRIDE are the documented mitigations.

Security: no concerns — generated client SDK + docs; secret-pattern scan over added lines is clean (example credentials are server-masked placeholders).

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

Unresolved threads: 14 non-outdated unresolved threads from prior reviews remain — all still applicable to the current code. Not re-posted here to avoid duplication.

Scope: incremental — only the Design Arena endpoint is net-new since the prior review
Review: tier=large · model=claude-opus-latest · score=867.1

@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.4.1 → 0.4.2: adds Observability, Presets, BYOK, Datasets, STT and Beta Analytics operation groups, an additive Messages fallbacks field, and error.OpenrouterMetadata across many ops — but ships ~15 breaking API changes under a patch version bump and re-introduces no fixes for the previously-flagged streaming/pagination context-cancellation bugs.

Verdict: 🔁 Needs changes

Details

Scope: incremental — only ~137 new lines since my prior review (the additive Messages fallbacks field + its generated param type). The rest of the diff is unchanged from the SHA I last reviewed.

Risk: 🔴 High — human approval required (touches the streaming/SSE response path and ships a breaking public API surface change)

CI: no checks reported on the head commit (no required checks configured on this repo).

What changed since my last review (in-scope, clean):

  • New optional fallbacks field on the Messages request (OptionalNullable, omitzero) + a generated MessagesFallbackParam type. Purely additive, existing constructors unaffected — no new findings.

Standing blockers — still unaddressed (18 open review threads from prior rounds):

  • Streaming context cancellationdefer cancel() on the timeout context fires when Send() returns, cancelling the context the returned EventStream still reads from. Any configured SDK/operation timeout makes streaming fail immediately with context canceled. Affects both the chat and responses streaming paths. (Confirmed against Go context semantics — see Research.)
  • Pagination context cancellation — the same defer cancel() pattern cancels the context captured by the Next() pagination closure in the new BYOK, Observability and Datasets list operations; calling Next() after the first call fails once a timeout is configured.
  • Pagination never terminates / overshoots — the Next() termination check (len(arr) < limit) never fires when limit is nil, and offset can advance past the API maximum after a full final page (400 instead of clean end).
  • Breaking type renames without aliases — the Reasoning/Effort types (and a function-call output type) were renamed, breaking every caller referencing the old components.* identifiers, with no compatibility alias.
  • Breaking method signatures from maxMethodParams: 4 — the param-count generator setting is the root cause of recurring breaking Send() signature churn on every regen; setting it to 0 produces a stable request-struct-only signature.
  • Doc examples reference non-existent stream fields — several README/SDK-doc SSE snippets reference response stream fields that do not exist on the generated response structs (and omit the stream flag), so the examples will not compile.

Versioning (root cause): Speakeasy versioningStrategy: automatic derives the bump from generator + OpenAPI + config deltas, taking the largest. The OpenAPI changes here are breaking, yet the release landed as patch (0.4.1 → 0.4.2, PR labelled patch). For a pre-1.0 SDK Speakeasy downgrades a detected major to a minor — so the correct bump for these breaking changes is 0.5.0, not a patch. A patch release carrying breaking changes violates SemVer expectations downstream consumers rely on.

Codex (gpt-5.5): surfaced only the SSE doc-field and Datasets pagination-overshoot issues — both already covered by the standing open threads above. No net-new findings.

Research: Speakeasy SDK versioning docs (largest-of-three-inputs bump; pre-1.0 major→minor downgrade) and Go context cancellation semantics (defer cancel before a streamed body read yields context canceled) — both confirm the standing findings.

Security: secret scan over added lines — no committed credentials. Streaming/SSE response path touched (category 2); the cancellation bug is a correctness issue, not an exfiltration vector.

Test coverage: generated SDK with test generation disabled in gen.yaml; the context-cancellation and pagination bugs have no regression coverage.

Unresolved threads: 18 open — all prior Perry findings listed above. No new inline comments posted this round (the only new code since my last review is the additive fallbacks field, which is clean); re-posting the standing findings would duplicate the existing open threads.

Scope: incremental — ~137 new lines since prior review

Review: tier=large · model=claude-opus-latest · score=866.80.0

@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 to v0.4.2 — adds the BYOK, Observability, Presets, STT, BetaAnalytics, and Design-Arena / Artificial-Analysis benchmark surfaces, plus new ChatRequest sampling params (min_p, top_a, top_k, repetition_penalty, reasoning_effort). Ships breaking API changes under a patch version bump.

Verdict: 🔁 Needs changes

Details

Risk: 🔴 High — human approval required (breaking public-API change shipped under a patch tag; immutable once published to the Go module proxy).

CI: no checks configured on the head SHA — not an approval gate.

Scope: incremental re-review. Since the last reviewed SHA (701cc28) the only changes are 3 generated model files: models/components/chatrequest.go (+72), models/components/aabenchmarkentry.go (new), and models/components/modelbenchmarks.go (+30/-3). All new lines are clean additive generated code — new optional sampling fields plus their getters, and the AABenchmarkEntry type wired into ModelBenchmarks. No new findings on the delta.

Standing blockers — unchanged since the last review; see the existing inline threads, none resolved:

  • 🔴 Breaking changes shipped under a patch bump (0.4.1 → 0.4.2). For a pre-1.0 SDK a breaking change should be a minor bump (0.5.0). chat.go and responses.go Send gained a positional xOpenRouterMetadata param; Effort → ChatRequestEffort, Reasoning → ChatRequestReasoning, Category → GetModelsCategory, and FunctionCallOutputItemOutputType were renamed — every downstream consumer that compiled against 0.4.1 breaks. Root cause: Speakeasy only escalates the bump when the OpenAPI info.version carries a SemVer increment; bump info.version upstream so the regen produces 0.5.0.
  • 🔴 In .speakeasy/gen.yaml, maxMethodParams: 4 is the structural root cause of the recurring breaking-signature churn — set it to 0 to force request objects so future param additions stay non-breaking.
  • 🟡 Streaming defer-cancel in chat.go and responses.go cancels the timeout context before the caller reads the EventStream. This is pre-existing generated boilerplate, not introduced here, but still active and unaddressed.
  • 🟡 Pagination defer-cancel plus nil-limit termination in the new byok.go, datasets.go, observability.go, and presets.go: the Next closure captures a context the parent's defer-cancel has already cancelled, and the len(arr) < l guard never fires when limit is nil.

Codex (HEAVY_SECONDARY_MODEL): no additional findings — the analysis hit the time cap on this 88k-LoC diff and produced no usable output.

Research: Speakeasy versioning docs (https://www.speakeasy.com/docs/sdks/manage/versioning) — pre-1.0 breaking changes downgrade to a minor bump, and the bump is driven by the OpenAPI info.version SemVer delta (not content analysis), so a config-only checksum change yields just a patch. Speakeasy methods docs (https://www.speakeasy.com/docs/sdks/customize/methods) — maxMethodParams: 0 forces a request object, making future field additions backward-compatible. Go context docs (https://pkg.go.dev/context) confirm the defer-cancel streaming footgun: the context's lifetime must fully contain the body read.

Security: no concerns — the diff is generated SDK plus docs; no real secrets (BYOK key fields are masked, e.g. label "sk-...AbCd"), no hand-written auth or validation logic.

Test coverage: generated SDK — no unit tests in the diff; correctness is governed by the OpenAPI spec and generator config, which is why the versioning and maxMethodParams fixes belong upstream.

Unresolved threads: ~13 active Perry threads from prior rounds remain open and unaddressed — they are the standing blockers above. This incremental re-review adds no new inline comments because the new delta is clean.

Scope: incremental — 0 new findings since prior review (delta is 3 clean generated files)
Review: tier=large · model=claude-opus-latest · score=884.0

@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.4.1 to 0.4.2) that adds a new Artificial Analysis benchmarks endpoint and regenerates the full client; the new endpoint is clean, but several breaking API changes from prior pushes remain unaddressed and are still shipped under a patch bump.

Verdict: 🔁 Needs changes

Details

Risk: 🔴 High — human approval required (touches the streaming response path and ships breaking public-API changes)

CI: no checks configured on this repo (0 check runs, 0 statuses on the head commit)

What's new since my last review (incremental scope): the only net-new code is the Artificial Analysis benchmarks endpoint — a new GetBenchmarksArtificialAnalysis method on Datasets plus its generated models (BenchmarksAAItem / BenchmarksAAMeta / BenchmarksAAResponse) and docs. This delta is clean: a standard generated non-streaming GET, proper OptionalNullable handling, no new footguns. ✅

Standing blockers (carried forward — already have open review threads, not re-posted inline to avoid duplicate spam):

  • Breaking Chat.Send / Responses.Send signature change — a new positional metadata parameter (see the two inline comments on this push; the parameter was renamed from the earlier ExperimentalMetadata form but remains breaking).
  • Breaking type renames with no compatibility aliases: Effort to ChatRequestEffort, Reasoning to ChatRequestReasoning, and FunctionCallOutputItemOutputType renamed (existing unresolved threads on the chatrequest and functioncalloutputitem components).
  • The deferred cancel cancels the streaming context before the caller reads the returned EventStream, in both the chat and responses send paths (existing unresolved threads). This is a well-documented Go gotcha — the timeout context is torn down on function return while the body is still being streamed.
  • Pagination Next closures capture a context that the parent's deferred cancel tears down, and never terminate when limit is nil (the local limit defaults to 0, so the len-less-than-limit guard never fires) — existing unresolved threads on the byok, observability, and datasets pagination paths.
  • Root cause of the recurring signature breakage: maxMethodParams is set to 4 in the Speakeasy generator config, which flattens added OpenAPI parameters straight into method signatures (existing unresolved thread on the generator config).
  • A patch version bump (0.4.1 to 0.4.2) understates these breaking changes; per pre-1.0 SemVer convention this should be a 0.5.0 minor.

Codex (gpt-5.5): 2 findings surfaced; both rejected on verification — one (a datasets pagination nil-deref panic) is a false positive (the code uses OptionalNullable Get with a proper nil guard), the other (analytics rows generated as empty structs from a bare object schema) is a real modeling weakness but is pre-existing on the prior reviewed commit and outside this push's delta.

Research: SemVer 2.0.0 section 4 — the pre-1.0 convention treats minor as the breaking indicator and patch as backward-compatible (and Go/npm caret plus patch-level upgrades auto-resolve patch bumps, so a breaking patch silently reaches consumers). Speakeasy docs confirm setting maxMethodParams to 0 forces a request-object signature so added params are non-breaking. Go context docs and community guidance confirm the deferred-cancel-before-stream-read pattern cancels the request as soon as the function returns.

Security: streaming response path touched (Step 6c category 2) — no credential-exposure or injection concerns; the streaming finding is a correctness/reliability bug, not a security one. No secrets detected in the diff.

Test coverage: generated SDK; no unit tests accompany the regenerated client paths. The breaking-signature and context-cancellation issues would not be caught by any test in this repo.

Unresolved threads: ~16 active Perry threads from prior review rounds remain open, covering the standing blockers above. They are intentionally not duplicated here.

Scope: incremental — additive AA-benchmarks endpoint since prior reviewed commit 41a95fa; standing blockers carried forward
Review: tier=large · model=claude-opus-latest · score=881.9

Comment thread chat.go
// Send - Create a chat completion
// Sends a request for a model response for the given chat conversation. Supports both streaming and non-streaming modes.
func (s *Chat) Send(ctx context.Context, request components.ChatRequest, opts ...operations.Option) (*operations.SendChatCompletionRequestResponse, error) {
func (s *Chat) Send(ctx context.Context, chatRequest components.ChatRequest, xOpenRouterMetadata *components.MetadataLevel, opts ...operations.Option) (*operations.SendChatCompletionRequestResponse, error) {

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] Chat.Send adds a new positional xOpenRouterMetadata *components.MetadataLevel parameter — breaks every existing caller, shipped under a patch bump (0.4.1 → 0.4.2).

Details

Why: The signature went from Send(ctx, request, opts...) to Send(ctx, chatRequest, xOpenRouterMetadata, opts...). Any consumer calling client.Chat.Send(ctx, req) now fails to compile — xOpenRouterMetadata is positional (before the variadic opts), not optional. For a pre-1.0 SDK, SemVer convention treats the minor digit as the breaking-change indicator and the patch digit as backward-compatible; Go module consumers on v0.4.x will silently pull this via go get -u=patch. This is the recurring root cause flagged across prior reviews: maxMethodParams: 4 in .speakeasy/gen.yaml flattens added OpenAPI params straight into the method signature.

Fix: Set maxMethodParams: 0 in .speakeasy/gen.yaml so Speakeasy always generates a single request object (new fields become non-breaking additions), and cut this release as 0.5.0 (minor) rather than 0.4.2 (patch).

Ref: Speakeasy — Customize methods (maxMethodParams) · SemVer 2.0.0 §4 (0.x.y)

Prompt for agents
In .speakeasy/gen.yaml set `maxMethodParams: 0` (currently 4) so the Go generator emits a single request-object parameter for every method instead of flattening OpenAPI parameters into positional args. Regenerate the SDK. This restores a stable `Chat.Send(ctx, request, opts...)` / `Responses.Send(ctx, request, opts...)` signature and makes future parameter additions non-breaking. Additionally, bump the release version in .speakeasy/gen.yaml and gen.lock from 0.4.2 to 0.5.0 (minor), since the change set still carries breaking API changes and a pre-1.0 patch bump understates that.

Reviewed at f1bba19

Comment thread responses.go
@@ -35,7 +35,12 @@ func newResponses(rootSDK *OpenRouter, sdkConfig config.SDKConfiguration, hooks

// Send - Create a response
// Creates a streaming or non-streaming response using OpenResponses API format
func (s *Responses) Send(ctx context.Context, request components.ResponsesRequest, opts ...operations.Option) (*operations.CreateResponsesResponse, error) {
func (s *Responses) Send(ctx context.Context, responsesRequest components.ResponsesRequest, xOpenRouterMetadata *components.MetadataLevel, opts ...operations.Option) (*operations.CreateResponsesResponse, error) {

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] Responses.Send — same breaking positional xOpenRouterMetadata *components.MetadataLevel parameter as Chat.Send, under a patch bump.

Details

Why: Identical failure mode to the Chat.Send finding: a new positional parameter inserted before the variadic opts ...operations.Option breaks every existing Responses.Send(ctx, req) call site. Same root cause (maxMethodParams: 4), same SemVer concern (breaking change shipped as 0.4.1 → 0.4.2 patch).

Fix: Addressed by the same maxMethodParams: 0 + 0.5.0 minor-bump remedy described on the Chat.Send comment — no separate change needed here once the generator config is fixed and the SDK is regenerated.

Ref: Speakeasy — Customize methods (maxMethodParams)

Prompt for agents
This is the same issue as the Chat.Send blocker — fixing `maxMethodParams: 0` in .speakeasy/gen.yaml and regenerating the SDK resolves both Send signatures at once. No file-specific edit to responses.go is required; it is generated output. Verify after regeneration that Responses.Send returns to a `Send(ctx, request, opts...)` shape.

Reviewed at f1bba19

@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.4.2 — this push adds a generated web-search server-tool model family (WebSearchServerTool + preview/legacy variants, WebSearchEngineEnum, WebSearchConfig, ChatWebSearchShorthand, SearchQualityLevel) and wires them into the existing tool unions.

Verdict: 🔁 Needs changes

Details

Incremental re-review — 6th review of this PR. Only the ~62 new lines since my last pass (the web-search tool types + lock/spec updates) are in scope here; I did not re-litigate code I reviewed on prior pushes.

New since last review (in scope) — clean ✅:

  • 10 new generated files (5 Go types + 5 docs) modelling the OpenRouter web-search server tool. Verified the whole module compiles cleanly (go build over all packages), and the new types are correctly spliced into OpenResponsesResultToolUnion and ChatFunctionToolUnion.
  • The generated surface faithfully matches the documented OpenRouter web-search API: engines auto/native/exa/firecrawl/parallel/perplexity, max_results / max_total_results, search_context_size (low/medium/high), allowed/excluded domain filters (mutually exclusive), max_characters precedence, and user_location. No new findings.
  • Note: two engine enums now coexist — WebSearchEngine (no "auto", used by the legacy WebSearchPlugin) and WebSearchEngineEnum (with "auto", used by the new server tools). This mirrors the real API distinction and is generated correctly, not a defect.

Standing blockers (unchanged — 20 unresolved threads from prior pushes):

  • Breaking Send-signature change (new positional metadata param on Chat.Send / Responses.Send) and the Effort/Reasoning → ChatRequestEffort/ChatRequestReasoning type renames are still shipping under a patch bump (0.4.2). Per Speakeasy's own rules a breaking change on a pre-v1 Go SDK should bump minor (0.5.0), not patch. Root cause remains the maxMethodParams=4 generator config.
  • The defer cancel() streaming/pagination footguns flagged previously remain present.
  • See the existing unresolved review threads for the full inline detail + fixes — I have not re-posted them to avoid duplicate noise.

CI: no checks reported on the head commit.

Codex (HEAVY_SECONDARY_MODEL): findings surfaced (datasets.go pagination, README SSE example) all fall in already-reviewed code with open threads — not re-raised.

Research: Speakeasy SDK versioning docs (Go SDKs downgrade major→minor; breaking change ⇒ minor for pre-v1) and the OpenRouter web-search server-tool API reference — the new types match the spec.

Security: no concerns — secret scan clean; delta is additive generated config types with no auth/streaming/logging code.

Test coverage: generated SDK; no hand-written tests in the delta (expected for codegen output).

Unresolved threads: 20 open Perry threads carrying the standing breaking-change + lifecycle blockers above.

Scope: incremental — ~62 new lines since prior review
Review: tier=large · model=claude-opus-latest · score=883.1

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

perry-the-pr-reviewer[bot]

This comment was marked as outdated.

* `OpenRouter.Chat.Send()`: 
  *  `request` **Changed** (Breaking ⚠️)
  *  `response` **Changed**
  *  `error` **Changed**
* `OpenRouter.VideoGeneration.Generate()`: 
  *  `request.Request` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Beta.Responses.Send()`: 
  *  `request` **Changed** (Breaking ⚠️)
  *  `response` **Changed** (Breaking ⚠️)
  *  `error` **Changed**
* `OpenRouter.Rerank.Rerank()`: 
  *  `request.Request` **Changed** (Breaking ⚠️)
  *  `response.Results[].Document` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Models.ListForUser()`: 
  *  `response.Data[]` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Models.List()`: 
  *  `request` **Changed** (Breaking ⚠️)
  *  `response.Data[]` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Generations.GetGeneration()`: 
  *  `response.Data` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Endpoints.List()`: 
  *  `response.Data` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Endpoints.ListZdrEndpoints()`: 
  *  `response.Data[].ProviderName` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Embeddings.ListModels()`: 
  *  `response.Data[]` **Changed** (Breaking ⚠️)
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Embeddings.Generate()`: 
  *  `request.Request` **Changed** (Breaking ⚠️)
  *  `response.Usage.PromptTokensDetails.FileTokens` **Added**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Observability.Create()`: **Added**
* `OpenRouter.Guardrails.Delete()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Files.Upload()`: **Added**
* `OpenRouter.Files.Delete()`: **Added**
* `OpenRouter.Files.Retrieve()`: **Added**
* `OpenRouter.Files.Download()`: **Added**
* `OpenRouter.Models.Get()`: **Added**
* `OpenRouter.Observability.List()`: **Added**
* `OpenRouter.Beta.Analytics.GetAnalyticsMeta()`: **Added**
* `OpenRouter.Observability.Delete()`: **Added**
* `OpenRouter.Observability.Get()`: **Added**
* `OpenRouter.Observability.Update()`: **Added**
* `OpenRouter.Presets.List()`: **Added**
* `OpenRouter.Presets.Get()`: **Added**
* `OpenRouter.Presets.CreatePresetsChatCompletions()`: **Added**
* `OpenRouter.Presets.CreatePresetsMessages()`: **Added**
* `OpenRouter.Presets.CreatePresetsResponses()`: **Added**
* `OpenRouter.Presets.ListVersions()`: **Added**
* `OpenRouter.Presets.GetVersion()`: **Added**
* `OpenRouter.Analytics.GetUserActivity()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Tts.CreateSpeech()`: 
  *  `request.Request.Provider.Options` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.OAuth.ExchangeAuthCodeForApiKey()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.OAuth.CreateAuthCode()`: 
  *  `request.Request.WorkspaceId` **Added**
  *  `error` **Changed**
* `OpenRouter.Datasets.GetRankingsDaily()`: **Added**
* `OpenRouter.Credits.GetCredits()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Datasets.GetBenchmarksDesignArena()`: **Added**
* `OpenRouter.Datasets.GetBenchmarksArtificialAnalysis()`: **Added**
* `OpenRouter.Datasets.GetAppRankings()`: **Added**
* `OpenRouter.Byok.Update()`: **Added**
* `OpenRouter.Byok.Get()`: **Added**
* `OpenRouter.Generations.ListGenerationContent()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.List()`: 
  *  `response.Data[]` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.Create()`: 
  *  `request.Request` **Changed**
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Files.List()`: **Added**
* `OpenRouter.Guardrails.Get()`: 
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.Update()`: 
  *  `request.UpdateGuardrailRequest` **Changed**
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.ListGuardrailKeyAssignments()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.BulkAssignKeys()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.BulkUnassignKeys()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.ListGuardrailMemberAssignments()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.BulkAssignMembers()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.BulkUnassignMembers()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.ListKeyAssignments()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Guardrails.ListMemberAssignments()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.GetCurrentKeyMetadata()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.List()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.Create()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.Delete()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.Get()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.ApiKeys.Update()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Byok.Delete()`: **Added**
* `OpenRouter.Models.Count()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Byok.Create()`: **Added**
* `OpenRouter.Organization.ListMembers()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Providers.List()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Byok.List()`: **Added**
* `OpenRouter.Stt.CreateTranscription()`: **Added**
* `OpenRouter.Beta.Analytics.QueryAnalytics()`: **Added**
* `OpenRouter.VideoGeneration.GetGeneration()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.VideoGeneration.GetVideoContent()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.VideoGeneration.ListVideosModels()`: 
  *  `response.Data[]` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.List()`: 
  *  `response.Data[]` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.Create()`: 
  *  `request.Request` **Changed**
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.Delete()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.Get()`: 
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.Update()`: 
  *  `request.UpdateWorkspaceRequest` **Changed**
  *  `response.Data` **Changed**
  *  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.BulkAddMembers()`:  `error.OpenrouterMetadata` **Added**
* `OpenRouter.Workspaces.BulkRemoveMembers()`:  `error.OpenrouterMetadata` **Added**

@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 regen to SDK v0.5.0 (newer CLI 1.778.0); since my last review at 45df551 the branch was force-pushed — the genuinely new code is a clean 67-file / +404-292 delta of internals fixes, but the 22 findings I previously raised are all still present and unaddressed at HEAD.

Verdict: 💬 Comments / questions

Details

Risk: 🔴 High — human approval required (touches the streaming/SSE response path + ships breaking public-API signatures under a "minor" label)

CI: none reported on de4d404 (commit status pending/empty)

What changed since my last review (force-push 45df551de4d404):

  • 🟢 types/stream/stream.go — SSE scanner now sets a 1 GiB scanner.Buffer and a stateful splitter that only re-scans the trailing 3 bytes. This fixes a real latent bug: the old bufio.NewScanner used the default 64 KiB token cap, so any single SSE event > 64 KiB would have failed with bufio.Scanner: token too long. Verified correct against the W3C EventSource boundary rules. ✅
  • 🟢 internal/utils/union.gocountFieldsRecursive no longer calls .Elem()/.IsNil() unconditionally on union variants, fixing a panic on non-pointer variants (slice/map/any). Backed by a new table-driven test (TestPickBestUnionCandidate_NonPointerUnionVariants). ✅
  • 🟢 internal/utils/json.go — map fields implementing json.Unmarshaler now delegate to the custom unmarshaler. ✅
  • 🟢 models/components/urlcitation.go — additive Content *string field + GetContent(). ✅
  • 🟢 service files: explicit status-code error lists (["400","401",…,"524","529",…]) collapsed to ["4XX","5XX"]. Verified semantically equivalent via MatchStatusCodes (wildcard 4XX/5XX covers every previously-enumerated code, including the non-standard 524/529). ✅
  • 🟡 go.modgo 1.22go 1.25.10 (see inline comment).

Both the build (go build) and the unit tests for the changed packages pass in the worktree.

Findings (1 net-new; see inline comment):

  • 🟡 go.mod:3 — full-patch version floor go 1.25.10 over-constrains SDK consumers.

Still-open prior findings (unchanged by this force-push — 22 threads): breaking positional xOpenRouterMetadata on Chat.Send/Responses.Send; defer cancel() cancelling the streaming context before the caller reads it (chat.go:79, responses.go:80); pagination Next() non-termination (byok.go, observability.go, datasets.go); Reasoning/Effort type renames; empty QueryAnalyticsData1; maxMethodParams: 4 as the recurring root cause of breaking signatures. None were addressed — they were re-emitted verbatim by the regen.

Codex (gpt-5.5): 2 findings (QueryAnalytics empty struct; GetAppRankings offset overrun) — both already on record in the prior threads; no net-new.

Research: Go module go directive semantics (go.dev/ref/mod — full-patch floor vs language-version family); W3C/WHATWG SSE boundary + Go bufio.Scanner 64 KiB ErrTooLong — confirms the stream change is a genuine fix.

Security: streaming/SSE path touched (Step 6c cat. 2) — change is a robustness fix, no exfiltration/validation-bypass surface; no secrets in the delta.

Test coverage: new union behaviour covered; the SSE splitter has no in-repo test (types/stream has no _test.go).

Unresolved threads: 22 (all Perry-authored, all still applicable at HEAD).

Scope: incremental — ~404 new lines since prior review (force-push)
Review: tier=large · model=claude-opus-latest · score=937.7

Comment thread go.mod
@@ -1,6 +1,6 @@
module github.com/OpenRouterTeam/go-sdk

go 1.22
go 1.25.10

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] go 1.25.10 — pinning a full patch version as the module floor forces every SDK consumer onto Go ≥ 1.25.10

Details

Why: Since Go 1.21 the go directive is a hard minimum, not advisory — a toolchain older than the declared version refuses to build the module (go: go.mod requires go >= 1.25.10). The patch-level form 1.25.10 is the strictest possible floor: a consumer on Go 1.25.9 (or any earlier 1.25.x) cannot build this SDK at all, even though there are no language features here that need 1.25.10 specifically. This jumped from go 1.22 in one regen and ships under a minor-labeled 0.5.0 release, so it is an unannounced, consumer-affecting toolchain requirement.

For a published library the idiomatic choice is the language-version form (go 1.25, or even keep go 1.22 if no ≥1.23 language features are actually used), which permits any patch in that family, and a separate toolchain directive if a specific build version is desired. The patch-pinned floor is a generator artifact, not a deliberate compatibility decision — worth confirming the bump is intended.

Fix:

go 1.25

(or restore go 1.22 if no 1.23+ language features are used; add toolchain go1.25.10 separately only if you want to suggest — not require — that exact build version)

Ref: Go Modules Reference — go directive & version syntax · Go Toolchains

Prompt for agents
In go.mod:3, the `go` directive was changed from `go 1.22` to `go 1.25.10`. A full-patch-version floor forces every consumer of this SDK onto Go >= 1.25.10 and breaks builds on any earlier 1.25.x. If this strict floor is not intentional, change it to the language-version form `go 1.25` (permits any 1.25.x patch), or restore `go 1.22` if no Go 1.23+ language features are used. If a specific build toolchain is genuinely desired, express it via a separate `toolchain go1.25.10` directive rather than raising the consumer-facing minimum. This is a Speakeasy generator setting — check `.speakeasy/gen.yaml` / the generation config for what controls the emitted go version.

Reviewed at de4d404

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants