export type SkillQualityNodeKey = | "trigger" | "inputs" | "steps" | "output" | "constraints"; export type SkillNodeQuality = { complete: boolean; missing: string[]; }; function normalizedContent(content: string) { return content.replace(/\s+/g, " ").trim(); } function hasOrderedSteps(content: string) { const numberedSteps = content.match(/(?:^|[\n;;。])\s*(?:步骤\s*)?\d+[.、)::]/g)?.length ?? 0; const sequenceMarkers = ["先", "再", "然后", "接着", "最后", "最终"].filter( (marker) => content.includes(marker), ).length; const actionSegments = content .split(/[\n;;。]+/) .filter((segment) => /(?:检查|识别|提取|分析|整理|比较|判断|生成|输出|复核|验证|标记)/.test( segment, ), ).length; return numberedSteps >= 2 || sequenceMarkers >= 2 || actionSegments >= 2; } export function evaluateSkillNodeQuality( nodeKey: SkillQualityNodeKey, content: string, ): SkillNodeQuality { const normalized = normalizedContent(content); const missing: string[] = []; if (normalized.length < 8) { missing.push("内容过短,尚未形成可执行规范"); return { complete: false, missing }; } switch (nodeKey) { case "trigger": if ( !/(?:当|如果|遇到|用户|场景|适用|触发|不处理|不适用|请求)/.test( normalized, ) ) { missing.push("需要说明何时触发或适用场景"); } break; case "inputs": if ( !/(?:必填|可选|输入|参数|提供|原文|材料|目标|字段|默认|缺失)/.test( normalized, ) ) { missing.push("需要列明执行所需的输入信息"); } break; case "steps": if (!hasOrderedSteps(normalized)) { missing.push("需要至少两个有明确顺序的执行动作"); } break; case "output": if ( !/(?:输出|结果|格式|结构|标题|字段|表格|Markdown|JSON|列表|篇幅|语气|字数|包含)/i.test( normalized, ) ) { missing.push("需要明确结果结构、字段或格式"); } break; case "constraints": if ( !/(?:不得|不能|禁止|必须|至少|至多|缺少|不足|失败|异常|验收|测试|反例|确保|待确认|质量)/.test( normalized, ) ) { missing.push("需要至少一条约束、质量标准或验收条件"); } break; } return { complete: missing.length === 0, missing }; } export function getSkillNodeQualityIssues( nodes: Array<{ key: SkillQualityNodeKey; title: string; content: string; }>, ) { return nodes.flatMap((node) => { const quality = evaluateSkillNodeQuality(node.key, node.content); return quality.missing.map((missing) => `${node.title}:${missing}`); }); } export function skillNodeQualityErrorMessage(issues: string[]) { return `Skill 节点尚未达到可发布标准。需补充:${issues.join(";")}`; }