fix(coding-agent): allow skill names to differ from directories
closes #4534
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed skill diagnostics to stop warning when a skill name differs from its parent directory ([#4534](https://github.com/earendil-works/pi/issues/4534)).
|
||||||
- Fixed prompt template argument parsing to split unquoted multiline input on newlines ([#4553](https://github.com/earendil-works/pi/issues/4553)).
|
- Fixed prompt template argument parsing to split unquoted multiline input on newlines ([#4553](https://github.com/earendil-works/pi/issues/4553)).
|
||||||
- Fixed `--resume` session listing to cap in-flight session metadata loads and avoid OOM on large session histories ([#4583](https://github.com/earendil-works/pi/issues/4583)).
|
- Fixed `--resume` session listing to cap in-flight session metadata loads and avoid OOM on large session histories ([#4583](https://github.com/earendil-works/pi/issues/4583)).
|
||||||
- Fixed interactive error messages to render with trailing spacing so reload errors do not run into resource listings ([#4510](https://github.com/earendil-works/pi/issues/4510)).
|
- Fixed interactive error messages to render with trailing spacing so reload errors do not run into resource listings ([#4510](https://github.com/earendil-works/pi/issues/4510)).
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
||||||
|
|
||||||
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about most violations but remaining lenient. Pi allows skill names to differ from their parent directory even though the standard disallows it; that rule is suboptimal for shared skill directories used across multiple agent harnesses.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
|
|||||||
|
|
||||||
| Field | Required | Description |
|
| Field | Required | Description |
|
||||||
|-------|----------|-------------|
|
|-------|----------|-------------|
|
||||||
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Must match parent directory. |
|
| `name` | Yes | Max 64 chars. Lowercase a-z, 0-9, hyphens. Unlike the standard, Pi does not require this to match the parent directory because that standard requirement is suboptimal for shared skill directories. |
|
||||||
| `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
|
| `description` | Yes | Max 1024 chars. What the skill does and when to use it. |
|
||||||
| `license` | No | License name or reference to bundled file. |
|
| `license` | No | License name or reference to bundled file. |
|
||||||
| `compatibility` | No | Max 500 chars. Environment requirements. |
|
| `compatibility` | No | Max 500 chars. Environment requirements. |
|
||||||
@@ -154,7 +154,7 @@ Per the [Agent Skills specification](https://agentskills.io/specification#frontm
|
|||||||
- Lowercase letters, numbers, hyphens only
|
- Lowercase letters, numbers, hyphens only
|
||||||
- No leading/trailing hyphens
|
- No leading/trailing hyphens
|
||||||
- No consecutive hyphens
|
- No consecutive hyphens
|
||||||
- Must match parent directory name
|
Pi does not require the name to match the parent directory. The Agent Skills standard does, but that requirement is suboptimal for shared skill directories used by multiple tools.
|
||||||
|
|
||||||
Valid: `pdf-processing`, `data-analysis`, `code-review`
|
Valid: `pdf-processing`, `data-analysis`, `code-review`
|
||||||
Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
|
Invalid: `PDF-Processing`, `-pdf`, `pdf--processing`
|
||||||
@@ -177,7 +177,6 @@ description: Helps with PDFs.
|
|||||||
|
|
||||||
Pi validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
Pi validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||||
|
|
||||||
- Name doesn't match parent directory
|
|
||||||
- Name exceeds 64 characters or contains invalid characters
|
- Name exceeds 64 characters or contains invalid characters
|
||||||
- Name starts/ends with hyphen or has consecutive hyphens
|
- Name starts/ends with hyphen or has consecutive hyphens
|
||||||
- Description exceeds 1024 characters
|
- Description exceeds 1024 characters
|
||||||
|
|||||||
@@ -90,13 +90,9 @@ export interface LoadSkillsResult {
|
|||||||
* Validate skill name per Agent Skills spec.
|
* Validate skill name per Agent Skills spec.
|
||||||
* Returns array of validation error messages (empty if valid).
|
* Returns array of validation error messages (empty if valid).
|
||||||
*/
|
*/
|
||||||
function validateName(name: string, parentDirName: string): string[] {
|
function validateName(name: string): string[] {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
|
|
||||||
if (name !== parentDirName) {
|
|
||||||
errors.push(`name "${name}" does not match parent directory "${parentDirName}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.length > MAX_NAME_LENGTH) {
|
if (name.length > MAX_NAME_LENGTH) {
|
||||||
errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
|
errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
|
||||||
}
|
}
|
||||||
@@ -301,7 +297,7 @@ function loadSkillFromFile(
|
|||||||
const name = frontmatter.name || parentDirName;
|
const name = frontmatter.name || parentDirName;
|
||||||
|
|
||||||
// Validate name
|
// Validate name
|
||||||
const nameErrors = validateName(name, parentDirName);
|
const nameErrors = validateName(name);
|
||||||
for (const error of nameErrors) {
|
for (const error of nameErrors) {
|
||||||
diagnostics.push({ type: "warning", message: error, path: filePath });
|
diagnostics.push({ type: "warning", message: error, path: filePath });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ describe("skills", () => {
|
|||||||
expect(diagnostics).toHaveLength(0);
|
expect(diagnostics).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should warn when name doesn't match parent directory", () => {
|
it("should allow names that don't match parent directory", () => {
|
||||||
const { skills, diagnostics } = loadSkillsFromDir({
|
const { skills, diagnostics } = loadSkillsFromDir({
|
||||||
dir: join(fixturesDir, "name-mismatch"),
|
dir: join(fixturesDir, "name-mismatch"),
|
||||||
source: "test",
|
source: "test",
|
||||||
@@ -51,7 +51,7 @@ describe("skills", () => {
|
|||||||
expect(skills[0].name).toBe("different-name");
|
expect(skills[0].name).toBe("different-name");
|
||||||
expect(
|
expect(
|
||||||
diagnostics.some((d: ResourceDiagnostic) => d.message.includes("does not match parent directory")),
|
diagnostics.some((d: ResourceDiagnostic) => d.message.includes("does not match parent directory")),
|
||||||
).toBe(true);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should warn when name contains invalid characters", () => {
|
it("should warn when name contains invalid characters", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user