mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-19 18:47:41 +08:00
This commit adds the _internal package structure for AstrBot's standardized MCP & Skills support: astrbot/_internal/mcp/: - MCPClient for MCP server connections - MCPTool wrapper for MCP tools - MCP configuration management astrbot/_internal/skills/: - SkillManager for skill lifecycle - Skill parser and loader - SkillToToolConverter for tool-based skills - Prompt builder for skills astrbot/_internal/tools/: - ToolSchema, FunctionTool, ToolSet base definitions - FunctionToolManager for tool registry - Builtin tools (cron, send_message, kb_query) - Tool providers (internal, plugin, computer) astrbot/api/: - Public API for tools (ToolRegistry, tool decorator) - Public API for MCP (get_mcp_servers, register_mcp_server) - Public API for skills (get_skill_manager, skill_to_tool)
82 lines
1.9 KiB
Python
82 lines
1.9 KiB
Python
"""SKILL.md parser for extracting frontmatter and content."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
|
|
def parse_frontmatter(text: str) -> dict:
|
|
"""Extract metadata from YAML frontmatter.
|
|
|
|
Expects the standard SKILL.md format used by OpenAI Codex CLI and
|
|
Anthropic Claude Skills::
|
|
|
|
---
|
|
name: my-skill
|
|
description: What this skill does and when to use it.
|
|
input_schema: ...
|
|
output_schema: ...
|
|
---
|
|
"""
|
|
if not text.startswith("---"):
|
|
return {}
|
|
lines = text.splitlines()
|
|
if not lines or lines[0].strip() != "---":
|
|
return {}
|
|
end_idx = None
|
|
for i in range(1, len(lines)):
|
|
if lines[i].strip() == "---":
|
|
end_idx = i
|
|
break
|
|
if end_idx is None:
|
|
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 {}
|
|
|
|
return payload
|
|
|
|
|
|
def parse_skill_markdown(path: Path) -> dict:
|
|
"""Parse a SKILL.md file and return frontmatter + content.
|
|
|
|
Args:
|
|
path: Path to the SKILL.md file
|
|
|
|
Returns:
|
|
dict with keys: frontmatter (dict), content (str)
|
|
"""
|
|
try:
|
|
text = path.read_text(encoding="utf-8")
|
|
except Exception:
|
|
return {"frontmatter": {}, "content": ""}
|
|
|
|
frontmatter = parse_frontmatter(text)
|
|
|
|
# Extract content after frontmatter
|
|
if text.startswith("---"):
|
|
lines = text.splitlines()
|
|
end_idx = None
|
|
for i in range(1, len(lines)):
|
|
if lines[i].strip() == "---":
|
|
end_idx = i
|
|
break
|
|
if end_idx is not None:
|
|
content = "\n".join(lines[end_idx + 1 :]).strip()
|
|
else:
|
|
content = ""
|
|
else:
|
|
content = text
|
|
|
|
return {
|
|
"frontmatter": frontmatter,
|
|
"content": content,
|
|
}
|