phase1-skillmd-v2-schema
This commit is contained in:
1 parent
a336ac283d
commit
1e0bd6f7a2
2 files changed
+111
-2
No files matched your search
@@ -1740,3 +1740,112 @@ def _execute_install_app(db: Session, url: str, user_id, app_type: str = "auto")
|
||||
db.commit()
|
||||
|
||||
return f"已成功安装「{_name}」({detected})。你现在可以直接在对话中使用它,或在应用市场查看。"
|
||||
|
||||
|
||||
|
||||
|
||||
# Phase 1: Enhanced SKILL.md parser with 9-block standard
|
||||
SKILLMD_SCHEMA = {
|
||||
"name": "name",
|
||||
"version": "version",
|
||||
"author": "author",
|
||||
"description": "description",
|
||||
"capabilities": "capabilities",
|
||||
"inputs": "inputs",
|
||||
"outputs": "outputs",
|
||||
"permissions": "permissions",
|
||||
"dependencies": "dependencies",
|
||||
"pricing": "pricing",
|
||||
}
|
||||
|
||||
def _parse_skillmd_v2(content: str) -> dict:
|
||||
"""Phase 1: Parse SKILL.md with standardized 9-block schema.
|
||||
|
||||
SKILL.md Standard v2.0 format:
|
||||
---
|
||||
name: Skill Name
|
||||
version: 1.0.0
|
||||
author: Author Name <email>
|
||||
description: |
|
||||
Multi-line description
|
||||
capabilities: [text_generation, code_execution]
|
||||
inputs:
|
||||
- name: input_text
|
||||
type: string
|
||||
description: The input text
|
||||
outputs:
|
||||
- name: result
|
||||
type: string
|
||||
description: The processed result
|
||||
permissions: [file_read, network]
|
||||
dependencies: [python>=3.10, requests]
|
||||
pricing:
|
||||
free_tier: 10/day
|
||||
pro_tier: 100/day
|
||||
---
|
||||
Skill instruction content...
|
||||
"""
|
||||
import re, yaml
|
||||
|
||||
result = {
|
||||
"name": None, "version": "1.0.0", "author": None,
|
||||
"description": None, "capabilities": [], "inputs": [],
|
||||
"outputs": [], "permissions": [], "dependencies": [],
|
||||
"pricing": {}, "instructions": "", "valid": False, "errors": []
|
||||
}
|
||||
|
||||
if not content or not content.strip():
|
||||
result["errors"].append("Empty content")
|
||||
return result
|
||||
|
||||
# Extract YAML frontmatter
|
||||
fm_match = re.match(r'^---\s*\n(.*?)\n---\s*\n?(.*)', content, re.DOTALL)
|
||||
|
||||
if fm_match:
|
||||
try:
|
||||
fm = yaml.safe_load(fm_match.group(1))
|
||||
if isinstance(fm, dict):
|
||||
for key in SKILLMD_SCHEMA:
|
||||
if key in fm:
|
||||
result[key] = fm[key]
|
||||
result["valid"] = True
|
||||
except yaml.YAMLError as e:
|
||||
result["errors"].append(f"YAML parse error: {e}")
|
||||
result["instructions"] = fm_match.group(2).strip()
|
||||
else:
|
||||
# No frontmatter: treat entire content as instructions
|
||||
result["instructions"] = content.strip()
|
||||
result["description"] = content[:200].strip()
|
||||
|
||||
# Validate required fields
|
||||
if not result["name"]:
|
||||
result["errors"].append("Missing required field: name")
|
||||
if not result["description"]:
|
||||
result["errors"].append("Missing recommended field: description")
|
||||
|
||||
result["valid"] = len([e for e in result["errors"] if "Missing required" in e]) == 0
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _validate_skillmd(content: str) -> dict:
|
||||
"""Validate a SKILL.md content against the v2 schema. Returns {valid, errors, warnings}."""
|
||||
parsed = _parse_skillmd_v2(content)
|
||||
errors = list(parsed["errors"])
|
||||
warnings = []
|
||||
|
||||
if not parsed["name"]:
|
||||
errors.append("REQUIRED: 'name' field is missing")
|
||||
if not parsed["description"]:
|
||||
warnings.append("Recommended: add 'description' field")
|
||||
if not parsed["version"]:
|
||||
warnings.append("Recommended: specify 'version' (e.g. 1.0.0)")
|
||||
if not parsed["capabilities"]:
|
||||
warnings.append("Recommended: list 'capabilities' for marketplace visibility")
|
||||
|
||||
return {
|
||||
"valid": len(errors) == 0,
|
||||
"errors": errors,
|
||||
"warnings": warnings,
|
||||
"parsed": parsed
|
||||
}
|
||||
Reference in new issue
Block a user