@@ -244,6 +244,60 @@ describe("OpenAiHandler - Codex model detection", () => {
244244 expect ( input [ 3 ] . type ) . toBe ( "function_call_output" )
245245 expect ( input [ 3 ] . output ) . toBe ( "2" )
246246 } )
247+
248+ it ( "converts tools to the flat Responses API schema (not nested under `function`)" , async ( ) => {
249+ handler = new OpenAiHandler ( {
250+ openAiApiKey : "test-key" ,
251+ openAiModelId : "gpt-5.3-codex" ,
252+ openAiBaseUrl : "https://test.openai.azure.com/openai/deployments/gpt5.3" ,
253+ openAiUseAzure : true ,
254+ } )
255+
256+ mockResponsesCreate . mockResolvedValue ( {
257+ [ Symbol . asyncIterator ] : async function * ( ) {
258+ yield { type : "response.done" , response : { usage : { input_tokens : 1 , output_tokens : 1 } } }
259+ } ,
260+ } )
261+
262+ const messages : Anthropic . Messages . MessageParam [ ] = [ { role : "user" , content : "Hi" } ]
263+ // Chat Completions nested tool shape (what the rest of the handler receives).
264+ const tools = [
265+ {
266+ type : "function" ,
267+ function : {
268+ name : "calculator" ,
269+ description : "Evaluate a math expression" ,
270+ parameters : {
271+ type : "object" ,
272+ properties : { expression : { type : "string" } } ,
273+ required : [ "expression" ] ,
274+ } ,
275+ } ,
276+ } ,
277+ ]
278+
279+ for await ( const _chunk of handler . createMessage ( "You are helpful" , messages , {
280+ taskId : "test" ,
281+ tools,
282+ } as any ) ) {
283+ // Consume the stream so responses.create is invoked.
284+ }
285+
286+ const requestBody = mockResponsesCreate . mock . calls [ 0 ] [ 0 ]
287+ expect ( Array . isArray ( requestBody . tools ) ) . toBe ( true )
288+ expect ( requestBody . tools ) . toHaveLength ( 1 )
289+
290+ const tool = requestBody . tools [ 0 ]
291+ // Flat structure: fields live at the top level, not under `function`.
292+ expect ( tool . type ) . toBe ( "function" )
293+ expect ( tool . name ) . toBe ( "calculator" )
294+ expect ( tool . description ) . toBe ( "Evaluate a math expression" )
295+ expect ( tool . function ) . toBeUndefined ( )
296+ expect ( tool . parameters ) . toBeDefined ( )
297+ expect ( tool . parameters . properties ) . toBeDefined ( )
298+ // Non-MCP tools are sent with strict schema validation enabled.
299+ expect ( tool . strict ) . toBe ( true )
300+ } )
247301 } )
248302
249303 describe ( "createMessage codex tool call streaming" , ( ) => {
0 commit comments