48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
"""Validate a plugin package; --live checks MCP declarations without executing actions."""
|
|
|
|
import argparse
|
|
import asyncio
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from artemis.plugins.evidence import validate_tools
|
|
from artemis.plugins.models import PluginManifest, PluginProfile
|
|
from artemis.plugins.session import PluginSession, resolve_server
|
|
from artemis.plugins.store import contained_path
|
|
|
|
|
|
async def check(directory: Path, live: bool, values: dict[str, str]) -> None:
|
|
manifest = PluginManifest.model_validate_json((directory / "plugin.json").read_text("utf-8"))
|
|
manifest.check_compatible()
|
|
if manifest.skill:
|
|
skill = contained_path(directory, manifest.skill)
|
|
if not skill.is_file() or not skill.read_text("utf-8").strip():
|
|
raise ValueError("缺少有效的 Skill")
|
|
if manifest.schema_version != 2:
|
|
raise ValueError("新市场插件必须适配 schema_version=2")
|
|
if live and manifest.server:
|
|
server = resolve_server(manifest, PluginProfile(values=values), directory)
|
|
session = await PluginSession(server, directory).start()
|
|
try:
|
|
validate_tools(manifest, session.tools)
|
|
finally:
|
|
await session.aclose()
|
|
print(
|
|
f"PASS {manifest.id} {manifest.version}: 清单/兼容性/Skill"
|
|
+ ("/MCP 工具声明" if live else "")
|
|
)
|
|
print("此检查不代替实际执行、超时取消、证据导出和视觉能力验收。")
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("directory", type=Path)
|
|
parser.add_argument("--live", action="store_true")
|
|
parser.add_argument("--values", default="{}", help="普通配置 JSON;不得包含密钥")
|
|
args = parser.parse_args()
|
|
asyncio.run(check(args.directory.resolve(), args.live, json.loads(args.values)))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|