kbot:structured output - spieglein spieglein :)

This commit is contained in:
lovebird 2025-04-01 14:45:51 +02:00
parent 393591e28e
commit 3459307bea
8 changed files with 180 additions and 112 deletions

File diff suppressed because one or more lines are too long

View File

@ -427,6 +427,6 @@ export interface IKBotOptions {
filters?: (string | ("JSON" | "JSONUnescape" | "JSONPretty" | "AlphaSort" | "code" | "JSONParse" | "trim")[] | string[] | ((...args_0: unknown[]) => unknown)[]);
/** Dry run - only write out parameters without making API calls */
dry?: (boolean | string);
/** Zod schema for structured outputs. Can be a Zod schema, a JSON schema string, or a path to a JSON file. */
format?: (string | undefined) | undefined;
/** Format for structured outputs. Can be a Zod schema, a Zod schema string, a JSON schema string, or a path to a JSON file. */
format?: (string | any) | undefined;
}

View File

@ -188,8 +188,13 @@
"description": "Dry run - only write out parameters without making API calls"
},
"format": {
"type": "string",
"description": "Zod schema for structured outputs. Can be a Zod schema, a JSON schema string, or a path to a JSON file."
"anyOf": [
{
"type": "string"
},
{}
],
"description": "Format for structured outputs. Can be a Zod schema, a Zod schema string, a JSON schema string, or a path to a JSON file."
}
},
"additionalProperties": true,

View File

@ -127,7 +127,7 @@
"ui:placeholder": false
},
"format": {
"ui:description": "Zod schema for structured outputs. Can be a Zod schema, a JSON schema string, or a path to a JSON file.",
"ui:description": "Format for structured outputs. Can be a Zod schema, a Zod schema string, a JSON schema string, or a path to a JSON file.",
"ui:title": "Format"
}
}

View File

@ -248,27 +248,45 @@ export const OptionsSchema = (opts?: any): any => {
)
.add(
'format',
z.string().optional().transform((val) => {
try {
let schema;
// Check if the string is a file path
if (exists(val) && val.endsWith('.json')) {
const content = readFS(val);
schema = JSON.parse(content.toString());
} else {
schema = JSON.parse(val);
z.union([
z.string().transform((val) => {
try {
// Check if the string is a file path
if (exists(val) && val.endsWith('.json')) {
const content = readFS(val);
const schema = JSON.parse(content.toString());
const zodSchemaStr = jsonSchemaToZod(schema);
// Evaluate the string to get the actual Zod schema
const zodSchema = eval(`(${zodSchemaStr})`);
return zodResponseFormat(zodSchema, "format");
} else {
// Try parsing as JSON schema first
try {
const schema = JSON.parse(val);
const zodSchemaStr = jsonSchemaToZod(schema);
const zodSchema = eval(`(${zodSchemaStr})`);
return zodResponseFormat(zodSchema, "format");
} catch {
// If not JSON, try evaluating as Zod schema directly
const zodSchema = eval(`(${val})`);
return zodResponseFormat(zodSchema, "format");
}
}
} catch (e) {
console.error(`Error parsing format: ${e}`)
return null;
}
}),
z.any().transform((val) => {
// If it's already a Zod schema, use it directly
if (val && typeof val === 'object' && 'parse' in val) {
return zodResponseFormat(val, "format");
}
const zodSchemaStr = jsonSchemaToZod(schema);
// Evaluate the string to get the actual Zod schema
const zodSchema = eval(`(${zodSchemaStr})`);
return zodResponseFormat(zodSchema, "format");
} catch (e) {
console.error(`Error parsing format: ${e}`)
return null;
}
})
})
])
.optional()
.describe('Zod schema for structured outputs. Can be a Zod schema, a JSON schema string, or a path to a JSON file.')
.describe('Format for structured outputs. Can be a Zod schema, a Zod schema string, a JSON schema string, or a path to a JSON file.')
);
return schemaMap.root()
.passthrough()

View File

@ -427,6 +427,6 @@ export interface IKBotOptions {
filters?: (string | ("JSON" | "JSONUnescape" | "JSONPretty" | "AlphaSort" | "code" | "JSONParse" | "trim")[] | string[] | ((...args_0: unknown[]) => unknown)[]);
/** Dry run - only write out parameters without making API calls */
dry?: (boolean | string);
/** Zod schema for structured outputs. Can be a Zod schema, a JSON schema string, or a path to a JSON file. */
format?: (string | undefined) | undefined;
/** Format for structured outputs. Can be a Zod schema, a Zod schema string, a JSON schema string, or a path to a JSON file. */
format?: (string | any) | undefined;
}

View File

@ -1,84 +1,94 @@
{
"cities": [
{
"name": "Lagos",
"country": "Nigeria",
"population": 14779000
"name": "Nigeria",
"population": 21140000,
"conflict": 0,
"exports": "Petroleum, Cocoa",
"languages": "English, Hausa, Igbo, Yoruba",
"religion": "Islam, Christianity, Indigenous beliefs",
"colonia": "Colonized by the British"
},
{
"name": "Cairo",
"country": "Egypt",
"population": 20484965
"name": "Egypt",
"population": 98420000,
"conflict": 0,
"exports": "Crude Oil, Cotton, Textiles",
"languages": "Arabic",
"religion": "Islam, Christianity",
"colonia": "Colonized by the British"
},
{
"name": "Kinshasa",
"country": "Democratic Republic of the Congo",
"population": 15075000
"name": "South Africa",
"population": 59310000,
"conflict": 0,
"exports": "Gold, Diamonds, Platinum",
"languages": "Zulu, Xhosa, Afrikaans, English",
"religion": "Christianity, Traditional African beliefs",
"colonia": "Colonized by the British and Dutch"
},
{
"name": "Johannesburg",
"country": "South Africa",
"population": 9574417
"name": "Kenya",
"population": 53700000,
"conflict": 0,
"exports": "Tea, Coffee, Cut Flowers",
"languages": "English, Swahili",
"religion": "Christianity, Islam, Hinduism",
"colonia": "Colonized by the British"
},
{
"name": "Nairobi",
"country": "Kenya",
"population": 5545000
"name": "Ethiopia",
"population": 112100000,
"conflict": 1,
"exports": "Coffee, Livestock, Pulses",
"languages": "Amharic, Oromo, Tigrinya",
"religion": "Christianity, Islam, Indigenous beliefs",
"colonia": "Briefly occupied by Italy"
},
{
"name": "Luanda",
"country": "Angola",
"population": 8200000
"name": "Ghana",
"population": 31280000,
"conflict": 0,
"exports": "Gold, Cocoa, Oil",
"languages": "English, Akan, Ewe",
"religion": "Christianity, Islam, Traditional African beliefs",
"colonia": "Colonized by the British"
},
{
"name": "Addis Ababa",
"country": "Ethiopia",
"population": 4942826
"name": "Morocco",
"population": 36470000,
"conflict": 0,
"exports": "Electronics, Phosphates, Textiles",
"languages": "Arabic, Berber",
"religion": "Islam",
"colonia": "Colonized by the French and Spanish"
},
{
"name": "Khartoum",
"country": "Sudan",
"population": 6400000
"name": "Algeria",
"population": 43850000,
"conflict": 0,
"exports": "Petroleum, Natural Gas",
"languages": "Arabic, Berber",
"religion": "Islam",
"colonia": "Colonized by the French"
},
{
"name": "Dar es Salaam",
"country": "Tanzania",
"population": 6936403
"name": "Uganda",
"population": 45740000,
"conflict": 0,
"exports": "Coffee, Fish, Tea",
"languages": "English, Swahili",
"religion": "Christianity, Islam",
"colonia": "Colonized by the British"
},
{
"name": "Accra",
"country": "Ghana",
"population": 4540000
},
{
"name": "Algiers",
"country": "Algeria",
"population": 3415811
},
{
"name": "Casablanca",
"country": "Morocco",
"population": 3500000
},
{
"name": "Abidjan",
"country": "Ivory Coast",
"population": 5040000
},
{
"name": "Dakar",
"country": "Senegal",
"population": 3483664
},
{
"name": "Tunis",
"country": "Tunisia",
"population": 2750330
},
{
"name": "Douala",
"country": "Cameroon",
"population": 4050687
"name": "Sudan",
"population": 43850000,
"conflict": 1,
"exports": "Gold, Oil, Gum Arabic",
"languages": "Arabic, English",
"religion": "Islam, Christianity",
"colonia": "Colonized by the British and Egyptians"
}
]
}

View File

@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/cities.schema.json",
"title": "Cities Wrapper",
"description": "An object containing a list of cities (without coordinates).",
"title": "countries Wrapper",
"description": "An object containing a list of countries (without coordinates).",
"type": "object",
"properties": {
"cities": {
@ -12,15 +12,31 @@
"properties": {
"name": {
"type": "string",
"description": "City name."
},
"country": {
"type": "string",
"description": "Country where the city is located."
"description": "Country name."
},
"population": {
"type": "integer",
"description": "Total population of the city."
},
"conflict": {
"type": "integer",
"description": "Is involved in a conflict."
},
"exports": {
"type": "string",
"description": "Goods exported from the country."
},
"languages": {
"type": "string",
"description": "list of languages spoken in the country."
},
"religion": {
"type": "string",
"description": "list of religions practiced in the country."
},
"colonia": {
"type": "string",
"description": "Colonial history of the country."
}
},
"required": ["name", "country"]