diff --git a/scripts/generate-llms.ts b/scripts/generate-llms.ts index c82c37e..12417d3 100644 --- a/scripts/generate-llms.ts +++ b/scripts/generate-llms.ts @@ -212,6 +212,53 @@ function parseExample(response: string) { } } +type Schema = Record + +function mergeSchemas(schemas: Schema[]): Schema { + const unique = [...new Map(schemas.map((schema) => [JSON.stringify(schema), schema])).values()] + if (unique.length === 1) return unique[0] + const objects = unique.filter((schema) => schema.type === 'object') + if (objects.length > 1 && objects.length === unique.length) { + const keys = [...new Set(objects.flatMap((schema) => Object.keys(schema.properties as Schema)))] + return { + type: 'object', + properties: Object.fromEntries( + keys.map((key) => [ + key, + mergeSchemas( + objects + .map((schema) => (schema.properties as Record)[key]) + .filter((schema) => schema !== undefined), + ), + ]), + ), + required: keys.filter((key) => + objects.every((schema) => key in (schema.properties as Schema)), + ), + } + } + return { anyOf: unique } +} + +function inferSchema(value: unknown): Schema { + if (value === null) return { type: 'null' } + if (Array.isArray(value)) { + return value.length === 0 + ? { type: 'array', items: {} } + : { type: 'array', items: mergeSchemas(value.map(inferSchema)) } + } + if (typeof value === 'object') { + const entries = Object.entries(value as Record) + return { + type: 'object', + properties: Object.fromEntries(entries.map(([key, child]) => [key, inferSchema(child)])), + required: entries.map(([key]) => key), + } + } + if (typeof value === 'number') return { type: Number.isInteger(value) ? 'integer' : 'number' } + return { type: typeof value } +} + function operation(item: ApiEndpoint) { const pathParameters = [...item.path.matchAll(/\{(\w+)\}/g)].map((match) => ({ name: match[1], @@ -234,7 +281,10 @@ function operation(item: ApiEndpoint) { : { description: 'Success', content: { - 'application/json': { schema: {}, ...(example === undefined ? {} : { example }) }, + 'application/json': { + schema: example === undefined ? {} : inferSchema(example), + ...(example === undefined ? {} : { example }), + }, }, }, }