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:
@@ -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]:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ----------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user