tests / render.test.ts
tests / render.test.ts
import { describe, expect, it } from "vitest";
import {
hasSkillMarker,
renderActiveReference,
renderError,
renderHint,
renderMessage,
renderNote,
renderReadError,
renderSkillBlock,
} from "../src/render";
import type { Skill } from "../src/types";
const pdf: Skill = {
name: "pdf",
description: "Work with PDF files.",
dir: "/s/pdf",
skillMdPath: "/s/pdf/SKILL.md",
routable: true,
disableModelInvocation: false,
};
const docx: Skill = { ...pdf, name: "docx", description: "Word docs.", dir: "/s/docx", skillMdPath: "/s/docx/SKILL.md" };
describe("renderSkillBlock", () => {
it("wraps the body with name, path, source and probability", () => {
const out = renderSkillBlock(pdf, "# PDF\nDo things.", { source: "jev", p: 0.9123, maxInjectedChars: 1000 });
expect(out).toBe('<skill name="pdf" path="/s/pdf" source="jev" p="0.91">\n# PDF\nDo things.\n</skill>');
});
it("omits p for explicit activation", () => {
const out = renderSkillBlock(pdf, "body", { source: "explicit", maxInjectedChars: 1000 });
expect(out).toBe('<skill name="pdf" path="/s/pdf" source="explicit">\nbody\n</skill>');
});
it("truncates long bodies with a pointer to read_skill_file", () => {
const out = renderSkillBlock(pdf, "abcdefghij", { source: "explicit", maxInjectedChars: 4 });
expect(out).toContain("\nabcd\n[truncated — read the rest with read_skill_file(\"pdf\")]\n</skill>");
});
it("escapes quotes in attributes and hasSkillMarker round-trips", () => {
const weird: Skill = { ...pdf, dir: '/s/we"ird', skillMdPath: '/s/we"ird/SKILL.md' };
expect(renderSkillBlock(weird, "b", { source: "explicit", maxInjectedChars: 100 })).toContain('path="/s/we"ird"');
expect(renderActiveReference({ ...pdf, dir: "/s/a&b" })).toContain('path="/s/a&b"');
expect(hasSkillMarker(renderSkillBlock(pdf, "x", { source: "jev", p: 0.5, maxInjectedChars: 100 }), "pdf")).toBe(true);
});
});
describe("renderReadError", () => {
it("renders the unreadable-skill error", () => {
expect(renderReadError("pdf", "ENOENT: gone")).toBe('<skill_error>Could not read SKILL.md for "pdf": ENOENT: gone</skill_error>');
});
});
describe("other blocks", () => {
it("renders the active reference", () => {
expect(renderActiveReference(pdf)).toBe(
'<skill_active name="pdf" path="/s/pdf">Instructions were given earlier in this conversation and still apply. Use read_skill_file to reload them if needed.</skill_active>',
);
});
it("renders the note", () => {
expect(renderNote()).toBe(
"<skill_note>Files under a skill (references/, scripts/) can be read with read_skill_file(skill, path). To run a script use shell_run if that tool is available; otherwise show the user the exact command to run.</skill_note>",
);
});
it("renders the hint list", () => {
expect(renderHint([pdf, docx])).toBe(
[
"<available_skills>",
"- pdf: Work with PDF files. (/s/pdf)",
"- docx: Word docs. (/s/docx)",
"Call read_skill_file(name) to load a skill's instructions.",
"</available_skills>",
].join("\n"),
);
});
it("renders the unknown-skill error", () => {
expect(renderError("nope", [pdf, docx])).toBe('<skill_error>No skill named "nope". Available: pdf, docx</skill_error>');
});
});
describe("renderMessage", () => {
it("joins blocks and wraps the task", () => {
expect(renderMessage(["<a/>", "<b/>"], "do it")).toBe("<a/>\n\n<b/>\n\n<user_task>\ndo it\n</user_task>");
});
it("uses a placeholder for an empty task", () => {
expect(renderMessage(["<a/>"], "")).toBe(
"<a/>\n\n<user_task>\n(no task text — ask the user what to do with this skill)\n</user_task>",
);
});
});
describe("hasSkillMarker", () => {
it("detects a previously injected skill block by name", () => {
expect(hasSkillMarker('<skill name="pdf" path="/s/pdf" source="jev" p="0.9">x</skill>', "pdf")).toBe(true);
expect(hasSkillMarker('<skill name="pdf-extra" path="/s/pdf-extra" source="jev">x</skill>', "pdf")).toBe(false);
expect(hasSkillMarker("plain text about pdf", "pdf")).toBe(false);
});
});
import { describe, expect, it } from "vitest";
import {
hasSkillMarker,
renderActiveReference,
renderError,
renderHint,
renderMessage,
renderNote,
renderReadError,
renderSkillBlock,
} from "../src/render";
import type { Skill } from "../src/types";
const pdf: Skill = {
name: "pdf",
description: "Work with PDF files.",
dir: "/s/pdf",
skillMdPath: "/s/pdf/SKILL.md",
routable: true,
disableModelInvocation: false,
};
const docx: Skill = { ...pdf, name: "docx", description: "Word docs.", dir: "/s/docx", skillMdPath: "/s/docx/SKILL.md" };
describe("renderSkillBlock", () => {
it("wraps the body with name, path, source and probability", () => {
const out = renderSkillBlock(pdf, "# PDF\nDo things.", { source: "jev", p: 0.9123, maxInjectedChars: 1000 });
expect(out).toBe('<skill name="pdf" path="/s/pdf" source="jev" p="0.91">\n# PDF\nDo things.\n</skill>');
});
it("omits p for explicit activation", () => {
const out = renderSkillBlock(pdf, "body", { source: "explicit", maxInjectedChars: 1000 });
expect(out).toBe('<skill name="pdf" path="/s/pdf" source="explicit">\nbody\n</skill>');
});
it("truncates long bodies with a pointer to read_skill_file", () => {
const out = renderSkillBlock(pdf, "abcdefghij", { source: "explicit", maxInjectedChars: 4 });
expect(out).toContain("\nabcd\n[truncated — read the rest with read_skill_file(\"pdf\")]\n</skill>");
});
it("escapes quotes in attributes and hasSkillMarker round-trips", () => {
const weird: Skill = { ...pdf, dir: '/s/we"ird', skillMdPath: '/s/we"ird/SKILL.md' };
expect(renderSkillBlock(weird, "b", { source: "explicit", maxInjectedChars: 100 })).toContain('path="/s/we"ird"');
expect(renderActiveReference({ ...pdf, dir: "/s/a&b" })).toContain('path="/s/a&b"');
expect(hasSkillMarker(renderSkillBlock(pdf, "x", { source: "jev", p: 0.5, maxInjectedChars: 100 }), "pdf")).toBe(true);
});
});
describe("renderReadError", () => {
it("renders the unreadable-skill error", () => {
expect(renderReadError("pdf", "ENOENT: gone")).toBe('<skill_error>Could not read SKILL.md for "pdf": ENOENT: gone</skill_error>');
});
});
describe("other blocks", () => {
it("renders the active reference", () => {
expect(renderActiveReference(pdf)).toBe(
'<skill_active name="pdf" path="/s/pdf">Instructions were given earlier in this conversation and still apply. Use read_skill_file to reload them if needed.</skill_active>',
);
});
it("renders the note", () => {
expect(renderNote()).toBe(
"<skill_note>Files under a skill (references/, scripts/) can be read with read_skill_file(skill, path). To run a script use shell_run if that tool is available; otherwise show the user the exact command to run.</skill_note>",
);
});
it("renders the hint list", () => {
expect(renderHint([pdf, docx])).toBe(
[
"<available_skills>",
"- pdf: Work with PDF files. (/s/pdf)",
"- docx: Word docs. (/s/docx)",
"Call read_skill_file(name) to load a skill's instructions.",
"</available_skills>",
].join("\n"),
);
});
it("renders the unknown-skill error", () => {
expect(renderError("nope", [pdf, docx])).toBe('<skill_error>No skill named "nope". Available: pdf, docx</skill_error>');
});
});
describe("renderMessage", () => {
it("joins blocks and wraps the task", () => {
expect(renderMessage(["<a/>", "<b/>"], "do it")).toBe("<a/>\n\n<b/>\n\n<user_task>\ndo it\n</user_task>");
});
it("uses a placeholder for an empty task", () => {
expect(renderMessage(["<a/>"], "")).toBe(
"<a/>\n\n<user_task>\n(no task text — ask the user what to do with this skill)\n</user_task>",
);
});
});
describe("hasSkillMarker", () => {
it("detects a previously injected skill block by name", () => {
expect(hasSkillMarker('<skill name="pdf" path="/s/pdf" source="jev" p="0.9">x</skill>', "pdf")).toBe(true);
expect(hasSkillMarker('<skill name="pdf-extra" path="/s/pdf-extra" source="jev">x</skill>', "pdf")).toBe(false);
expect(hasSkillMarker("plain text about pdf", "pdf")).toBe(false);
});
});