fix(coding-agent): tighten skill discovery and edit diffs closes #2603

This commit is contained in:
Mario Zechner
2026-03-27 03:48:28 +01:00
parent eeace79715
commit a0734bd162
6 changed files with 168 additions and 48 deletions

View File

@@ -106,6 +106,22 @@ Content`,
expect(result.skills.some((r) => r.path === skillFile && r.enabled)).toBe(true);
});
it("should auto-discover root markdown skills from .pi skill dirs", async () => {
const skillFile = join(agentDir, "skills", "single-file.md");
mkdirSync(join(agentDir, "skills"), { recursive: true });
writeFileSync(
skillFile,
`---
name: single-file
description: A root markdown skill
---
Content`,
);
const result = await packageManager.resolve();
expect(result.skills.some((r) => r.path === skillFile && r.enabled)).toBe(true);
});
it("should resolve project paths relative to .pi", async () => {
const extDir = join(tempDir, ".pi", "extensions");
mkdirSync(extDir, { recursive: true });
@@ -232,6 +248,26 @@ Content`,
expect(result.skills.some((r) => r.path === middleSkill && r.enabled)).toBe(true);
});
it("should ignore root markdown files in .agents/skills", async () => {
const agentsSkillsDir = join(tempDir, ".agents", "skills");
mkdirSync(join(agentsSkillsDir, "nested-skill"), { recursive: true });
const rootSkill = join(agentsSkillsDir, "root-file.md");
const nestedSkill = join(agentsSkillsDir, "nested-skill", "SKILL.md");
writeFileSync(rootSkill, "---\nname: root-file\ndescription: Root markdown file\n---\n");
writeFileSync(nestedSkill, "---\nname: nested-skill\ndescription: Nested skill\n---\n");
const pm = new DefaultPackageManager({
cwd: join(tempDir, "work"),
agentDir,
settingsManager,
});
mkdirSync(join(tempDir, "work"), { recursive: true });
const result = await pm.resolve();
expect(result.skills.some((r) => r.path === rootSkill)).toBe(false);
expect(result.skills.some((r) => r.path === nestedSkill && r.enabled)).toBe(true);
});
it("should keep ~/.agents/skills user-scoped when cwd is under home in a non-git directory", async () => {
const previousHome = process.env.HOME;
process.env.HOME = tempDir;
@@ -352,6 +388,19 @@ Content`,
expect(result.extensions.some((r) => pathEndsWith(r.path, "main.ts") && r.enabled)).toBe(true);
expect(result.themes.some((r) => pathEndsWith(r.path, "dark.json") && r.enabled)).toBe(true);
});
it("should stop recursing when a package skill directory contains SKILL.md", async () => {
const pkgDir = join(tempDir, "skill-root-pkg");
mkdirSync(join(pkgDir, "skills", "root-skill", "nested-skill"), { recursive: true });
const rootSkill = join(pkgDir, "skills", "root-skill", "SKILL.md");
const nestedSkill = join(pkgDir, "skills", "root-skill", "nested-skill", "SKILL.md");
writeFileSync(rootSkill, "---\nname: root-skill\ndescription: Root skill\n---\n");
writeFileSync(nestedSkill, "---\nname: nested-skill\ndescription: Nested skill\n---\n");
const result = await packageManager.resolveExtensionSources([pkgDir]);
expect(result.skills.some((r) => r.path === rootSkill && r.enabled)).toBe(true);
expect(result.skills.some((r) => r.path === nestedSkill)).toBe(false);
});
});
describe("progress callback", () => {

View File

@@ -277,6 +277,29 @@ describe("Coding Agent Tools", () => {
expect(result.details?.diff).toContain("GAMMA");
});
it("should collapse large unchanged gaps in multi-edit diffs", async () => {
const testFile = join(testDir, "edit-multi-large-gap.txt");
const lines = Array.from({ length: 600 }, (_, i) => `line ${String(i + 1).padStart(3, "0")}`);
writeFileSync(testFile, `${lines.join("\n")}\n`);
const result = await editTool.execute("test-call-8b", {
path: testFile,
edits: [
{ oldText: "line 100\n", newText: "LINE 100\n" },
{ oldText: "line 300\n", newText: "LINE 300\n" },
{ oldText: "line 500\n", newText: "LINE 500\n" },
],
});
const diff = result.details?.diff ?? "";
expect(diff).toContain("LINE 100");
expect(diff).toContain("LINE 300");
expect(diff).toContain("LINE 500");
expect(diff).toContain("...");
expect(diff).not.toContain("line 250");
expect(diff.split("\n").length).toBeLessThan(50);
});
it("should match edits against the original file, not incrementally", async () => {
const testFile = join(testDir, "edit-multi-original.txt");
writeFileSync(testFile, "foo\nbar\nbaz\n");