From d60106042cc674590d2e51126534951c00dbe106 Mon Sep 17 00:00:00 2001 From: Jiaoyc224 <3150610635@qq.com> Date: Sun, 16 Aug 2026 23:32:12 +0800 Subject: [PATCH] fix: escape backslash in frontmatter regex --- lib/index.js | 154 +++++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/lib/index.js b/lib/index.js index 6f5230c..75620bc 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,77 +1,77 @@ -/** - * github-explore dsh bundle entry. - * - * A small Cordis plugin that reads this package's skill (Agent Plugins - * layout: skills/github-explore/SKILL.md) and registers it with ctx.skills, - * so the skill shows up in the agent's catalog when the package is installed - * as a dsh profile bundle: - * - * dsh plugin --profile web add - * - * The skill body's relative references (scripts/, references/) resolve - * against the skill directory (skills/github-explore/) via resourceBase. - */ -import { readFileSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; - -export const name = 'github-explore-skill'; -export const inject = ['skills']; - -/** Skill directory (Agent Plugins layout: skills//). */ -const SKILL_DIR = new URL('../skills/github-explore/', import.meta.url); -const SKILL_FILE = new URL('SKILL.md', SKILL_DIR); - -/** Minimal YAML-frontmatter parser for name/description/whenToUse. */ -function parseFrontmatter(text) { - const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/); - if (!match) return null; - const fm = match[1]; - const get = (key) => { - const line = fm.match(new RegExp('^' + key + ':\s*(.+)$', 'm')); - if (!line) return undefined; - let value = line[1].trim(); - const quoted = (value.startsWith('"') && value.endsWith('"')) - || (value.startsWith("'") && value.endsWith("'")); - if (quoted) value = value.slice(1, -1); - return value; - }; - return { - name: get('name'), - description: get('description'), - whenToUse: get('whenToUse'), - }; -} - -export function apply(ctx) { - let raw; - try { - raw = readFileSync(SKILL_FILE, 'utf-8'); - } catch (error) { - ctx.logger.error('github-explore: cannot read SKILL.md: %s', error.message); - return; - } - const meta = parseFrontmatter(raw); - if (!meta || !meta.name || !meta.description) { - ctx.logger.error( - 'github-explore: SKILL.md frontmatter missing name/description; skill not registered', - ); - return; - } - const content = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trimStart(); - const skill = { - name: meta.name, - description: meta.description, - ...(meta.whenToUse ? { whenToUse: meta.whenToUse } : {}), - content, - source: 'runtime', - resourceBase: { - kind: 'directory', - path: fileURLToPath(SKILL_DIR), - }, - }; - const disposer = ctx.skills.register(skill); - ctx.logger.info('github-explore: registered skill "%s"', skill.name); - ctx.on('dispose', () => { - if (typeof disposer === 'function') disposer(); - }); -} +/** + * github-explore dsh bundle entry. + * + * A small Cordis plugin that reads this package's skill (Agent Plugins + * layout: skills/github-explore/SKILL.md) and registers it with ctx.skills, + * so the skill shows up in the agent's catalog when the package is installed + * as a dsh profile bundle: + * + * dsh plugin --profile web add + * + * The skill body's relative references (scripts/, references/) resolve + * against the skill directory (skills/github-explore/) via resourceBase. + */ +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +export const name = 'github-explore-skill'; +export const inject = ['skills']; + +/** Skill directory (Agent Plugins layout: skills//). */ +const SKILL_DIR = new URL('../skills/github-explore/', import.meta.url); +const SKILL_FILE = new URL('SKILL.md', SKILL_DIR); + +/** Minimal YAML-frontmatter parser for name/description/whenToUse. */ +function parseFrontmatter(text) { + const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/); + if (!match) return null; + const fm = match[1]; + const get = (key) => { + const line = fm.match(new RegExp('^' + key + ':\\s*(.+)$', 'm')); + if (!line) return undefined; + let value = line[1].trim(); + const quoted = (value.startsWith('"') && value.endsWith('"')) + || (value.startsWith("'") && value.endsWith("'")); + if (quoted) value = value.slice(1, -1); + return value; + }; + return { + name: get('name'), + description: get('description'), + whenToUse: get('whenToUse'), + }; +} + +export function apply(ctx) { + let raw; + try { + raw = readFileSync(SKILL_FILE, 'utf-8'); + } catch (error) { + ctx.logger.error('github-explore: cannot read SKILL.md: %s', error.message); + return; + } + const meta = parseFrontmatter(raw); + if (!meta || !meta.name || !meta.description) { + ctx.logger.error( + 'github-explore: SKILL.md frontmatter missing name/description; skill not registered', + ); + return; + } + const content = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trimStart(); + const skill = { + name: meta.name, + description: meta.description, + ...(meta.whenToUse ? { whenToUse: meta.whenToUse } : {}), + content, + source: 'runtime', + resourceBase: { + kind: 'directory', + path: fileURLToPath(SKILL_DIR), + }, + }; + const disposer = ctx.skills.register(skill); + ctx.logger.info('github-explore: registered skill "%s"', skill.name); + ctx.on('dispose', () => { + if (typeof disposer === 'function') disposer(); + }); +}