@@ -394,13 +394,127 @@ export function inspectOpenAIToolSchemas(
394394 return [ ] ;
395395}
396396
397- export type ProviderToolCompatFamily = "gemini" | "openai" ;
397+ export const DEEPSEEK_UNSUPPORTED_SCHEMA_KEYWORDS = new Set ( [ "anyOf" , "oneOf" ] ) ;
398+
399+ function isNullSchemaVariant ( schema : unknown ) : boolean {
400+ if ( ! schema || typeof schema !== "object" || Array . isArray ( schema ) ) {
401+ return false ;
402+ }
403+ const record = schema as Record < string , unknown > ;
404+ if ( record . type === "null" ) {
405+ return true ;
406+ }
407+ if ( Array . isArray ( record . type ) && record . type . length === 1 && record . type [ 0 ] === "null" ) {
408+ return true ;
409+ }
410+ if ( "const" in record && record . const === null ) {
411+ return true ;
412+ }
413+ return Array . isArray ( record . enum ) && record . enum . length === 1 && record . enum [ 0 ] === null ;
414+ }
415+
416+ function normalizeDeepSeekSchema ( schema : unknown ) : unknown {
417+ if ( Array . isArray ( schema ) ) {
418+ let changed = false ;
419+ const normalized = schema . map ( ( entry ) => {
420+ const next = normalizeDeepSeekSchema ( entry ) ;
421+ changed ||= next !== entry ;
422+ return next ;
423+ } ) ;
424+ return changed ? normalized : schema ;
425+ }
426+ if ( ! schema || typeof schema !== "object" ) {
427+ return schema ;
428+ }
429+
430+ const record = schema as Record < string , unknown > ;
431+ const unionKey = Array . isArray ( record . anyOf )
432+ ? "anyOf"
433+ : Array . isArray ( record . oneOf )
434+ ? "oneOf"
435+ : undefined ;
436+
437+ let changed = false ;
438+ const normalized : Record < string , unknown > = { } ;
439+ for ( const [ key , value ] of Object . entries ( record ) ) {
440+ if ( key === "anyOf" || key === "oneOf" ) {
441+ if ( key === unionKey ) {
442+ changed = true ;
443+ continue ;
444+ }
445+ }
446+ const next = normalizeDeepSeekSchema ( value ) ;
447+ normalized [ key ] = next ;
448+ changed ||= next !== value ;
449+ }
450+
451+ if ( ! unionKey ) {
452+ return changed ? normalized : schema ;
453+ }
454+
455+ const variants = record [ unionKey ] as unknown [ ] ;
456+ const normalizedVariants = variants . map ( ( entry ) => normalizeDeepSeekSchema ( entry ) ) ;
457+ const nonNullVariants = normalizedVariants . filter ( ( entry ) => ! isNullSchemaVariant ( entry ) ) ;
458+ const selected = nonNullVariants [ 0 ] ?? normalizedVariants [ 0 ] ;
459+ if ( ! selected || typeof selected !== "object" || Array . isArray ( selected ) ) {
460+ return normalized ;
461+ }
462+
463+ const merged = {
464+ ...( selected as Record < string , unknown > ) ,
465+ ...normalized ,
466+ } ;
467+ if ( nonNullVariants . length < normalizedVariants . length ) {
468+ merged . nullable = true ;
469+ }
470+ return merged ;
471+ }
472+
473+ export function normalizeDeepSeekToolSchemas (
474+ ctx : ProviderNormalizeToolSchemasContext ,
475+ ) : AnyAgentTool [ ] {
476+ return ctx . tools . map ( ( tool ) => {
477+ if ( ! tool . parameters || typeof tool . parameters !== "object" ) {
478+ return tool ;
479+ }
480+ const parameters = normalizeDeepSeekSchema ( tool . parameters ) ;
481+ return parameters === tool . parameters
482+ ? tool
483+ : {
484+ ...tool ,
485+ parameters : parameters as TSchema ,
486+ } ;
487+ } ) ;
488+ }
489+
490+ export function inspectDeepSeekToolSchemas (
491+ ctx : ProviderNormalizeToolSchemasContext ,
492+ ) : ProviderToolSchemaDiagnostic [ ] {
493+ return ctx . tools . flatMap ( ( tool , toolIndex ) => {
494+ const violations = findUnsupportedSchemaKeywords (
495+ tool . parameters ,
496+ `${ tool . name } .parameters` ,
497+ DEEPSEEK_UNSUPPORTED_SCHEMA_KEYWORDS ,
498+ ) ;
499+ if ( violations . length === 0 ) {
500+ return [ ] ;
501+ }
502+ return [ { toolName : tool . name , toolIndex, violations } ] ;
503+ } ) ;
504+ }
505+
506+ export type ProviderToolCompatFamily = "deepseek" | "gemini" | "openai" ;
398507
399508export function buildProviderToolCompatFamilyHooks ( family : ProviderToolCompatFamily ) : {
400509 normalizeToolSchemas : ( ctx : ProviderNormalizeToolSchemasContext ) => AnyAgentTool [ ] ;
401510 inspectToolSchemas : ( ctx : ProviderNormalizeToolSchemasContext ) => ProviderToolSchemaDiagnostic [ ] ;
402511} {
403512 switch ( family ) {
513+ case "deepseek" :
514+ return {
515+ normalizeToolSchemas : normalizeDeepSeekToolSchemas ,
516+ inspectToolSchemas : inspectDeepSeekToolSchemas ,
517+ } ;
404518 case "gemini" :
405519 return {
406520 normalizeToolSchemas : normalizeGeminiToolSchemas ,
0 commit comments