package com.agent.management.parser; import com.agent.management.model.dto.IOField; import com.agent.management.model.dto.SkillDTO; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Optional; /** * SKILL.md 文件解析器 * 解析文件头部的 name、description、inputs、outputs 字段 */ @Slf4j @Component public class SkillMarkdownParser { private static final String NAME_PREFIX = "name:"; private static final String DESC_PREFIX = "description:"; private static final String INPUTS_PREFIX = "inputs:"; private static final String OUTPUTS_PREFIX = "outputs:"; private final ObjectMapper objectMapper = new ObjectMapper(); /** * 解析 SKILL.md 文件,提取 name、description、inputs、outputs * * @param skillMdPath SKILL.md 文件路径 * @return 解析后的 SkillDTO,若解析失败返回 empty */ public Optional parse(Path skillMdPath) { SkillDTO dto = new SkillDTO(); dto.setPath(skillMdPath.getParent().toString()); dto.setFolderName(skillMdPath.getParent().getFileName().toString()); try (BufferedReader reader = Files.newBufferedReader(skillMdPath, StandardCharsets.UTF_8)) { String name = null; String description = null; List inputs = null; List outputs = null; String line; int lineCount = 0; int maxLinesToScan = 30; while ((line = reader.readLine()) != null && lineCount < maxLinesToScan) { lineCount++; String trimmed = line.trim(); // 跳过空行、注释行、Markdown 标题行、frontmatter 分隔符 if (trimmed.isEmpty() || trimmed.startsWith("