@@ -18,9 +18,50 @@ type ToolWithParameters = {
1818 parameters : unknown ;
1919} ;
2020
21+ type ToolFieldRead < TField extends keyof ToolWithParameters > =
22+ | { readable : true ; value : ToolWithParameters [ TField ] }
23+ | { readable : false } ;
24+
2125const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8 ;
2226let strictOpenAISchemaCache = new WeakMap < object , Array < { key : string ; value : unknown } > > ( ) ;
2327
28+ function readToolField < TField extends keyof ToolWithParameters > (
29+ tool : ToolWithParameters ,
30+ field : TField ,
31+ ) : ToolFieldRead < TField > {
32+ try {
33+ return { readable : true , value : tool [ field ] } ;
34+ } catch {
35+ return { readable : false } ;
36+ }
37+ }
38+
39+ function readToolName ( tool : ToolWithParameters , toolIndex : number ) : {
40+ toolName : string ;
41+ diagnosticToolName ?: string ;
42+ violations : string [ ] ;
43+ } {
44+ const nameRead = readToolField ( tool , "name" ) ;
45+ if ( ! nameRead . readable ) {
46+ const toolName = `tool[${ toolIndex } ]` ;
47+ return {
48+ toolName,
49+ violations : [ `${ toolName } .name is unreadable` ] ,
50+ } ;
51+ }
52+ if ( typeof nameRead . value === "string" && nameRead . value ) {
53+ return {
54+ toolName : nameRead . value ,
55+ diagnosticToolName : nameRead . value ,
56+ violations : [ ] ,
57+ } ;
58+ }
59+ return {
60+ toolName : `tool[${ toolIndex } ]` ,
61+ violations : [ ] ,
62+ } ;
63+ }
64+
2465function resolveToolSchemaModelCompat (
2566 compat : ToolSchemaCompatInput | null | undefined ,
2667) : ModelCompatConfig | undefined {
@@ -179,18 +220,33 @@ export function findOpenAIStrictToolSchemaDiagnostics(
179220 tools : readonly ToolWithParameters [ ] ,
180221) : OpenAIStrictToolSchemaDiagnostic [ ] {
181222 return tools . flatMap ( ( tool , toolIndex ) => {
223+ const nameRead = readToolName ( tool , toolIndex ) ;
224+ const parametersRead = readToolField ( tool , "parameters" ) ;
225+ if ( ! parametersRead . readable ) {
226+ return [
227+ {
228+ toolIndex,
229+ ...( nameRead . diagnosticToolName ? { toolName : nameRead . diagnosticToolName } : { } ) ,
230+ violations : [
231+ ...nameRead . violations ,
232+ `${ nameRead . toolName } .parameters is unreadable` ,
233+ ] ,
234+ } ,
235+ ] ;
236+ }
182237 const violations = findStrictOpenAIJsonSchemaViolations (
183- normalizeStrictOpenAIJsonSchema ( tool . parameters ) ,
184- `${ typeof tool . name === "string" && tool . name ? tool . name : `tool[ ${ toolIndex } ]` } .parameters` ,
238+ normalizeStrictOpenAIJsonSchema ( parametersRead . value ) ,
239+ `${ nameRead . toolName } .parameters` ,
185240 ) ;
186- if ( violations . length === 0 ) {
241+ const allViolations = [ ...nameRead . violations , ...violations ] ;
242+ if ( allViolations . length === 0 ) {
187243 return [ ] ;
188244 }
189245 return [
190246 {
191247 toolIndex,
192- ...( typeof tool . name === "string" && tool . name ? { toolName : tool . name } : { } ) ,
193- violations,
248+ ...( nameRead . diagnosticToolName ? { toolName : nameRead . diagnosticToolName } : { } ) ,
249+ violations : allViolations ,
194250 } ,
195251 ] ;
196252 } ) ;
@@ -317,5 +373,8 @@ export function resolveOpenAIStrictToolFlagForInventory(
317373 if ( strict !== true ) {
318374 return strict === false ? false : undefined ;
319375 }
320- return tools . every ( ( tool ) => isStrictOpenAIJsonSchemaCompatible ( tool . parameters ) ) ;
376+ return tools . every ( ( tool ) => {
377+ const parametersRead = readToolField ( tool , "parameters" ) ;
378+ return parametersRead . readable && isStrictOpenAIJsonSchemaCompatible ( parametersRead . value ) ;
379+ } ) ;
321380}
0 commit comments