clone

push a directory of html from the terminal and get a four-character url back. a deno cli on cloudflare

codex/agent-interface
nzip / agent / hermes / tools.py
tools.py 4.1K
1"""CLI-backed implementations for the shared nzip tool contract."""23import json4import subprocess5import tempfile6from pathlib import Path78ROOT = Path(__file__).resolve().parent9if not (ROOT / "tools.json").exists():10 ROOT = ROOT.parent111213def definitions():14 return json.loads((ROOT / "tools.json").read_text())151617def _string(args, name, required=False):18 value = args.get(name)19 if value is None:20 if required:21 raise ValueError(f"{name} is required")22 return None23 if not isinstance(value, str) or not value.strip():24 raise ValueError(f"{name} must be a non-empty string")25 return value262728def _ttl(args):29 value = _string(args, "ttl")30 if value and value != "forever" and value != "0":31 if not (value.rstrip("d").isdigit() and value.count("d") <= 1):32 raise ValueError("ttl must be a number of days or forever")33 return value343536def _run(command):37 result = subprocess.run(["nzip", *command, "--json"], capture_output=True, text=True, check=False)38 body = (result.stdout or result.stderr).strip()39 try:40 parsed = json.loads(body)41 except json.JSONDecodeError as error:42 raise RuntimeError(body or f"nzip exited with status {result.returncode}") from error43 if result.returncode or parsed.get("ok") is False:44 raise RuntimeError(parsed.get("error", "nzip command failed"))45 return parsed464748def _host_html(args):49 html = _string(args, "html", required=True)50 target, ttl, password = _string(args, "target"), _ttl(args), _string(args, "password")51 with tempfile.TemporaryDirectory(prefix="nzip-agent-") as directory:52 page = Path(directory) / "index.html"53 page.write_text(html)54 command = ["push", str(page)]55 if target:56 command.append(target)57 if ttl:58 command.extend(["--ttl", ttl])59 hosted = _run(command)60 return _run(["share", hosted["address"], "--password", password]) if password else hosted616263def invoke(name, args):64 if not isinstance(args, dict):65 raise ValueError("arguments must be an object")66 if name == "status":67 return _run(["status"])68 if name == "list_vaults":69 return _run(["vault", "ls"])70 if name == "list_sites":71 vault = _string(args, "vault")72 return _run(["ls", vault] if vault else ["ls"])73 if name == "inspect_site":74 return _run(["share", _string(args, "target", required=True)])75 if name == "host_html":76 return _host_html(args)77 if name == "configure_site":78 target, ttl, password = _string(args, "target", required=True), _ttl(args), args.get("password")79 if not ttl and password is None and "password" not in args:80 raise ValueError("configure_site requires ttl or password")81 command = ["share", target]82 if ttl:83 command.extend(["--ttl", ttl])84 if password is None and "password" in args:85 command.append("--no-password")86 elif isinstance(password, str) and password:87 command.extend(["--password", password])88 elif password is not None:89 raise ValueError("password must be a string or null")90 return _run(command)91 if name == "download_site":92 command = ["download", _string(args, "target", required=True)]93 directory = _string(args, "directory")94 if directory:95 command.append(directory)96 if args.get("overwrite") is True:97 command.append("--overwrite")98 return _run(command)99 if name == "restore_site":100 command = ["revert", _string(args, "target", required=True)]101 if "to" in args:102 if not isinstance(args["to"], int) or args["to"] < 1:103 raise ValueError("to must be a positive integer")104 command.extend(["--to", str(args["to"])])105 return _run(command)106 if name == "delete_site":107 if args.get("confirm") is not True:108 raise ValueError("delete_site requires confirm: true")109 return _run(["rm", _string(args, "target", required=True), "--yes"])110 raise ValueError(f"unknown nzip tool: {name}")