Files
Artemis-Plugins/scripts/build_cua_driver.py
T
chenmingxuan b780a60e8d feat(cua): release 0.38.0+artemis.1 with verified shell observation
Upgrade the pinned driver, validate menu and taskbar focus ownership, patch untitled Shell resolution, and remove duplicate scroll scaling. Publish package provenance, verification boundaries and matching marketplace checksum. Go tests, vet, build and byte-level package verification passed.
2026-10-27 01:13:43 +08:00

177 lines
6.6 KiB
Python

"""Build a self-contained Windows plugin from a hash-pinned Cua release."""
import argparse
import hashlib
import json
import os
import re
import subprocess
import urllib.request
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "plugins/cua-driver"
UPSTREAM_VERSION = "0.38.0"
COMMIT = "85e2b1318bd77ccf3cfa88ccdf875a4bb7eaed19"
DIGEST = "5edaa74d0afa1b55a9668dbc4f32736507bd2bd4d75b18ca1dc8881bb12402b5"
URL = "https://github.com/trycua/cua/releases/download/cua-driver-rs-v0.38.0/cua-driver-rs-0.38.0-windows-x86_64-binary.zip"
PATCH = SOURCE / "patches/cua-driver-0.38.0-untitled-shell.patch"
PATCHED_PATH = "libs/cua-driver/rust/crates/platform-windows/src/win32/windows.rs"
def build_patched_runtime(source: Path, cargo: str) -> dict:
source = source.resolve()
head = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=source, text=True).strip()
if head != COMMIT:
raise ValueError("Patched Cua source must use the pinned upstream commit")
changes = subprocess.check_output(["git", "diff", "--name-only", "HEAD"], cwd=source, text=True)
if changes.splitlines() != [PATCHED_PATH]:
raise ValueError("Cua source may contain only the reviewed untitled-shell patch")
diff = subprocess.check_output(
["git", "diff", "--binary", "HEAD", "--", PATCHED_PATH], cwd=source
)
if diff.replace(b"\r\n", b"\n") != PATCH.read_bytes().replace(b"\r\n", b"\n"):
raise ValueError("Cua source does not match the packaged compatibility patch")
project = source / "libs/cua-driver/rust"
command = [
cargo,
"build",
"--release",
"--locked",
"-p",
"cua-driver",
"-p",
"cua-driver-uia",
"-p",
"cua-driver-sdk",
]
subprocess.run(command, cwd=project, check=True, timeout=1800)
binaries = {
name: project / "target/release" / name
for name in ("cua-driver.exe", "cua-driver-uia.exe", "cua_driver_sdk.dll")
}
if not all(path.is_file() for path in binaries.values()):
raise ValueError("Patched Cua runtime build is incomplete")
return binaries
def main():
parser = argparse.ArgumentParser(__doc__)
parser.add_argument("upstream_zip", type=Path)
parser.add_argument("--go", default="go")
parser.add_argument("--cargo", default="cargo")
parser.add_argument("--upstream-source", type=Path, required=True)
parser.add_argument("--output", type=Path, default=ROOT / "artifacts")
args = parser.parse_args()
version = json.loads((SOURCE / "plugin.json").read_text("utf-8"))["version"]
if version.split("+", 1)[0] != UPSTREAM_VERSION:
raise ValueError("Plugin version must match the pinned Cua Driver version")
match = re.search(r'const adapterVersion = "([^"]+)"', (SOURCE / "main.go").read_text("utf-8"))
if not match or match[1] != version:
raise ValueError("Adapter MCP version must match plugin.json")
if hashlib.sha256(args.upstream_zip.read_bytes()).hexdigest() != DIGEST:
raise ValueError("Cua release archive hash mismatch")
patched_runtime = build_patched_runtime(args.upstream_source, args.cargo)
output = args.output.resolve()
output.mkdir(parents=True, exist_ok=True)
adapter = output / "artemis-cua-adapter.exe"
env = {
**os.environ,
"CGO_ENABLED": "0",
"GOOS": "windows",
"GOARCH": "amd64",
"GOTOOLCHAIN": "local",
}
for command in (
[args.go, "test", "./..."],
[
args.go,
"build",
"-trimpath",
"-buildvcs=false",
"-ldflags=-s -w",
"-o",
str(adapter),
".",
],
):
subprocess.run(command, cwd=SOURCE, env=env, check=True, timeout=180)
license_file = SOURCE / "LICENSE.upstream"
if not license_file.exists():
with urllib.request.urlopen(
f"https://raw.githubusercontent.com/trycua/cua/{COMMIT}/LICENSE.md",
timeout=30,
) as response:
license_file.write_bytes(response.read())
target = output / f"cua-driver-{version}-windows-amd64.zip"
with (
zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED) as dest,
zipfile.ZipFile(args.upstream_zip) as upstream,
):
for name in (
"plugin.json",
"SKILL.md",
"LICENSE.upstream",
"RELEASE.md",
"VERIFICATION.md",
"BUILD.md",
):
dest.write(SOURCE / name, name)
for source in sorted(SOURCE.glob("*.go")):
dest.write(source, f"source/{source.name}")
for name in ("go.mod", "tools.json"):
dest.write(SOURCE / name, f"source/{name}")
dest.write(PATCH, f"source/patches/{PATCH.name}")
dest.write(adapter, "bin/artemis-cua-adapter.exe")
for name in upstream.namelist():
# Only the release's executable runtime; no global installer/hooks.
if Path(name).name in {
"cua-driver.exe",
"cua-driver-uia.exe",
"cua-cursor-theme.exe",
"cua_driver_sdk.dll",
}:
basename = Path(name).name
if basename not in patched_runtime:
dest.writestr(f"bin/{basename}", upstream.read(name))
for name, binary in patched_runtime.items():
dest.write(binary, f"bin/{name}")
dest.writestr(
"provenance.json",
json.dumps(
{
"source_commit": COMMIT,
"upstream_version": UPSTREAM_VERSION,
"plugin_version": version,
"adapter_revision": int(version.rsplit(".", 1)[1]),
"prerelease": True,
"upstream_release_channel": "stable",
"url": URL,
"sha256": DIGEST,
"compatibility_patch": {
"file": f"source/patches/{PATCH.name}",
"sha256": hashlib.sha256(PATCH.read_bytes()).hexdigest(),
"rebuilt_binaries": {
name: hashlib.sha256(binary.read_bytes()).hexdigest()
for name, binary in patched_runtime.items()
},
"cargo_locked": True,
},
},
indent=2,
),
)
print(
json.dumps(
{
"archive": str(target),
"sha256": hashlib.sha256(target.read_bytes()).hexdigest(),
}
)
)
if __name__ == "__main__":
main()