UNPKG

@langgraph-js/sdk

Version:

The UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces

120 lines (119 loc) 4.6 kB
/** * copy and modify from copilotkit * https://github.com/copilotkit/copilotkit * * MIT License */ import { z } from "zod"; export function actionParametersToJsonSchema(actionParameters) { // Create the parameters object based on the argumentAnnotations let parameters = {}; for (let parameter of actionParameters || []) { parameters[parameter.name] = convertAttribute(parameter); } let requiredParameterNames = []; for (let arg of actionParameters || []) { if (arg.required !== false) { requiredParameterNames.push(arg.name); } } // Create the ChatCompletionFunctions object return { type: "object", properties: parameters, required: requiredParameterNames, }; } function convertAttribute(attribute) { switch (attribute.type) { case "string": return { type: "string", description: attribute.description, ...(attribute.enum && { enum: attribute.enum }), }; case "number": case "boolean": return { type: attribute.type, description: attribute.description, }; case "object": case "object[]": const properties = attribute.attributes?.reduce((acc, attr) => { acc[attr.name] = convertAttribute(attr); return acc; }, {}); const required = attribute.attributes?.filter((attr) => attr.required !== false).map((attr) => attr.name); if (attribute.type === "object[]") { return { type: "array", items: { type: "object", ...(properties && { properties }), ...(required && required.length > 0 && { required }), }, description: attribute.description, }; } return { type: "object", description: attribute.description, ...(properties && { properties }), ...(required && required.length > 0 && { required }), }; default: // Handle arrays of primitive types and undefined attribute.type if (attribute.type?.endsWith("[]")) { const itemType = attribute.type.slice(0, -2); return { type: "array", items: { type: itemType }, description: attribute.description, }; } // Fallback for undefined type or any other unexpected type return { type: "string", description: attribute.description, }; } } export function convertJsonSchemaToZodRawShape(jsonSchema) { const spec = {}; for (const [key, value] of Object.entries(jsonSchema.properties)) { spec[key] = convertJsonSchemaToZodSchema(value, jsonSchema.required ? jsonSchema.required.includes(key) : false); } return spec; } export function convertJsonSchemaToZodSchema(jsonSchema, required) { if (jsonSchema.type === "object") { const spec = {}; if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) { return !required ? z.object(spec).optional() : z.object(spec); } for (const [key, value] of Object.entries(jsonSchema.properties)) { spec[key] = convertJsonSchemaToZodSchema(value, jsonSchema.required ? jsonSchema.required.includes(key) : false); } let schema = z.object(spec).describe(jsonSchema.description); return required ? schema : schema.optional(); } else if (jsonSchema.type === "string") { let schema = z.string().describe(jsonSchema.description); return required ? schema : schema.optional(); } else if (jsonSchema.type === "number") { let schema = z.number().describe(jsonSchema.description); return required ? schema : schema.optional(); } else if (jsonSchema.type === "boolean") { let schema = z.boolean().describe(jsonSchema.description); return required ? schema : schema.optional(); } else if (jsonSchema.type === "array") { let itemSchema = convertJsonSchemaToZodSchema(jsonSchema.items, true); let schema = z.array(itemSchema).describe(jsonSchema.description); return required ? schema : schema.optional(); } throw new Error("Invalid JSON schema"); }