161 lines
3.4 KiB
Go
161 lines
3.4 KiB
Go
package skills
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestLoadSkill(t *testing.T) {
|
|
// Create a temp skill
|
|
dir := t.TempDir()
|
|
skillDir := filepath.Join(dir, "test-skill")
|
|
os.MkdirAll(skillDir, 0755)
|
|
content := `---
|
|
name: test-skill
|
|
description: A test skill for unit testing. Use when testing skill loading.
|
|
---
|
|
|
|
# Test Skill
|
|
|
|
This is test content.
|
|
`
|
|
os.WriteFile(filepath.Join(skillDir, "SKILL.md"), []byte(content), 0644)
|
|
|
|
skill, err := loadSkill(filepath.Join(skillDir, "SKILL.md"))
|
|
if err != nil {
|
|
t.Fatalf("loadSkill: %v", err)
|
|
}
|
|
if skill.Name != "test-skill" {
|
|
t.Errorf("name = %q, want %q", skill.Name, "test-skill")
|
|
}
|
|
if skill.Description != "A test skill for unit testing. Use when testing skill loading." {
|
|
t.Errorf("description = %q", skill.Description)
|
|
}
|
|
}
|
|
|
|
func TestParseFrontmatter(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantN string
|
|
wantD string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid",
|
|
input: `---
|
|
name: my-skill
|
|
description: My description
|
|
---
|
|
content`,
|
|
wantN: "my-skill",
|
|
wantD: "My description",
|
|
},
|
|
{
|
|
name: "no frontmatter",
|
|
input: "# Just content",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing name",
|
|
input: `---
|
|
description: test
|
|
---`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing description",
|
|
input: `---
|
|
name: test
|
|
---`,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
n, d, err := parseFrontmatter([]byte(tt.input))
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Error("expected error")
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if n != tt.wantN {
|
|
t.Errorf("name = %q, want %q", n, tt.wantN)
|
|
}
|
|
if d != tt.wantD {
|
|
t.Errorf("description = %q, want %q", d, tt.wantD)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIndexMatch(t *testing.T) {
|
|
// Find model directory
|
|
home, _ := os.UserHomeDir()
|
|
modelDir := ""
|
|
candidates := []string{
|
|
"../data/models",
|
|
filepath.Join(home, ".local/share/ollie/models"),
|
|
}
|
|
for _, c := range candidates {
|
|
if _, err := os.Stat(filepath.Join(c, "model.onnx")); err == nil {
|
|
modelDir = c
|
|
break
|
|
}
|
|
}
|
|
if modelDir == "" {
|
|
t.Skip("model not found")
|
|
}
|
|
|
|
// Create temp skill directory
|
|
dir := t.TempDir()
|
|
|
|
skills := []struct {
|
|
name string
|
|
desc string
|
|
}{
|
|
{"jira-cli", "Interact with Jira for issue tracking. Use for tickets, sprints, and project management."},
|
|
{"github-cli", "Interact with GitHub repositories, issues, and pull requests."},
|
|
{"bash-exec", "Execute bash commands locally or remotely."},
|
|
}
|
|
|
|
for _, s := range skills {
|
|
skillDir := filepath.Join(dir, s.name)
|
|
os.MkdirAll(skillDir, 0755)
|
|
content := "---\nname: " + s.name + "\ndescription: " + s.desc + "\n---\n# " + s.name
|
|
os.WriteFile(filepath.Join(skillDir, "SKILL.md"), []byte(content), 0644)
|
|
}
|
|
|
|
idx, err := NewIndex(modelDir, []string{dir})
|
|
if err != nil {
|
|
t.Fatalf("NewIndex: %v", err)
|
|
}
|
|
defer idx.Close()
|
|
|
|
// Test matching
|
|
results, err := idx.Match("create a jira ticket for the bug", 0.1, 3)
|
|
if err != nil {
|
|
t.Fatalf("Match: %v", err)
|
|
}
|
|
|
|
if len(results) == 0 {
|
|
t.Fatal("expected results")
|
|
}
|
|
|
|
t.Logf("Query: 'create a jira ticket for the bug'")
|
|
for _, r := range results {
|
|
t.Logf(" %s: %.4f", r.Skill.Name, r.Score)
|
|
}
|
|
|
|
// Jira should be top result
|
|
if results[0].Skill.Name != "jira-cli" {
|
|
t.Errorf("expected jira-cli as top result, got %s", results[0].Skill.Name)
|
|
}
|
|
}
|