@@ -38,14 +38,7 @@ function validateResponsesRequest(body) {
3838 if ( body . max_output_tokens != null && ( ! Number . isInteger ( body . max_output_tokens ) || body . max_output_tokens < 1 ) ) {
3939 throw invalid ( "max_output_tokens must be a positive integer" , "max_output_tokens" ) ;
4040 }
41- if ( Array . isArray ( body . tools ) ) {
42- body . tools . forEach ( ( tool , index ) => {
43- if ( ! isObject ( tool ) || typeof tool . type !== "string" ) throw invalid ( "Each tool must be an object with a type" , `tools[${ index } ]` ) ;
44- if ( tool . type === "function" && ( typeof tool . name !== "string" || ! tool . name ) ) {
45- throw invalid ( "Function tools require a name" , `tools[${ index } ].name` ) ;
46- }
47- } ) ;
48- }
41+ if ( Array . isArray ( body . tools ) ) validateTools ( body . tools , "tools" ) ;
4942 if ( Array . isArray ( body . input ) ) {
5043 body . input . forEach ( ( item , index ) => validateInputItem ( item , `input[${ index } ]` ) ) ;
5144 }
@@ -88,8 +81,22 @@ function reasoningItemsFromCall(call) {
8881 return Array . isArray ( items ) ? items . map ( encryptedReasoningItem ) . filter ( Boolean ) : [ ] ;
8982}
9083
84+ function validateTools ( tools , param ) {
85+ tools . forEach ( ( tool , index ) => {
86+ if ( ! isObject ( tool ) || typeof tool . type !== "string" ) throw invalid ( "Each tool must be an object with a type" , `${ param } [${ index } ]` ) ;
87+ if ( tool . type === "function" && ( typeof tool . name !== "string" || ! tool . name ) ) {
88+ throw invalid ( "Function tools require a name" , `${ param } [${ index } ].name` ) ;
89+ }
90+ } ) ;
91+ }
92+
9193function validateInputItem ( item , param ) {
9294 if ( ! isObject ( item ) ) throw invalid ( "Input items must be objects" , param ) ;
95+ if ( item . type === "additional_tools" ) {
96+ if ( ! Array . isArray ( item . tools ) ) throw invalid ( "additional_tools tools must be an array" , `${ param } .tools` ) ;
97+ validateTools ( item . tools , `${ param } .tools` ) ;
98+ return ;
99+ }
93100 if ( item . type === "reasoning" ) {
94101 if ( item . encrypted_content != null && typeof item . encrypted_content !== "string" ) {
95102 throw invalid ( "reasoning encrypted_content must be a string or null" , `${ param } .encrypted_content` ) ;
@@ -110,7 +117,7 @@ function validateInputItem(item, param) {
110117 if ( ! ( typeof item . output === "string" || Array . isArray ( item . output ) ) ) throw invalid ( "function_call_output requires string or array output" , `${ param } .output` ) ;
111118 return ;
112119 }
113- if ( item . type !== "message" && ! item . role ) throw invalid ( "Unsupported input item" , `${ param } .type` ) ;
120+ if ( item . type !== undefined && item . type !== "message" ) throw invalid ( "Unsupported input item" , `${ param } .type` ) ;
114121 if ( ! [ "user" , "assistant" , "system" , "developer" ] . includes ( item . role ) ) throw invalid ( "Invalid message role" , `${ param } .role` ) ;
115122 if ( item . content == null ) {
116123 if ( item . role !== "assistant" ) throw invalid ( "Message content must be a string, content part, or array" , `${ param } .content` ) ;
@@ -129,6 +136,7 @@ function inputMessages(input) {
129136 let pendingAssistant = null ;
130137 let pendingReasoning = [ ] ;
131138 for ( const item of input ) {
139+ if ( item . type === "additional_tools" ) continue ;
132140 if ( item . type === "reasoning" ) {
133141 const reasoning = encryptedReasoningItem ( item ) ;
134142 if ( reasoning ) pendingReasoning . push ( reasoning ) ;
@@ -191,7 +199,11 @@ function toChatCompletionsBody(body) {
191199 const messages = inputMessages ( body . input ) ;
192200 if ( body . instructions != null ) messages . unshift ( { role : "system" , content : body . instructions } ) ;
193201 const out = { model : body . model , messages, stream : ! ! body . stream } ;
194- const tools = toChatTools ( body . tools ) ;
202+ const declaredTools = [
203+ ...( body . tools || [ ] ) ,
204+ ...( Array . isArray ( body . input ) ? body . input . filter ( ( item ) => item . type === "additional_tools" ) . flatMap ( ( item ) => item . tools ) : [ ] ) ,
205+ ] ;
206+ const tools = toChatTools ( declaredTools ) ;
195207 if ( tools ) out . tools = tools ;
196208 if ( body . tool_choice !== undefined ) out . tool_choice = toChatToolChoice ( body . tool_choice ) ;
197209 if ( body . reasoning !== undefined ) out . reasoning = { ...body . reasoning } ;
0 commit comments