Centralize frontmatter parsing + parse frontmatter with yaml library (#728)

* Add frontmatter utility and tidy coding agent prompts

* Add frontmatter parsing utilities and tests

* Parse frontmatter with YAML parser

* Simplify frontmatter parsing utilities

* strip body in 1 place

* Improve frontmatter parsing error handling

* Normalize multiline skill and select-list descriptions
This commit is contained in:
Richard Gill 2026-01-15 23:31:53 +00:00 committed by GitHub
parent df58d3191e
commit ce7e73b503
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 213 additions and 126 deletions

View file

@ -5,6 +5,7 @@
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { parseFrontmatter } from "@mariozechner/pi-coding-agent";
export type AgentScope = "user" | "project" | "both";
@ -23,36 +24,6 @@ export interface AgentDiscoveryResult {
projectAgentsDir: string | null;
}
function parseFrontmatter(content: string): { frontmatter: Record<string, string>; body: string } {
const frontmatter: Record<string, string> = {};
const normalized = content.replace(/\r\n/g, "\n");
if (!normalized.startsWith("---")) {
return { frontmatter, body: normalized };
}
const endIndex = normalized.indexOf("\n---", 3);
if (endIndex === -1) {
return { frontmatter, body: normalized };
}
const frontmatterBlock = normalized.slice(4, endIndex);
const body = normalized.slice(endIndex + 4).trim();
for (const line of frontmatterBlock.split("\n")) {
const match = line.match(/^([\w-]+):\s*(.*)$/);
if (match) {
let value = match[2].trim();
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
frontmatter[match[1]] = value;
}
}
return { frontmatter, body };
}
function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] {
const agents: AgentConfig[] = [];
@ -79,7 +50,7 @@ function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig
continue;
}
const { frontmatter, body } = parseFrontmatter(content);
const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
if (!frontmatter.name || !frontmatter.description) {
continue;
@ -87,7 +58,7 @@ function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig
const tools = frontmatter.tools
?.split(",")
.map((t) => t.trim())
.map((t: string) => t.trim())
.filter(Boolean);
agents.push({