Skip to content

Commit c87c9b2

Browse files
committed
fix(skill_manager): improve skill name normalization and validation logic
1 parent 28c366b commit c87c9b2

1 file changed

Lines changed: 21 additions & 9 deletions

File tree

astrbot/core/skills/skill_manager.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
_SKILL_NAME_RE = re.compile(r"^[\w.-]+$")
3131

3232

33+
def _normalize_skill_name(name: str | None) -> str:
34+
raw = str(name or "")
35+
return re.sub(r"\s+", "_", raw.strip())
36+
37+
3338
def _default_sandbox_skill_path(name: str) -> str:
3439
return f"{SANDBOX_WORKSPACE_ROOT}/{SANDBOX_SKILLS_ROOT}/{name}/SKILL.md"
3540

@@ -562,13 +567,17 @@ def install_skill_from_zip(
562567

563568
archive_skill_name = None
564569
if skill_name_hint is not None:
565-
archive_skill_name = skill_name_hint.strip()
566-
if archive_skill_name and not _SKILL_NAME_RE.match(archive_skill_name):
570+
archive_skill_name = _normalize_skill_name(skill_name_hint)
571+
if archive_skill_name and not _SKILL_NAME_RE.fullmatch(
572+
archive_skill_name
573+
):
567574
raise ValueError("Invalid skill name.")
568575

569576
if root_mode:
570-
archive_hint = (archive_skill_name or zip_path_obj.stem).strip()
571-
if not archive_hint or not _SKILL_NAME_RE.match(archive_hint):
577+
archive_hint = _normalize_skill_name(
578+
archive_skill_name or zip_path_obj.stem
579+
)
580+
if not archive_hint or not _SKILL_NAME_RE.fullmatch(archive_hint):
572581
raise ValueError("Invalid skill name.")
573582
skill_name = archive_hint
574583
else:
@@ -580,16 +589,17 @@ def install_skill_from_zip(
580589
"Zip archive must contain a single top-level folder."
581590
)
582591
archive_root_name = next(iter(top_dirs))
583-
if archive_root_name in {".", "..", ""} or not _SKILL_NAME_RE.match(
584-
archive_root_name
592+
archive_root_name_normalized = _normalize_skill_name(archive_root_name)
593+
if archive_root_name in {".", "..", ""} or not _SKILL_NAME_RE.fullmatch(
594+
archive_root_name_normalized
585595
):
586596
raise ValueError("Invalid skill folder name.")
587597
if archive_skill_name:
588-
if not _SKILL_NAME_RE.match(archive_skill_name):
598+
if not _SKILL_NAME_RE.fullmatch(archive_skill_name):
589599
raise ValueError("Invalid skill name.")
590600
skill_name = archive_skill_name
591601
else:
592-
skill_name = archive_root_name
602+
skill_name = archive_root_name_normalized
593603

594604
for name in names:
595605
if not name:
@@ -620,7 +630,9 @@ def install_skill_from_zip(
620630
if not member_name or _is_ignored_zip_entry(member_name):
621631
continue
622632
zf.extract(member, tmp_dir)
623-
src_dir = Path(tmp_dir) if root_mode else Path(tmp_dir) / archive_root_name
633+
src_dir = (
634+
Path(tmp_dir) if root_mode else Path(tmp_dir) / archive_root_name
635+
)
624636
normalized_path = _normalize_skill_markdown_path(src_dir)
625637
if normalized_path is None:
626638
raise ValueError("SKILL.md not found in the skill folder.")

0 commit comments

Comments
 (0)