Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ public static boolean saveSkills(Path baseDir, List<AgentSkill> skills, boolean
return false;
}

int size = skills.size();
int saveCount = 0;
try {
for (AgentSkill skill : skills) {
String skillName = skill.getName();
Expand All @@ -182,7 +184,7 @@ public static boolean saveSkills(Path baseDir, List<AgentSkill> skills, boolean
if (!force) {
logger.info(
"Skill directory already exists and force=false: {}", skillName);
return false;
continue; // Skip to the next skill if force=false
} else {
logger.info("Overwriting existing skill directory: {}", skillName);
deleteDirectory(skillDir);
Expand Down Expand Up @@ -215,10 +217,15 @@ public static boolean saveSkills(Path baseDir, List<AgentSkill> skills, boolean
}
}

saveCount++;
logger.info("Successfully saved skill: {}", skillName);
}
boolean allSaved = (size == saveCount);
if (!allSaved) {
logger.warn("Not all skills were saved. Saved {} of {}", saveCount, size);
}

return true;
return allSaved;
} catch (IOException e) {
logger.error("Failed to save skills", e);
throw new RuntimeException("Failed to save skills", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,72 @@ void testSaveSkills_ExistingSkill_ForceDisabled() {
assertEquals("Test Skill", loaded.getDescription());
}

@Test
@DisplayName(
"Should save zero skills and leave file contents unchanged when all exist and force is"
+ " false")
void testSaveSkills_AllExistingSkills_ForceDisabled_NoSkillsSaved() throws IOException {
String originalTestSkill =
Files.readString(
skillsBaseDir.resolve("test-skill/SKILL.md"), StandardCharsets.UTF_8);
String originalAnotherSkill =
Files.readString(
skillsBaseDir.resolve("another-skill/SKILL.md"), StandardCharsets.UTF_8);

AgentSkill skill1 = new AgentSkill("test-skill", "Updated Test", "Updated content 1", null);
AgentSkill skill2 =
new AgentSkill("another-skill", "Updated Another", "Updated content 2", null);

boolean result =
SkillFileSystemHelper.saveSkills(skillsBaseDir, List.of(skill1, skill2), false);

// 0 out of 2 saved — no coverage at all
assertFalse(result);
assertEquals(
originalTestSkill,
Files.readString(
skillsBaseDir.resolve("test-skill/SKILL.md"), StandardCharsets.UTF_8),
"test-skill SKILL.md must not be modified");
assertEquals(
originalAnotherSkill,
Files.readString(
skillsBaseDir.resolve("another-skill/SKILL.md"), StandardCharsets.UTF_8),
"another-skill SKILL.md must not be modified");
}

@Test
@DisplayName("Should save new skills while leaving existing ones unchanged when force is false")
void testSaveSkills_MixedSkills_ForceDisabled_NewSavedExistingUnchanged() throws IOException {
String originalContent =
Files.readString(
skillsBaseDir.resolve("test-skill/SKILL.md"), StandardCharsets.UTF_8);

AgentSkill existingSkill =
new AgentSkill("test-skill", "Updated Description", "Updated content", null);
AgentSkill newSkill = new AgentSkill("brand-new-skill", "Brand New", "New content", null);

boolean result =
SkillFileSystemHelper.saveSkills(
skillsBaseDir, List.of(existingSkill, newSkill), false);

// 1 out of 2 saved — not all saved
assertFalse(result);

// existing skill must not be modified
assertEquals(
originalContent,
Files.readString(
skillsBaseDir.resolve("test-skill/SKILL.md"), StandardCharsets.UTF_8),
"test-skill SKILL.md must not be modified");

// new skill must be saved correctly
AgentSkill loaded =
SkillFileSystemHelper.loadSkill(skillsBaseDir, "brand-new-skill", "source");
assertEquals("brand-new-skill", loaded.getName());
assertEquals("Brand New", loaded.getDescription());
assertEquals("New content", loaded.getSkillContent());
}

@Test
@DisplayName("Should overwrite when skill exists and force is true")
void testSaveSkills_ExistingSkill_ForceEnabled() {
Expand Down