feat(plugins): add managed runtime SDK and release 2.4.5
This commit is contained in:
1 parent
506e3bf1c5
commit
2a3bbaa3fb
45 files changed
+3348
-98
No files matched your search
@@ -0,0 +1,69 @@
|
||||
"""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())
|
||||
Reference in new issue
Block a user