@@ -125,7 +125,49 @@ function safeToolName(name: string | undefined): string {
125125 return sanitized ;
126126}
127127
128- function toolsToChatFormat ( parsed : OcxParsedRequest ) : unknown [ ] | undefined {
128+ const XAI_SCHEMA_BASE_URLS = new Set ( [ "api.x.ai" , "cli-chat-proxy.grok.com" ] ) ;
129+
130+ function isXaiSchemaTarget ( provider : OcxProviderConfig ) : boolean {
131+ try {
132+ return XAI_SCHEMA_BASE_URLS . has ( new URL ( provider . baseUrl ) . hostname ) ;
133+ } catch {
134+ return false ;
135+ }
136+ }
137+
138+ function expandXaiRootObjectSchemas ( schema : unknown ) : Record < string , unknown > [ ] | undefined {
139+ if ( ! schema || typeof schema !== "object" || Array . isArray ( schema ) ) return undefined ;
140+ const obj = schema as Record < string , unknown > ;
141+ const compositionKey = [ "oneOf" , "anyOf" ] . find ( key => Array . isArray ( obj [ key ] ) ) ;
142+ if ( ! compositionKey ) {
143+ if ( obj . type !== undefined && obj . type !== "object" ) return undefined ;
144+ return [ { ...obj , type : "object" } ] ;
145+ }
146+
147+ const siblings = Object . fromEntries ( Object . entries ( obj ) . filter ( ( [ key ] ) => key !== compositionKey ) ) ;
148+ const branches = obj [ compositionKey ] ;
149+ if ( ! Array . isArray ( branches ) ) return undefined ;
150+ const expanded : Record < string , unknown > [ ] = [ ] ;
151+ for ( const branch of branches ) {
152+ const variants = expandXaiRootObjectSchemas ( branch ) ;
153+ if ( ! variants ) return undefined ;
154+ for ( const variant of variants ) expanded . push ( { ...siblings , ...variant } ) ;
155+ }
156+ return expanded . length > 0 ? expanded : undefined ;
157+ }
158+
159+ function normalizeXaiToolParameters ( parameters : unknown ) : Record < string , unknown > | undefined {
160+ const variants = expandXaiRootObjectSchemas ( parameters ) ;
161+ if ( ! variants ) return undefined ;
162+ if ( variants . length === 1 ) return variants [ 0 ] ;
163+ const root = parameters && typeof parameters === "object" && ! Array . isArray ( parameters )
164+ ? parameters as Record < string , unknown >
165+ : { } ;
166+ const metadata = Object . fromEntries ( Object . entries ( root ) . filter ( ( [ key ] ) => key !== "oneOf" && key !== "anyOf" && key !== "type" ) ) ;
167+ return { ...metadata , oneOf : variants } ;
168+ }
169+
170+ function toolsToChatFormat ( parsed : OcxParsedRequest , provider : OcxProviderConfig ) : unknown [ ] | undefined {
129171 if ( ! parsed . context . tools || parsed . context . tools . length === 0 ) return undefined ;
130172 const allowed = isAllowedToolChoice ( parsed . options . toolChoice )
131173 ? new Set ( parsed . options . toolChoice . allowedTools )
@@ -134,15 +176,21 @@ function toolsToChatFormat(parsed: OcxParsedRequest): unknown[] | undefined {
134176 ? parsed . context . tools . filter ( t => toolAllowedByChoice ( t , allowed ) )
135177 : parsed . context . tools ;
136178 if ( tools . length === 0 ) return undefined ;
137- return tools . map ( t => ( {
179+ const xaiTarget = isXaiSchemaTarget ( provider ) ;
180+ const formatted = tools . flatMap ( t => {
181+ const parameters = xaiTarget ? normalizeXaiToolParameters ( t . parameters ) : t . parameters ;
182+ if ( parameters === undefined ) return [ ] ;
183+ return [ {
138184 type : "function" ,
139185 function : {
140186 name : namespacedToolName ( t . namespace , t . name ) ,
141187 description : t . description ,
142- parameters : t . parameters ,
188+ parameters,
143189 ...( t . strict !== undefined ? { strict : t . strict } : { } ) ,
144190 } ,
145- } ) ) ;
191+ } ] ;
192+ } ) ;
193+ return formatted . length > 0 ? formatted : undefined ;
146194}
147195
148196function toolChoiceToChatFormat ( tc : OcxParsedRequest [ "options" ] [ "toolChoice" ] , tools : OcxParsedRequest [ "context" ] [ "tools" ] ) : unknown {
@@ -190,7 +238,7 @@ export function createOpenAIChatAdapter(provider: OcxProviderConfig): ProviderAd
190238 }
191239
192240 const messages = messagesToChatFormat ( parsed , provider ) ;
193- const tools = toolsToChatFormat ( parsed ) ;
241+ const tools = toolsToChatFormat ( parsed , provider ) ;
194242 const toolChoice = toolChoiceToChatFormat ( parsed . options . toolChoice , parsed . context . tools ) ;
195243
196244 const body : Record < string , unknown > = {
0 commit comments