fix: parse multiline frontmatter description in SKILL.md (#6460)

* fix(skills): support multiline frontmatter descriptions

* fix(skills): 修复多行 frontmatter 描述解析

* style(skills): clean up frontmatter parser follow-ups

---------

Co-authored-by: RhoninSeiei <RhoninSeiei@users.noreply.github.com>
This commit is contained in:
Rhonin Wang
2026-03-17 13:53:16 +08:00
committed by GitHub
parent acbc5150cf
commit d5b98b353c
3 changed files with 66 additions and 14 deletions
+18 -7
View File
@@ -213,13 +213,24 @@ def parse_description(text: str) -> str:
break
if end_idx is None:
return ""
for line in lines[1:end_idx]:
if ":" not in line:
continue
key, value = line.split(":", 1)
if key.strip().lower() == "description":
return value.strip().strip('"').strip("'")
return ""
frontmatter = "\n".join(lines[1:end_idx])
try:
import yaml
except ImportError:
return ""
try:
payload = yaml.safe_load(frontmatter) or dict()
except yaml.YAMLError:
return ""
if not isinstance(payload, dict):
return ""
description = payload.get("description", "")
if not isinstance(description, str):
return ""
return description.strip()
def load_managed_skills() -> list[str]:
+15 -7
View File
@@ -11,6 +11,8 @@ from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path, PurePosixPath
import yaml
from astrbot.core.utils.astrbot_path import (
get_astrbot_data_path,
get_astrbot_skills_path,
@@ -69,13 +71,19 @@ def _parse_frontmatter_description(text: str) -> str:
break
if end_idx is None:
return ""
for line in lines[1:end_idx]:
if ":" not in line:
continue
key, value = line.split(":", 1)
if key.strip().lower() == "description":
return value.strip().strip('"').strip("'")
return ""
frontmatter = "\n".join(lines[1:end_idx])
try:
payload = yaml.safe_load(frontmatter) or {}
except yaml.YAMLError:
return ""
if not isinstance(payload, dict):
return ""
description = payload.get("description", "")
if not isinstance(description, str):
return ""
return description.strip()
# Regex for sanitizing paths used in prompt examples — only allow
+33
View File
@@ -49,6 +49,39 @@ def test_parse_frontmatter_quoted_description():
assert _parse_frontmatter_description(text) == "quoted value"
def test_parse_frontmatter_multiline_literal_description():
text = (
"---\n"
"name: humanizer-zh\n"
"description: |\n"
" 去除文本中的 AI 生成痕迹。\n"
" 适用于编辑或审阅文本,使其听起来更自然。\n"
"---\n"
)
assert _parse_frontmatter_description(text) == (
"去除文本中的 AI 生成痕迹。\n适用于编辑或审阅文本,使其听起来更自然。"
)
def test_parse_frontmatter_multiline_folded_description():
text = (
"---\n"
"name: humanizer-zh\n"
"description: >\n"
" 去除文本中的 AI 生成痕迹。\n"
" 适用于编辑或审阅文本,使其听起来更自然。\n"
"---\n"
)
assert _parse_frontmatter_description(text) == (
"去除文本中的 AI 生成痕迹。 适用于编辑或审阅文本,使其听起来更自然。"
)
def test_parse_frontmatter_invalid_yaml_returns_empty():
text = "---\ndescription: [broken\n---\n"
assert _parse_frontmatter_description(text) == ""
# ---------- build_skills_prompt tests ----------