Add plugin helper with agent skill for updating plugins

This commit is contained in:
pleb
2026-06-14 10:26:22 -07:00
parent a9881ebec4
commit caaa4a6558
23 changed files with 1604 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
from __future__ import annotations
import hashlib
import json
import os
import tempfile
from pathlib import Path
from typing import Any
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def sha256_bytes(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def atomic_write_json(path: Path, data: Any) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
fd, tmp_name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent)
try:
with os.fdopen(fd, "w", encoding="utf-8") as handle:
json.dump(data, handle, indent=2, sort_keys=True)
handle.write("\n")
Path(tmp_name).replace(path)
except Exception:
Path(tmp_name).unlink(missing_ok=True)
raise
def read_json(path: Path, default: Any) -> Any:
if not path.exists():
return default
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
def ensure_relative(path: str) -> Path:
if "\\" in path:
raise ValueError(f"unsafe relative path: {path}")
rel = Path(path)
if rel.is_absolute() or ".." in rel.parts or any(part.endswith(":") for part in rel.parts):
raise ValueError(f"unsafe relative path: {path}")
return rel
def ensure_inside(root: Path, target: Path) -> Path:
root_resolved = root.resolve()
target_resolved = target.resolve(strict=False)
try:
target_resolved.relative_to(root_resolved)
except ValueError as exc:
raise ValueError(f"target escapes instance root: {target}") from exc
return target_resolved