@@ -4573,6 +4573,207 @@ describe("openai transport stream", () => {
45734573 expect ( params . tools ?. [ 0 ] ) . not . toHaveProperty ( "strict" ) ;
45744574 } ) ;
45754575
4576+ it ( "skips unreadable tools before building OpenAI Responses params" , ( ) => {
4577+ const unreadableNameTool = {
4578+ get name ( ) : string {
4579+ throw new Error ( "boom name" ) ;
4580+ } ,
4581+ description : "Bad" ,
4582+ parameters : { } ,
4583+ } ;
4584+ const unreadableParametersTool = {
4585+ name : "bad_parameters" ,
4586+ description : "Bad" ,
4587+ get parameters ( ) : unknown {
4588+ throw new Error ( "boom parameters" ) ;
4589+ } ,
4590+ } ;
4591+ const params = buildOpenAIResponsesParams (
4592+ {
4593+ id : "gpt-5.5" ,
4594+ name : "GPT-5.5" ,
4595+ api : "openai-responses" ,
4596+ provider : "openai" ,
4597+ baseUrl : "https://api.openai.com/v1" ,
4598+ reasoning : true ,
4599+ input : [ "text" ] ,
4600+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
4601+ contextWindow : 200000 ,
4602+ maxTokens : 8192 ,
4603+ } satisfies Model < "openai-responses" > ,
4604+ {
4605+ systemPrompt : "system" ,
4606+ messages : [ ] ,
4607+ tools : [
4608+ unreadableNameTool ,
4609+ {
4610+ name : "healthy_lookup" ,
4611+ description : "Lookup" ,
4612+ parameters : { } ,
4613+ } ,
4614+ unreadableParametersTool ,
4615+ ] ,
4616+ } as never ,
4617+ undefined ,
4618+ ) as { tools ?: Array < { name ?: string } > } ;
4619+
4620+ expect ( params . tools ?. map ( ( tool ) => tool . name ) ) . toEqual ( [ "healthy_lookup" ] ) ;
4621+ } ) ;
4622+
4623+ it ( "drops pinned OpenAI Responses tool choice when that tool is unreadable" , ( ) => {
4624+ const unreadablePinnedTool = {
4625+ name : "bad_parameters" ,
4626+ description : "Bad" ,
4627+ get parameters ( ) : unknown {
4628+ throw new Error ( "boom parameters" ) ;
4629+ } ,
4630+ } ;
4631+ const params = buildOpenAIResponsesParams (
4632+ {
4633+ id : "gpt-5.5" ,
4634+ name : "GPT-5.5" ,
4635+ api : "openai-responses" ,
4636+ provider : "openai" ,
4637+ baseUrl : "https://api.openai.com/v1" ,
4638+ reasoning : true ,
4639+ input : [ "text" ] ,
4640+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
4641+ contextWindow : 200000 ,
4642+ maxTokens : 8192 ,
4643+ } satisfies Model < "openai-responses" > ,
4644+ {
4645+ systemPrompt : "system" ,
4646+ messages : [ ] ,
4647+ tools : [
4648+ unreadablePinnedTool ,
4649+ {
4650+ name : "healthy_lookup" ,
4651+ description : "Lookup" ,
4652+ parameters : { } ,
4653+ } ,
4654+ ] ,
4655+ } as never ,
4656+ {
4657+ toolChoice : { type : "function" , name : "bad_parameters" } ,
4658+ } ,
4659+ ) as { tools ?: Array < { name ?: string } > ; tool_choice ?: unknown } ;
4660+
4661+ expect ( params . tools ?. map ( ( tool ) => tool . name ) ) . toEqual ( [ "healthy_lookup" ] ) ;
4662+ expect ( params . tool_choice ) . toBeUndefined ( ) ;
4663+ } ) ;
4664+
4665+ it ( "drops forced OpenAI Responses tool choice when every tool is unreadable" , ( ) => {
4666+ const unreadableTool = {
4667+ name : "bad_parameters" ,
4668+ description : "Bad" ,
4669+ get parameters ( ) : unknown {
4670+ throw new Error ( "boom parameters" ) ;
4671+ } ,
4672+ } ;
4673+ const params = buildOpenAIResponsesParams (
4674+ {
4675+ id : "gpt-5.5" ,
4676+ name : "GPT-5.5" ,
4677+ api : "openai-responses" ,
4678+ provider : "openai" ,
4679+ baseUrl : "https://api.openai.com/v1" ,
4680+ reasoning : true ,
4681+ input : [ "text" ] ,
4682+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
4683+ contextWindow : 200000 ,
4684+ maxTokens : 8192 ,
4685+ } satisfies Model < "openai-responses" > ,
4686+ {
4687+ systemPrompt : "system" ,
4688+ messages : [ ] ,
4689+ tools : [ unreadableTool ] ,
4690+ } as never ,
4691+ {
4692+ toolChoice : "required" ,
4693+ } ,
4694+ ) as { tools ?: unknown [ ] ; tool_choice ?: unknown } ;
4695+
4696+ expect ( params . tools ) . toBeUndefined ( ) ;
4697+ expect ( params . tool_choice ) . toBeUndefined ( ) ;
4698+ } ) ;
4699+
4700+ it ( "drops forced OpenAI completions tool choice when every tool is unreadable" , ( ) => {
4701+ const unreadableTool = {
4702+ name : "bad_parameters" ,
4703+ description : "Bad" ,
4704+ get parameters ( ) : unknown {
4705+ throw new Error ( "boom parameters" ) ;
4706+ } ,
4707+ } ;
4708+ const params = buildOpenAICompletionsParams (
4709+ {
4710+ id : "gpt-5.5" ,
4711+ name : "GPT-5.5" ,
4712+ api : "openai-completions" ,
4713+ provider : "openai" ,
4714+ baseUrl : "https://api.openai.com/v1" ,
4715+ reasoning : false ,
4716+ input : [ "text" ] ,
4717+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
4718+ contextWindow : 200000 ,
4719+ maxTokens : 8192 ,
4720+ } satisfies Model < "openai-completions" > ,
4721+ {
4722+ systemPrompt : "system" ,
4723+ messages : [ ] ,
4724+ tools : [ unreadableTool ] ,
4725+ } as never ,
4726+ {
4727+ toolChoice : "required" ,
4728+ } ,
4729+ ) as { tools ?: unknown [ ] ; tool_choice ?: unknown } ;
4730+
4731+ expect ( params . tools ) . toBeUndefined ( ) ;
4732+ expect ( params . tool_choice ) . toBeUndefined ( ) ;
4733+ } ) ;
4734+
4735+ it ( "drops pinned OpenAI completions tool choice when that tool is unreadable" , ( ) => {
4736+ const unreadablePinnedTool = {
4737+ name : "bad_parameters" ,
4738+ description : "Bad" ,
4739+ get parameters ( ) : unknown {
4740+ throw new Error ( "boom parameters" ) ;
4741+ } ,
4742+ } ;
4743+ const params = buildOpenAICompletionsParams (
4744+ {
4745+ id : "gpt-5.5" ,
4746+ name : "GPT-5.5" ,
4747+ api : "openai-completions" ,
4748+ provider : "openai" ,
4749+ baseUrl : "https://api.openai.com/v1" ,
4750+ reasoning : false ,
4751+ input : [ "text" ] ,
4752+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
4753+ contextWindow : 200000 ,
4754+ maxTokens : 8192 ,
4755+ } satisfies Model < "openai-completions" > ,
4756+ {
4757+ systemPrompt : "system" ,
4758+ messages : [ ] ,
4759+ tools : [
4760+ unreadablePinnedTool ,
4761+ {
4762+ name : "healthy_lookup" ,
4763+ description : "Lookup" ,
4764+ parameters : { } ,
4765+ } ,
4766+ ] ,
4767+ } as never ,
4768+ {
4769+ toolChoice : { type : "function" , function : { name : "bad_parameters" } } ,
4770+ } ,
4771+ ) as { tools ?: Array < { function ?: { name ?: string } } > ; tool_choice ?: unknown } ;
4772+
4773+ expect ( params . tools ?. map ( ( tool ) => tool . function ?. name ) ) . toEqual ( [ "healthy_lookup" ] ) ;
4774+ expect ( params . tool_choice ) . toBeUndefined ( ) ;
4775+ } ) ;
4776+
45764777 it ( "still normalizes responses tool parameters when strict is omitted" , ( ) => {
45774778 const params = buildOpenAIResponsesParams (
45784779 {
0 commit comments