Ctrl K
ComunidadGuías…

internal/app/skill_file_requirement_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package app

import (
	"bytes"
	"log/slog"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/yeomyeonggeori/blueclaw/internal/skill"
)

func skillsRootDeclaringAFont(t *testing.T, fontPaths []string) string {
	t.Helper()
	skillsRoot := filepath.Join(t.TempDir(), "skills")
	skillPath := filepath.Join(skillsRoot, "pdf")
	if errorValue := os.MkdirAll(skillPath, 0o755); errorValue != nil {
		t.Fatal(errorValue)
	}
	document := `---
name: pdf
description: Writes a PDF from a source.
metadata:
  kim.intern.requires-any-file: "` + strings.Join(fontPaths, " ") + `"
---
Write the PDF.
`
	if errorValue := os.WriteFile(filepath.Join(skillPath, "SKILL.md"), []byte(document), 0o644); errorValue != nil {
		t.Fatal(errorValue)
	}
	return skillsRoot
}

func TestASkillWhoseDeclaredFileIsAbsentIsLeftOutOfThePrompt(t *testing.T) {
	absentFontPath := filepath.Join(t.TempDir(), "NanumGothic.ttf")

	discovered := readSkillInstructions(t.TempDir(), skillsRootDeclaringAFont(t, []string{absentFontPath}), []string{})

	if len(discovered.Selectable) != 0 {
		t.Fatalf("a skill that would write the wrong file must not be offered, got %+v", discovered.Selectable)
	}
	if len(discovered.Unavailable) != 1 || discovered.Unavailable[0].Name != "pdf" {
		t.Fatalf("expected pdf listed as unavailable, got %+v", discovered.Unavailable)
	}
	missingPaths := discovered.Unavailable[0].MissingAnyFilePaths
	if len(missingPaths) != 1 || missingPaths[0] != absentFontPath {
		t.Fatalf("expected the path that would have done, got %v", missingPaths)
	}
}

func TestASkillWhoseDeclaredFileIsThereStaysSelectable(t *testing.T) {
	fontDirectory := t.TempDir()
	presentFontPath := filepath.Join(fontDirectory, "NotoSansCJK-Regular.ttc")
	if errorValue := os.WriteFile(presentFontPath, []byte("font"), 0o644); errorValue != nil {
		t.Fatal(errorValue)
	}
	absentFontPath := filepath.Join(fontDirectory, "NanumGothic.ttf")

	discovered := readSkillInstructions(t.TempDir(), skillsRootDeclaringAFont(t, []string{absentFontPath, presentFontPath}), []string{})

	if len(discovered.Unavailable) != 0 {
		t.Fatalf("one of the alternatives being there is enough, got %+v", discovered.Unavailable)
	}
	if len(discovered.Selectable) != 1 || discovered.Selectable[0].Name != "pdf" {
		t.Fatalf("expected pdf offered, got %+v", discovered.Selectable)
	}
}

// A skill left out for a missing tool used to be the only one said out loud.
// Every other reason reached the inventory and nothing else, so a host that had
// quietly dropped a skill looked the same as one that never shipped it.
func TestStartupSaysEveryReasonASkillWasLeftOut(t *testing.T) {
	logDocument := bytes.Buffer{}
	logger := slog.New(slog.NewTextHandler(&logDocument, nil))

	logSkillsThisHostCannotSatisfy(logger, []skill.UnavailableSkill{
		{Name: "internkim-api", Path: "/skills/internkim-api/SKILL.md", MissingEnvironmentVariables: []string{"INTERNKIM_TOKEN"}},
		{Name: "pdf", Path: "/skills/pdf/SKILL.md", MissingAnyFilePaths: []string{"/usr/share/fonts/truetype/nanum/NanumGothic.ttf"}},
		{Name: "calendar", Path: "/skills/calendar/SKILL.md", MissingToolNames: []string{"event_add"}},
	})

	for _, expectedText := range []string{
		`skill.environment.missing`, `missingEnvironment=INTERNKIM_TOKEN`,
		`skill.file.missing`, `anyOfTheseWouldHaveDone=/usr/share/fonts/truetype/nanum/NanumGothic.ttf`,
		`skill.tools.missing`, `missingTools=event_add`,
	} {
		if !strings.Contains(logDocument.String(), expectedText) {
			t.Fatalf("startup must say %q; it said:\n%s", expectedText, logDocument.String())
		}
	}
}