phase1-skillmd-v2-schema

This commit is contained in:
QihuAI Design committed 2026-07-27 16:55:48 +08:00
1 parent a336ac283d
commit 1e0bd6f7a2
2 files changed
+111 -2

No files matched your search

+109
View File
@@ -1740,3 +1740,112 @@ def _execute_install_app(db: Session, url: str, user_id, app_type: str = "auto")
db.commit() db.commit()
return f"已成功安装「{_name}」({detected})。你现在可以直接在对话中使用它,或在应用市场查看。" 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
}
+2 -2
View File
@@ -48,7 +48,7 @@ services:
- DEFAULT_MODEL=deepseek-ai/DeepSeek-V4-Flash - DEFAULT_MODEL=deepseek-ai/DeepSeek-V4-Flash
- HTTP_PROXY=http://172.18.0.1:7890 - HTTP_PROXY=http://172.18.0.1:7890
- HTTPS_PROXY=http://172.18.0.1:7890 - HTTPS_PROXY=http://172.18.0.1:7890
- NO_PROXY=localhost,127.0.0.1,::1,210.16.161.218,172.17.0.0/16,172.18.0.0/16,172.19.0.0/16,172.20.0.0/16,10.0.0.0/8,192.168.0.0/16,.svc,.local,casdoor,qihu-aiflow-mysql,qihu-aiflow-redis,qihu-aiflow-pgvector,qihu-aiflow-pg18,qihu-aiflow-casdoor,qihuyun.com,ai.qihuyun.com,docs.qihuyun.com,bot.qihuyun.com,siliconflow.cn,api.siliconflow.cn,deepseek.com,api.deepseek.com,volcengineapi.com,aliyun.com,aliyuncs.com,dysmsapi.aliyuncs.com,tencentcloudapi.com,baidubce.com,dashscope.com,qwen.ai,zhipuai.cn,moonshot.cn,minimax.chat,baichuan.com,chatglm.cn,xiaomimimo.com,token-plan-cn.xiaomimimo.com,mi.com,pypi.tuna.tsinghua.edu.cn,feishu.cn,open.feishu.cn,dingtalk.com,open.dingtalk.com,weixin.qq.com,developers.weixin.qq.com,qyapi.weixin.qq.com,ilinkai.weixin.qq.com,tencent.com - NO_PROXY=localhost,127.0.0.1,::1,210.16.161.2,qihu-aiflow-litellm,qihu-aiflow-meilisearch,qihu-aiflow-pg18,qihu-aiflow-redis,qihu-aiflow-casdoor18,172.17.0.0/16,172.18.0.0/16,172.19.0.0/16,172.20.0.0/16,10.0.0.0/8,192.168.0.0/16,.svc,.local,casdoor,qihu-aiflow-mysql,qihu-aiflow-redis,qihu-aiflow-pgvector,qihu-aiflow-pg18,qihu-aiflow-casdoor,qihuyun.com,ai.qihuyun.com,docs.qihuyun.com,bot.qihuyun.com,siliconflow.cn,api.siliconflow.cn,deepseek.com,api.deepseek.com,volcengineapi.com,aliyun.com,aliyuncs.com,dysmsapi.aliyuncs.com,tencentcloudapi.com,baidubce.com,dashscope.com,qwen.ai,zhipuai.cn,moonshot.cn,minimax.chat,baichuan.com,chatglm.cn,xiaomimimo.com,token-plan-cn.xiaomimimo.com,mi.com,pypi.tuna.tsinghua.edu.cn,feishu.cn,open.feishu.cn,dingtalk.com,open.dingtalk.com,weixin.qq.com,developers.weixin.qq.com,qyapi.weixin.qq.com,ilinkai.weixin.qq.com,tencent.com
depends_on: depends_on:
redis: redis:
condition: service_started condition: service_started
@@ -98,7 +98,7 @@ services:
- AGNES_API_KEY=sk-idsplzeccvmbtyqxcrbhaiwmkzwajmicliunkjkouivepaaz - AGNES_API_KEY=sk-idsplzeccvmbtyqxcrbhaiwmkzwajmicliunkjkouivepaaz
- LITELLM_CONFIG=/app/config.yaml - LITELLM_CONFIG=/app/config.yaml
- MIMO_API_KEY=sk-idsplzeccvmbtyqxcrbhaiwmkzwajmicliunkjkouivepaaz - MIMO_API_KEY=sk-idsplzeccvmbtyqxcrbhaiwmkzwajmicliunkjkouivepaaz
- DATABASE_URL=postgresql://aiflow:pwd2026@qihu-aiflow-pg18:5432/aiflow - DATABASE_URL=postgresql://aiflow:pwd2026@qihu-aiflow-pg18:5432/litellm
- LITELLM_MODE=PRODUCTION - LITELLM_MODE=PRODUCTION
restart: unless-stopped restart: unless-stopped
networks: networks: