@@ -12,6 +12,14 @@ export type CallModelInput =
1212 | models . OpenResponsesInput
1313 | models . Message [ ] ;
1414
15+ /**
16+ * Tool type that accepts chat-style, responses-style, or enhanced tools
17+ */
18+ export type CallModelTools =
19+ | EnhancedTool [ ]
20+ | models . ToolDefinitionJson [ ]
21+ | models . OpenResponsesRequest [ "tools" ] ;
22+
1523/**
1624 * Check if input is chat-style messages (Message[])
1725 */
@@ -25,6 +33,33 @@ function isChatStyleMessages(input: CallModelInput): input is models.Message[] {
2533 return first && 'role' in first && ! ( 'type' in first ) ;
2634}
2735
36+ /**
37+ * Check if tools are chat-style (ToolDefinitionJson[])
38+ */
39+ function isChatStyleTools ( tools : CallModelTools ) : tools is models . ToolDefinitionJson [ ] {
40+ if ( ! Array . isArray ( tools ) ) return false ;
41+ if ( tools . length === 0 ) return false ;
42+
43+ const first = tools [ 0 ] as any ;
44+ // Chat-style tools have nested 'function' property with 'name' inside
45+ // Enhanced tools have 'function' with 'inputSchema'
46+ // Responses-style tools have 'name' at top level
47+ return first && 'function' in first && first . function && 'name' in first . function && ! ( 'inputSchema' in first . function ) ;
48+ }
49+
50+ /**
51+ * Convert chat-style tools to responses-style
52+ */
53+ function convertChatToResponsesTools ( tools : models . ToolDefinitionJson [ ] ) : models . OpenResponsesRequest [ "tools" ] {
54+ return tools . map ( ( tool ) : models . OpenResponsesRequestToolFunction => ( {
55+ type : "function" ,
56+ name : tool . function . name ,
57+ description : tool . function . description ?? null ,
58+ strict : tool . function . strict ?? null ,
59+ parameters : tool . function . parameters ?? null ,
60+ } ) ) ;
61+ }
62+
2863/**
2964 * Convert chat-style messages to responses-style input
3065 */
@@ -140,7 +175,7 @@ export function callModel(
140175 client : OpenRouterCore ,
141176 request : Omit < models . OpenResponsesRequest , "stream" | "tools" | "input" > & {
142177 input ?: CallModelInput ;
143- tools ?: EnhancedTool [ ] | models . OpenResponsesRequest [ "tools" ] ;
178+ tools ?: CallModelTools ;
144179 maxToolRounds ?: MaxToolRounds ;
145180 } ,
146181 options ?: RequestOptions ,
@@ -157,16 +192,27 @@ export function callModel(
157192 input : convertedInput ,
158193 } ;
159194
160- // Separate enhanced tools from API tools
195+ // Determine tool type and convert as needed
161196 let isEnhancedTools = false ;
162- if ( tools && tools . length > 0 ) {
197+ let isChatTools = false ;
198+
199+ if ( tools && Array . isArray ( tools ) && tools . length > 0 ) {
163200 const firstTool = tools [ 0 ] as any ;
164201 isEnhancedTools = "function" in firstTool && firstTool . function && "inputSchema" in firstTool . function ;
202+ isChatTools = ! isEnhancedTools && isChatStyleTools ( tools ) ;
165203 }
204+
166205 const enhancedTools = isEnhancedTools ? ( tools as EnhancedTool [ ] ) : undefined ;
167206
168- // Convert enhanced tools to API format if provided, otherwise use tools as-is
169- const apiTools = enhancedTools ? convertEnhancedToolsToAPIFormat ( enhancedTools ) : ( tools as models . OpenResponsesRequest [ "tools" ] ) ;
207+ // Convert tools to API format based on their type
208+ let apiTools : models . OpenResponsesRequest [ "tools" ] ;
209+ if ( enhancedTools ) {
210+ apiTools = convertEnhancedToolsToAPIFormat ( enhancedTools ) ;
211+ } else if ( isChatTools ) {
212+ apiTools = convertChatToResponsesTools ( tools as models . ToolDefinitionJson [ ] ) ;
213+ } else {
214+ apiTools = tools as models . OpenResponsesRequest [ "tools" ] ;
215+ }
170216
171217 // Build the request with converted tools
172218 const finalRequest : models . OpenResponsesRequest = {
0 commit comments