UNPKG

coaian

Version:

Creative Orientation AI Agentic Memories - Narrative Beat Extension with IAIP relational integration

146 lines (145 loc) 5.67 kB
export function validate(args, schema) { if (typeof args !== 'object' || args === null) { return { valid: false, error: 'Arguments must be an object' }; } for (const [key, rule] of Object.entries(schema)) { const value = args[key]; // Check required if (rule.required && (value === undefined || value === null)) { return { valid: false, error: `Missing required field: ${key}` }; } if (value === undefined || value === null) continue; // Type validation const result = validateValue(value, rule, key); if (!result.valid) return result; } return { valid: true }; } function validateValue(value, rule, path) { // Type check switch (rule.type) { case 'string': if (typeof value !== 'string') { return { valid: false, error: `${path} must be a string, got ${typeof value}` }; } if (rule.minLength && value.length < rule.minLength) { return { valid: false, error: `${path} must be at least ${rule.minLength} characters` }; } if (rule.maxLength && value.length > rule.maxLength) { return { valid: false, error: `${path} must be at most ${rule.maxLength} characters` }; } if (rule.pattern && !rule.pattern.test(value)) { return { valid: false, error: `${path} format is invalid` }; } if (rule.enumValues && !rule.enumValues.includes(value)) { return { valid: false, error: `${path} must be one of: ${rule.enumValues.join(', ')}` }; } break; case 'number': if (typeof value !== 'number' || isNaN(value)) { return { valid: false, error: `${path} must be a number` }; } if (rule.minValue !== undefined && value < rule.minValue) { return { valid: false, error: `${path} must be at least ${rule.minValue}` }; } if (rule.maxValue !== undefined && value > rule.maxValue) { return { valid: false, error: `${path} must be at most ${rule.maxValue}` }; } if (rule.enumValues && !rule.enumValues.includes(value)) { return { valid: false, error: `${path} must be one of: ${rule.enumValues.join(', ')}` }; } break; case 'boolean': if (typeof value !== 'boolean') { return { valid: false, error: `${path} must be a boolean` }; } break; case 'date': if (typeof value !== 'string') { return { valid: false, error: `${path} must be an ISO date string` }; } if (isNaN(Date.parse(value))) { return { valid: false, error: `${path} must be a valid ISO date string` }; } break; case 'array': if (!Array.isArray(value)) { return { valid: false, error: `${path} must be an array` }; } if (rule.minLength && value.length < rule.minLength) { return { valid: false, error: `${path} must have at least ${rule.minLength} items` }; } if (rule.maxLength && value.length > rule.maxLength) { return { valid: false, error: `${path} must have at most ${rule.maxLength} items` }; } if (rule.items) { for (let i = 0; i < value.length; i++) { const itemResult = validateValue(value[i], rule.items, `${path}[${i}]`); if (!itemResult.valid) return itemResult; } } break; case 'object': if (typeof value !== 'object' || value === null || Array.isArray(value)) { return { valid: false, error: `${path} must be an object` }; } if (rule.properties) { const nestedResult = validate(value, rule.properties); if (!nestedResult.valid) { return { valid: false, error: `${path}: ${nestedResult.error}` }; } } break; case 'enum': if (!rule.enumValues?.includes(value)) { return { valid: false, error: `${path} must be one of: ${rule.enumValues?.join(', ')}` }; } break; } return { valid: true }; } // Pre-built schemas for common tool patterns export const ValidationSchemas = { stringArray: (minLength = 0) => ({ type: 'array', required: true, minLength, items: { type: 'string' } }), entityArray: () => ({ type: 'array', required: true, items: { type: 'object', properties: { name: { type: 'string', required: true }, entityType: { type: 'string', required: true }, observations: { type: 'array', required: true, items: { type: 'string' } } } } }), relationArray: () => ({ type: 'array', required: true, items: { type: 'object', properties: { from: { type: 'string', required: true }, to: { type: 'string', required: true }, relationType: { type: 'string', required: true } } } }), isoDate: () => ({ type: 'date', required: true }), nonEmptyString: () => ({ type: 'string', required: true, minLength: 1 }) };