feat: enhance tool conversion to support strict mode based on schema validation
This commit is contained in:
@@ -300,13 +300,75 @@ export function convertToolsToResponsesTools(
|
||||
): ResponsesTool[] {
|
||||
return tools
|
||||
.filter(tool => tool.name && tool.name !== 'ToolSearchTool')
|
||||
.map(tool => ({
|
||||
type: 'function',
|
||||
name: tool.name ?? 'tool',
|
||||
description: tool.description ?? '',
|
||||
parameters: tool.input_schema ?? { type: 'object', properties: {} },
|
||||
strict: true,
|
||||
}))
|
||||
.map(tool => {
|
||||
const parameters = tool.input_schema ?? { type: 'object', properties: {} }
|
||||
|
||||
return {
|
||||
type: 'function',
|
||||
name: tool.name ?? 'tool',
|
||||
description: tool.description ?? '',
|
||||
parameters,
|
||||
...(isStrictResponsesSchema(parameters) ? { strict: true } : {}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function isStrictResponsesSchema(schema: unknown): boolean {
|
||||
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
||||
return true
|
||||
}
|
||||
|
||||
const record = schema as Record<string, unknown>
|
||||
const type = record.type
|
||||
|
||||
if (type === 'object') {
|
||||
const properties =
|
||||
record.properties && typeof record.properties === 'object' && !Array.isArray(record.properties)
|
||||
? (record.properties as Record<string, unknown>)
|
||||
: {}
|
||||
|
||||
const propertyKeys = Object.keys(properties)
|
||||
const required = Array.isArray(record.required)
|
||||
? record.required.filter((value): value is string => typeof value === 'string')
|
||||
: null
|
||||
|
||||
if (propertyKeys.length > 0) {
|
||||
if (!required) return false
|
||||
|
||||
const requiredSet = new Set(required)
|
||||
for (const key of propertyKeys) {
|
||||
if (!requiredSet.has(key)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const child of Object.values(properties)) {
|
||||
if (!isStrictResponsesSchema(child)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const combinators = ['anyOf', 'oneOf', 'allOf'] as const
|
||||
for (const key of combinators) {
|
||||
if (key in record) {
|
||||
const value = record[key]
|
||||
if (!Array.isArray(value) || value.some(item => !isStrictResponsesSchema(item))) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('items' in record) {
|
||||
const items = record.items
|
||||
if (Array.isArray(items)) {
|
||||
return items.every(item => isStrictResponsesSchema(item))
|
||||
}
|
||||
return isStrictResponsesSchema(items)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function convertToolChoice(toolChoice: unknown): unknown {
|
||||
|
||||
Reference in New Issue
Block a user