"""Run with the current ARTEMIS Python; no pytest/device/service/config needed.""" import asyncio import hashlib import json from pathlib import Path import sys import tempfile from artemis.plugins.evidence import persist_attachments, validate_tools from artemis.plugins.models import PluginManifest, PluginProfile from artemis.plugins.sdk_checks import run_checks from artemis.plugins.session import PluginSession, resolve_server async def run_contract(): directory = Path(__file__).resolve().parent manifest = PluginManifest.model_validate_json((directory / "plugin.json").read_text("utf-8")) with tempfile.TemporaryDirectory(prefix="artemis-template-contract-") as temporary: trace = Path(temporary).resolve() artifacts = trace / "artifacts" / "plugins" / manifest.id artifacts.mkdir(parents=True) content = "synthetic local sample\n中文\x00".encode() (artifacts / "样例.txt").write_bytes(content) server = resolve_server( manifest, PluginProfile(values={"python": sys.executable}), directory ) server.env["ARTEMIS_ARTIFACTS_DIR"] = str(artifacts) server.env["PYTHONDONTWRITEBYTECODE"] = "1" session = await PluginSession(server, directory).start() try: validate_tools(manifest, session.tools) success = await session.call( "verify_note", {"name": "样例.txt", "sha256": hashlib.sha256(content).hexdigest()} ) if success.isError: raise AssertionError("MCP 校验入口失败") receipt = success.structuredContent["artemis"] attachments = persist_attachments(trace, manifest.id, receipt["attachments"]) if len(attachments) != 1: raise AssertionError("宿主未回读到校验回执") for name, digest in (("样例.txt", "0" * 64), ("../outside.txt", "0" * 64)): denied = await session.call("verify_note", {"name": name, "sha256": digest}) if ( not denied.isError or denied.structuredContent["artemis"]["execution"] != "not_started" ): raise AssertionError("无效输入没有在工具启动前拒绝") finally: await session.aclose() return { "status": "passed", "scope": "template_offline_contract", "mcp_calls": 3, "host_attachments_verified": 1, "real_device_actions": False, } async def main(): print( json.dumps( {"sdk": await run_checks(), "template": await run_contract()}, ensure_ascii=False ) ) if __name__ == "__main__": asyncio.run(main())