package com.ankurm.agentskills; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import com.ankurm.agentskills.support.Transcript; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.springaicommunity.agent.tools.SkillsTool; import org.springaicommunity.agent.utils.Skills; import org.springframework.ai.tool.ToolCallback; /** What the loader does with an unknown name, a duplicate name and a SKILL.md with no description. */ class SkillLoadingEdgeCasesTest { @TempDir Path dir; @Test void recordWhatActuallyHappens() throws Exception { Path dup = Files.createDirectories(dir.resolve("copy/release-notes")); Files.writeString(dup.resolve("SKILL.md"), "---\nname: release-notes\ndescription: A second skill that reuses an existing name.\n---\n\nSECOND COPY BODY\n"); Path nodesc = Files.createDirectories(dir.resolve("copy/no-description")); Files.writeString(nodesc.resolve("SKILL.md"), "---\nname: no-description\n---\n\nBODY WITHOUT A DESCRIPTION\n"); try (Transcript t = new Transcript("03-loading-edge-cases.txt", "Unknown, duplicate and description-less skills")) { ToolCallback bundled = SkillClients.bundledSkills(); t.line("== unknown skill name"); t.line("call Skill(command=\"does-not-exist\") returns: %s", oneLine(call(bundled, "does-not-exist"))); t.blank(); t.line("== the same name in two directories (classpath skills first, then the copy)"); ToolCallback both = SkillsTool.builder() .addSkillsResource(new org.springframework.core.io.ClassPathResource("skills")) .addSkillsDirectory(dir.resolve("copy").toString()) .build(); String loaded = call(both, "release-notes"); t.line("body served for release-notes contains the first copy ('Breaking') : %s", loaded.contains("Breaking")); t.line("body served for release-notes contains the second copy : %s", loaded.contains("SECOND COPY BODY")); t.blank(); t.line("== a SKILL.md with no description"); List skills = Skills.loadDirectory(dir.resolve("copy").toString()); skills.forEach(s -> t.line("loaded: name=%s frontMatterKeys=%s", s.name(), s.frontMatter().keySet())); String listing = both.getToolDefinition().description(); t.line("'no-description' appears in the tool description : %s", listing.contains("no-description")); t.blank(); t.line("== the allowed-tools key in sql-review's frontmatter"); t.line("echoed into the listing as : %s", bundled.getToolDefinition().description().contains("Bash")); } } private static String call(ToolCallback tool, String command) { return tool.call("{\"command\":\"" + command + "\"}"); } private static String oneLine(String s) { return s.replace("\n", "\\n"); } }