UNPKG

@copilotkit/shared

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

1 lines 17.2 kB
{"version":3,"file":"json-schema.cjs","names":["z"],"sources":["../../src/utils/json-schema.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { Parameter } from \"../types\";\n\nexport type JSONSchemaString = {\n type: \"string\";\n description?: string;\n enum?: string[];\n};\n\nexport type JSONSchemaNumber = {\n type: \"number\";\n description?: string;\n};\n\nexport type JSONSchemaBoolean = {\n type: \"boolean\";\n description?: string;\n};\n\nexport type JSONSchemaObject = {\n type: \"object\";\n properties?: Record<string, JSONSchema>;\n required?: string[];\n description?: string;\n};\n\nexport type JSONSchemaArray = {\n type: \"array\";\n items: JSONSchema;\n description?: string;\n};\n\nexport type JSONSchema =\n | JSONSchemaString\n | JSONSchemaNumber\n | JSONSchemaBoolean\n | JSONSchemaObject\n | JSONSchemaArray;\n\nexport function actionParametersToJsonSchema(\n actionParameters: Parameter[],\n): JSONSchema {\n // Create the parameters object based on the argumentAnnotations\n let parameters: { [key: string]: any } = {};\n for (let parameter of actionParameters || []) {\n parameters[parameter.name] = convertAttribute(parameter);\n }\n\n let requiredParameterNames: string[] = [];\n for (let arg of actionParameters || []) {\n if (arg.required !== false) {\n requiredParameterNames.push(arg.name);\n }\n }\n\n // Create the ChatCompletionFunctions object\n return {\n type: \"object\",\n properties: parameters,\n required: requiredParameterNames,\n };\n}\n\n// Convert JSONSchema to Parameter[]\nexport function jsonSchemaToActionParameters(\n jsonSchema: JSONSchema,\n): Parameter[] {\n if (jsonSchema.type !== \"object\" || !jsonSchema.properties) {\n return [];\n }\n\n const parameters: Parameter[] = [];\n const requiredFields = jsonSchema.required || [];\n\n for (const [name, schema] of Object.entries(jsonSchema.properties)) {\n const parameter = convertJsonSchemaToParameter(\n name,\n schema,\n requiredFields.includes(name),\n );\n parameters.push(parameter);\n }\n\n return parameters;\n}\n\n// Convert JSONSchema property to Parameter\nfunction convertJsonSchemaToParameter(\n name: string,\n schema: JSONSchema,\n isRequired: boolean,\n): Parameter {\n const baseParameter: Parameter = {\n name,\n description: schema.description,\n };\n\n if (!isRequired) {\n baseParameter.required = false;\n }\n\n // Handle null-union types like [\"string\", \"null\"] by picking the non-null type\n if (Array.isArray(schema.type)) {\n const types = schema.type as string[];\n const hasNull = types.includes(\"null\");\n const nonNullTypes = types.filter((t: string) => t !== \"null\");\n const resolvedType = nonNullTypes.length > 0 ? nonNullTypes[0] : \"string\";\n return convertJsonSchemaToParameter(\n name,\n { ...schema, type: resolvedType } as JSONSchema,\n hasNull ? false : isRequired,\n );\n }\n\n switch (schema.type) {\n case \"string\":\n return {\n ...baseParameter,\n type: \"string\",\n ...(schema.enum && { enum: schema.enum }),\n };\n case \"number\":\n case \"boolean\":\n return {\n ...baseParameter,\n type: schema.type,\n };\n case \"object\":\n if (schema.properties) {\n const attributes: Parameter[] = [];\n const requiredFields = schema.required || [];\n\n for (const [propName, propSchema] of Object.entries(\n schema.properties,\n )) {\n attributes.push(\n convertJsonSchemaToParameter(\n propName,\n propSchema,\n requiredFields.includes(propName),\n ),\n );\n }\n\n return {\n ...baseParameter,\n type: \"object\",\n attributes,\n };\n }\n return {\n ...baseParameter,\n type: \"object\",\n };\n case \"array\":\n if (schema.items.type === \"object\" && \"properties\" in schema.items) {\n const attributes: Parameter[] = [];\n const requiredFields = schema.items.required || [];\n\n for (const [propName, propSchema] of Object.entries(\n schema.items.properties || {},\n )) {\n attributes.push(\n convertJsonSchemaToParameter(\n propName,\n propSchema,\n requiredFields.includes(propName),\n ),\n );\n }\n\n return {\n ...baseParameter,\n type: \"object[]\",\n attributes,\n };\n } else if (schema.items.type === \"array\") {\n throw new Error(\"Nested arrays are not supported\");\n } else {\n return {\n ...baseParameter,\n type: `${schema.items.type}[]`,\n };\n }\n default:\n return {\n ...baseParameter,\n type: \"string\",\n };\n }\n}\n\nfunction convertAttribute(attribute: Parameter): JSONSchema {\n switch (attribute.type) {\n case \"string\":\n return {\n type: \"string\",\n description: attribute.description,\n ...(attribute.enum && { enum: attribute.enum }),\n };\n case \"number\":\n case \"boolean\":\n return {\n type: attribute.type,\n description: attribute.description,\n };\n case \"object\":\n case \"object[]\":\n const properties = attribute.attributes?.reduce(\n (acc, attr) => {\n acc[attr.name] = convertAttribute(attr);\n return acc;\n },\n {} as Record<string, any>,\n );\n const required = attribute.attributes\n ?.filter((attr) => attr.required !== false)\n .map((attr) => attr.name);\n if (attribute.type === \"object[]\") {\n return {\n type: \"array\",\n items: {\n type: \"object\",\n ...(properties && { properties }),\n ...(required && required.length > 0 && { required }),\n },\n description: attribute.description,\n };\n }\n return {\n type: \"object\",\n description: attribute.description,\n ...(properties && { properties }),\n ...(required && required.length > 0 && { required }),\n };\n default:\n // Handle arrays of primitive types and undefined attribute.type\n if (attribute.type?.endsWith(\"[]\")) {\n const itemType = attribute.type.slice(0, -2);\n return {\n type: \"array\",\n items: { type: itemType as any },\n description: attribute.description,\n };\n }\n // Fallback for undefined type or any other unexpected type\n return {\n type: \"string\",\n description: attribute.description,\n };\n }\n}\n\nexport function convertJsonSchemaToZodSchema(\n jsonSchema: any,\n required: boolean,\n definitions?: Record<string, any>,\n visitedRefs?: Set<string>,\n): z.ZodSchema {\n // Resolve $ref references\n if (jsonSchema.$ref && definitions) {\n const refPath = jsonSchema.$ref.replace(\n /^#\\/\\$defs\\/|^#\\/definitions\\//,\n \"\",\n );\n\n // Detect circular $ref cycles\n const refs = visitedRefs ?? new Set<string>();\n if (refs.has(refPath)) {\n console.warn(\n `[CopilotKit] Circular $ref detected for \"${refPath}\" — falling back to z.any()`,\n );\n let schema = z.any();\n if (jsonSchema.description) {\n schema = schema.describe(jsonSchema.description);\n }\n return required ? schema : schema.optional();\n }\n\n const resolved = definitions[refPath];\n if (resolved) {\n // Clone the set so sibling branches don't see each other's visited refs\n const nextRefs = new Set(refs);\n nextRefs.add(refPath);\n return convertJsonSchemaToZodSchema(\n resolved,\n required,\n definitions,\n nextRefs,\n );\n }\n }\n\n // Collect top-level definitions for $ref resolution\n const defs = definitions ?? jsonSchema.$defs ?? jsonSchema.definitions;\n\n // Handle null-union types like [\"string\", \"null\"]\n if (Array.isArray(jsonSchema.type)) {\n const types = jsonSchema.type as string[];\n const hasNull = types.includes(\"null\");\n const nonNullTypes = types.filter((t: string) => t !== \"null\");\n const resolvedType = nonNullTypes.length > 0 ? nonNullTypes[0] : \"string\";\n const innerSchema = convertJsonSchemaToZodSchema(\n { ...jsonSchema, type: resolvedType },\n true,\n defs,\n visitedRefs,\n );\n let schema = hasNull ? z.union([innerSchema, z.null()]) : innerSchema;\n if (jsonSchema.description) {\n schema = schema.describe(jsonSchema.description);\n }\n return required ? schema : schema.optional();\n }\n\n // Handle anyOf / oneOf as z.union\n const unionVariants = jsonSchema.anyOf ?? jsonSchema.oneOf;\n if (Array.isArray(unionVariants) && unionVariants.length > 0) {\n if (unionVariants.length === 1) {\n return convertJsonSchemaToZodSchema(\n unionVariants[0],\n required,\n defs,\n visitedRefs,\n );\n }\n const schemas = unionVariants.map((v: any) =>\n convertJsonSchemaToZodSchema(v, true, defs, visitedRefs),\n );\n let schema = z.union(\n schemas as [z.ZodSchema, z.ZodSchema, ...z.ZodSchema[]],\n );\n if (jsonSchema.description) {\n schema = schema.describe(jsonSchema.description);\n }\n return required ? schema : schema.optional();\n }\n\n if (jsonSchema.type === \"object\") {\n const spec: { [key: string]: z.ZodSchema } = {};\n\n if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) {\n return !required ? z.object(spec).optional() : z.object(spec);\n }\n\n for (const [key, value] of Object.entries(jsonSchema.properties)) {\n spec[key] = convertJsonSchemaToZodSchema(\n value,\n jsonSchema.required ? jsonSchema.required.includes(key) : false,\n defs,\n visitedRefs,\n );\n }\n let schema = z.object(spec).describe(jsonSchema.description);\n return required ? schema : schema.optional();\n } else if (jsonSchema.type === \"string\") {\n if (jsonSchema.enum && jsonSchema.enum.length > 0) {\n let schema = z\n .enum(jsonSchema.enum as [string, ...string[]])\n .describe(jsonSchema.description);\n return required ? schema : schema.optional();\n }\n let schema = z.string().describe(jsonSchema.description);\n return required ? schema : schema.optional();\n } else if (jsonSchema.type === \"number\" || jsonSchema.type === \"integer\") {\n let schema = z.number().describe(jsonSchema.description);\n return required ? schema : schema.optional();\n } else if (jsonSchema.type === \"boolean\") {\n let schema = z.boolean().describe(jsonSchema.description);\n return required ? schema : schema.optional();\n } else if (jsonSchema.type === \"array\") {\n let itemSchema = convertJsonSchemaToZodSchema(\n jsonSchema.items,\n true,\n defs,\n visitedRefs,\n );\n let schema = z.array(itemSchema).describe(jsonSchema.description);\n return required ? schema : schema.optional();\n } else if (jsonSchema.type === \"null\") {\n let schema = z.null().describe(jsonSchema.description);\n return required ? schema : schema.optional();\n }\n\n // Fallback: accept any value rather than throwing\n console.warn(\n `[CopilotKit] Unsupported JSON schema type \"${jsonSchema.type ?? \"unknown\"}\" — falling back to z.any()`,\n );\n let schema = z.any();\n if (jsonSchema.description) {\n schema = schema.describe(jsonSchema.description);\n }\n return required ? schema : schema.optional();\n}\n\nexport function getZodParameters<T extends [] | Parameter[] | undefined>(\n parameters: T,\n): any {\n if (!parameters) return z.object({});\n const jsonParams = actionParametersToJsonSchema(parameters);\n return convertJsonSchemaToZodSchema(jsonParams, true);\n}\n"],"mappings":"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"}