fix: strip frontmatter from injected skill content and share parser from src

This commit is contained in:
haylan committed 2026-10-14 12:34:56 +02:00
1 parent 023e012eda
commit d301ef5a62
7 files changed
+108 -43

No files matched your search

-42
View File
@@ -1,42 +0,0 @@
// Minimal YAML-subset frontmatter parser for upstream SKILL.md files.
// Supports exactly what mattpocock/skills uses (census 2026-10-14, @49dd158): top-level
// `key: value` scalars, double/single-quoted strings with \" escapes, and nested blocks
// (e.g. `metadata:`) which are skipped. test/generate.test.ts asserts every vendored skill
// parses with non-empty name+description, so an upstream format change fails the build
// instead of silently producing a broken manifest.
export type Frontmatter = Record<string, string>
export function parseFrontmatter(content: string): { frontmatter: Frontmatter; body: string } {
const text = content.replace(/^\uFEFF/, "")
if (!text.startsWith("---\n") && !text.startsWith("---\r\n")) {
return { frontmatter: {}, body: text }
}
const end = text.indexOf("\n---", 3)
if (end === -1) return { frontmatter: {}, body: text }
const raw = text.slice(text.indexOf("\n") + 1, end + 1)
const body = text.slice(text.indexOf("\n", end + 1) + 1)
const frontmatter: Frontmatter = {}
for (const line of raw.split(/\r?\n/)) {
if (!line || /^\s/.test(line) || line.trim() === "---") continue // nested block or separator
const m = /^([A-Za-z][\w-]*):\s*(.*)$/.exec(line)
if (!m) continue
frontmatter[m[1]] = unquote(m[2].trim())
}
return { frontmatter, body }
}
function unquote(value: string): string {
if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
return value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\")
}
if (value.length >= 2 && value.startsWith("'") && value.endsWith("'")) {
return value.slice(1, -1).replace(/''/g, "'")
}
return value
}
export function isUserInvoked(frontmatter: Frontmatter): boolean {
return frontmatter["disable-model-invocation"] === "true"
}
+10 -2
View File
@@ -10,10 +10,18 @@
//
// Deterministic: same inputs produce byte-identical outputs, so the nightly git diff is the
// affected-set report. Never hand-edit skills/ or the matrix section.
import { cpSync, existsSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs"
import {
cpSync,
existsSync,
readFileSync,
readdirSync,
rmSync,
statSync,
writeFileSync,
} from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { isUserInvoked, parseFrontmatter } from "./frontmatter.ts"
import { isUserInvoked, parseFrontmatter } from "../src/frontmatter.ts"
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")