UNPKG

dpml-prompt

Version:

DPML-powered AI prompt framework - Revolutionary AI-First CLI system based on Deepractice Prompt Markup Language. Build sophisticated AI agents with structured prompts, memory systems, and execution frameworks.

374 lines (316 loc) 10.6 kB
const { TOOL_INTERFACE, TOOL_ERROR_CODES } = require('./ToolInterface'); /** * ToolValidator - 工具接口验证器 * 使用鸭子类型验证工具是否符合PromptX接口规范 */ class ToolValidator { /** * 验证工具是否符合接口规范 * @param {any} tool - 待验证的工具对象 * @returns {Object} 验证结果 {valid: boolean, errors: [], warnings: []} */ static validateTool(tool) { const errors = []; const warnings = []; // 基础类型检查 if (!tool || typeof tool !== 'object') { errors.push('工具必须是对象类型'); return { valid: false, errors, warnings }; } // 验证必需方法 for (const methodSpec of TOOL_INTERFACE.required) { const methodName = methodSpec.name; if (!(methodName in tool)) { errors.push(`缺少必需方法: ${methodName}`); continue; } if (typeof tool[methodName] !== 'function') { errors.push(`${methodName} 必须是函数类型`); continue; } // 方法签名验证 try { const validationResult = this.validateMethod(tool, methodSpec); if (!validationResult.valid) { errors.push(...validationResult.errors); warnings.push(...validationResult.warnings); } } catch (error) { warnings.push(`${methodName} 方法验证时出错: ${error.message}`); } } // 验证可选方法 for (const methodSpec of TOOL_INTERFACE.optional) { const methodName = methodSpec.name; if (methodName in tool) { if (typeof tool[methodName] !== 'function') { warnings.push(`${methodName} 应该是函数类型`); } else { try { const validationResult = this.validateMethod(tool, methodSpec); if (!validationResult.valid) { warnings.push(...validationResult.errors); } } catch (error) { warnings.push(`${methodName} 方法验证时出错: ${error.message}`); } } } } return { valid: errors.length === 0, errors, warnings }; } /** * 验证特定方法 * @param {Object} tool - 工具对象 * @param {Object} methodSpec - 方法规范 * @returns {Object} 验证结果 */ static validateMethod(tool, methodSpec) { const errors = []; const warnings = []; const methodName = methodSpec.name; try { switch (methodName) { case 'getMetadata': return this.validateGetMetadata(tool); case 'getSchema': return this.validateGetSchema(tool); case 'execute': return this.validateExecute(tool); case 'validate': return this.validateValidateMethod(tool); default: return { valid: true, errors: [], warnings: [] }; } } catch (error) { errors.push(`${methodName} 方法调用失败: ${error.message}`); return { valid: false, errors, warnings }; } } /** * 验证getMetadata方法 * @param {Object} tool - 工具对象 * @returns {Object} 验证结果 */ static validateGetMetadata(tool) { const errors = []; const warnings = []; try { const metadata = tool.getMetadata(); if (!metadata || typeof metadata !== 'object') { errors.push('getMetadata() 必须返回对象'); return { valid: false, errors, warnings }; } // 验证必需字段 if (!metadata.name || typeof metadata.name !== 'string') { errors.push('metadata.name 必须是非空字符串'); } if (!metadata.description || typeof metadata.description !== 'string') { errors.push('metadata.description 必须是非空字符串'); } if (!metadata.version || typeof metadata.version !== 'string') { errors.push('metadata.version 必须是非空字符串'); } // 验证可选字段 if (metadata.category && typeof metadata.category !== 'string') { warnings.push('metadata.category 应该是字符串类型'); } if (metadata.author && typeof metadata.author !== 'string') { warnings.push('metadata.author 应该是字符串类型'); } } catch (error) { errors.push(`getMetadata() 执行失败: ${error.message}`); } return { valid: errors.length === 0, errors, warnings }; } /** * 验证getSchema方法 * @param {Object} tool - 工具对象 * @returns {Object} 验证结果 */ static validateGetSchema(tool) { const errors = []; const warnings = []; try { const schema = tool.getSchema(); if (!schema || typeof schema !== 'object') { errors.push('getSchema() 必须返回对象'); return { valid: false, errors, warnings }; } // 基础JSON Schema验证 if (!schema.type) { warnings.push('schema.type 建议定义'); } if (schema.type && typeof schema.type !== 'string') { errors.push('schema.type 必须是字符串'); } if (schema.properties && typeof schema.properties !== 'object') { errors.push('schema.properties 必须是对象'); } if (schema.required && !Array.isArray(schema.required)) { errors.push('schema.required 必须是数组'); } } catch (error) { errors.push(`getSchema() 执行失败: ${error.message}`); } return { valid: errors.length === 0, errors, warnings }; } /** * 验证execute方法 * @param {Object} tool - 工具对象 * @returns {Object} 验证结果 */ static validateExecute(tool) { const errors = []; const warnings = []; // 检查方法签名 const executeMethod = tool.execute; if (executeMethod.length === 0) { warnings.push('execute() 方法建议接受parameters参数'); } // 注意:这里不实际调用execute方法,因为可能有副作用 // 只进行静态检查 return { valid: errors.length === 0, errors, warnings }; } /** * 验证validate方法(可选) * @param {Object} tool - 工具对象 * @returns {Object} 验证结果 */ static validateValidateMethod(tool) { const errors = []; const warnings = []; try { // 测试validate方法的返回格式 const testParams = {}; const result = tool.validate(testParams); if (!result || typeof result !== 'object') { errors.push('validate() 必须返回对象'); return { valid: false, errors, warnings }; } if (typeof result.valid !== 'boolean') { errors.push('validate() 返回值必须包含valid(boolean)字段'); } if (result.errors && !Array.isArray(result.errors)) { errors.push('validate() 返回值的errors字段必须是数组'); } } catch (error) { warnings.push(`validate() 方法测试失败: ${error.message}`); } return { valid: errors.length === 0, errors, warnings }; } /** * 为工具提供默认的validate方法实现 * @param {Object} tool - 工具对象 * @param {Object} parameters - 待验证参数 * @returns {Object} 验证结果 */ static defaultValidate(tool, parameters) { const errors = []; try { // 获取schema const schema = tool.getSchema(); // 基础类型检查 if (!parameters || typeof parameters !== 'object') { errors.push('参数必须是对象类型'); return { valid: false, errors }; } // 必需参数检查 if (schema.required && Array.isArray(schema.required)) { for (const field of schema.required) { if (!(field in parameters)) { errors.push(`缺少必需参数: ${field}`); } } } // 基础字段类型检查 if (schema.properties && typeof schema.properties === 'object') { for (const [field, fieldSchema] of Object.entries(schema.properties)) { if (field in parameters) { const value = parameters[field]; const expectedType = fieldSchema.type; if (expectedType && !this.validateType(value, expectedType)) { errors.push(`参数 ${field} 类型错误,期望 ${expectedType},实际 ${typeof value}`); } } } } } catch (error) { errors.push(`参数验证失败: ${error.message}`); } return { valid: errors.length === 0, errors }; } /** * 类型验证辅助方法 * @param {*} value - 待验证值 * @param {string} expectedType - 期望类型 * @returns {boolean} 是否匹配 */ static validateType(value, expectedType) { switch (expectedType) { case 'string': return typeof value === 'string'; case 'number': return typeof value === 'number'; case 'boolean': return typeof value === 'boolean'; case 'object': return typeof value === 'object' && value !== null; case 'array': return Array.isArray(value); default: return true; // 未知类型,跳过验证 } } /** * 生成工具接口报告 * @param {Object} tool - 工具对象 * @returns {Object} 接口报告 */ static generateInterfaceReport(tool) { const validation = this.validateTool(tool); const report = { toolName: 'unknown', valid: validation.valid, errors: validation.errors, warnings: validation.warnings, implementedMethods: { required: [], optional: [] }, metadata: null, schema: null }; try { // 获取工具名称 if (tool.getMetadata) { const metadata = tool.getMetadata(); report.toolName = metadata.name || 'unknown'; report.metadata = metadata; } // 获取schema if (tool.getSchema) { report.schema = tool.getSchema(); } // 检查已实现的方法 for (const methodSpec of TOOL_INTERFACE.required) { if (typeof tool[methodSpec.name] === 'function') { report.implementedMethods.required.push(methodSpec.name); } } for (const methodSpec of TOOL_INTERFACE.optional) { if (typeof tool[methodSpec.name] === 'function') { report.implementedMethods.optional.push(methodSpec.name); } } } catch (error) { report.warnings.push(`生成报告时出错: ${error.message}`); } return report; } } module.exports = ToolValidator;