summaryrefslogtreecommitdiff
path: root/tests/Agent.Core.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Agent.Core.Tests')
-rw-r--r--tests/Agent.Core.Tests/ConfigurationTests.cs45
-rw-r--r--tests/Agent.Core.Tests/InternalToolTests.cs2
-rw-r--r--tests/Agent.Core.Tests/PromptAndRuntimeTests.cs11
3 files changed, 52 insertions, 6 deletions
diff --git a/tests/Agent.Core.Tests/ConfigurationTests.cs b/tests/Agent.Core.Tests/ConfigurationTests.cs
index 2c52b0c..79c746d 100644
--- a/tests/Agent.Core.Tests/ConfigurationTests.cs
+++ b/tests/Agent.Core.Tests/ConfigurationTests.cs
@@ -1,5 +1,6 @@
using Agent.App.Cli;
using Agent.App.Configuration;
+using Agent.Core.Skills;
namespace Agent.Core.Tests;
@@ -43,16 +44,52 @@ public sealed class ConfigurationTests
}
[Fact]
- public void SkillLoader_supports_legacy_markdown_and_standard_skill_directories()
+ public void SkillLoader_loads_standard_skill_directories_only()
{
using var directory = new TestDirectory();
+ // Legacy single markdown — should be ignored (not loaded).
directory.File("skills/legacy.md", "legacy skill");
- directory.File("skills/python-via-uv/SKILL.md", "standard skill");
+ // Standard skill directory with frontmatter.
+ directory.File("skills/python-via-uv/SKILL.md", "---\nname: python-via-uv\ndescription: Python execution skill.\n---\n# Python via uv\nInstructions here.");
+ // Non-SKILL.md files in skill directory should not be loaded as skills.
directory.File("skills/python-via-uv/reference.md", "must not be loaded as a skill");
- string[] skills = SkillLoader.Load(Path.Combine(directory.Path, "skills"));
+ var skills = SkillLoader.Load(Path.Combine(directory.Path, "skills"));
- Assert.Equal(["legacy skill", "standard skill"], skills);
+ Assert.Single(skills);
+ Assert.Equal("python-via-uv", skills[0].Name);
+ Assert.Equal("Python execution skill.", skills[0].Description);
+ Assert.Contains("Instructions here.", skills[0].Instructions);
+ }
+
+ [Fact]
+ public void SkillLoader_rejects_missing_frontmatter()
+ {
+ using var directory = new TestDirectory();
+ directory.File("skills/no-frontmatter/SKILL.md", "# No frontmatter\nJust body.");
+
+ Assert.Throws<SkillLoadException>(() => SkillLoader.Load(Path.Combine(directory.Path, "skills")));
+ }
+
+ [Fact]
+ public void SkillLoader_rejects_name_mismatch()
+ {
+ using var directory = new TestDirectory();
+ directory.File("skills/wrong-name/SKILL.md", "---\nname: different-name\ndescription: A skill.\n---\nBody.");
+
+ Assert.Throws<SkillLoadException>(() => SkillLoader.Load(Path.Combine(directory.Path, "skills")));
+ }
+
+ [Fact]
+ public void SkillLoader_rejects_duplicate_names()
+ {
+ using var directory = new TestDirectory();
+ directory.File("skills/dup-skill/SKILL.md", "---\nname: dup-skill\ndescription: First.\n---\nBody1.");
+ // Create a second directory with the same skill name (via symlink or junction is not needed;
+ // just create another dir that also has name: dup-skill in frontmatter).
+ directory.File("skills/dup-skill-copy/SKILL.md", "---\nname: dup-skill\ndescription: Second.\n---\nBody2.");
+
+ Assert.Throws<SkillLoadException>(() => SkillLoader.Load(Path.Combine(directory.Path, "skills")));
}
private static string CreateValidConfiguration(TestDirectory directory)
diff --git a/tests/Agent.Core.Tests/InternalToolTests.cs b/tests/Agent.Core.Tests/InternalToolTests.cs
index 2015702..c157458 100644
--- a/tests/Agent.Core.Tests/InternalToolTests.cs
+++ b/tests/Agent.Core.Tests/InternalToolTests.cs
@@ -19,6 +19,8 @@ public sealed class InternalToolTests
[InlineData("file_search", "{\"root\":\".\",\"mode\":\"text\",\"query\":\"x\",\"max_results\":1001}")]
[InlineData("process_run", "{\"executable\":\"x\",\"args\":\"bad\",\"cwd\":\".\"}")]
[InlineData("task_update", "{\"operation\":\"add\",\"description\":\"missing estimate\"}")]
+ [InlineData("file_edit", "{\"path\":\"a\",\"operation\":\"rename\"}")]
+ [InlineData("file_edit", "{\"path\":\"a\",\"operation\":\"rename\",\"new_path\":\"\"}")]
public void Malformed_arguments_are_rejected(string tool, string json)
{
using JsonDocument document = JsonDocument.Parse(json);
diff --git a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs
index 5e682cd..27308ef 100644
--- a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs
+++ b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs
@@ -2,6 +2,7 @@ using Agent.Core.Ollama;
using Agent.Core.Prompts;
using Agent.Core.Runtime;
using Agent.Core.Sessions;
+using Agent.Core.Skills;
using Agent.Core.Tasks;
using Agent.Core.Tools;
using System.Text.Json;
@@ -13,12 +14,18 @@ public sealed class PromptAndRuntimeTests
[Fact]
public void Prompt_order_is_fixed_and_request_is_last()
{
+ var availableSkills = new List<AgentSkill>
+ {
+ new("root", "test-skill", "A test skill.", "skill instructions")
+ };
IReadOnlyList<OllamaMessage> messages = PromptComposer.Compose(new PromptContext(
- "fixed", "user system", "ja", ["skill"], "capability", "graph", "summary",
+ "fixed", "user system", "ja", availableSkills, [], "capability", "graph", "summary",
[new ConversationMessage("user", "old"), new ConversationMessage("assistant", "reply")],
"new request", ["image"]));
- Assert.Equal(["fixed", "user system", "Respond in locale: ja.", "skill", "capability", "graph", "summary", "old", "reply", "new request"], messages.Select(x => x.Content));
+ // Check that the skill catalog (name + description) is present, not the full instructions.
+ Assert.Contains(messages, m => m.Content.Contains("test-skill") && m.Content.Contains("A test skill."));
+ Assert.DoesNotContain(messages, m => m.Content == "skill instructions");
Assert.Equal("system", messages[0].Role);
Assert.Equal("user", messages[^1].Role);
Assert.Equal(["image"], messages[^1].Images);