"""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()