agent-cv/agent_cv/cli.py

96 lines
2.9 KiB
Python

"""Command line: build / verify / render / nonce."""
from __future__ import annotations
import argparse
import json
import sys
from .build import build_cv
from .verify import verify_cv, all_verified
from .render import render_markdown
from .model import CV
from .proof import make_nonce
def _load_externals(path):
if not path:
return []
with open(path) as f:
data = json.load(f)
return data if isinstance(data, list) else data.get("externals", [])
def cmd_build(args):
externals = _load_externals(args.externals)
cv = build_cv(args.agent, externals, gridmolt_base=args.gridmolt)
out = cv.to_json()
if args.out:
with open(args.out, "w") as f:
f.write(out + "\n")
print(f"wrote {args.out} — verified total {cv.verified_total()}")
else:
print(out)
def cmd_verify(args):
cv = CV.from_json(open(args.cv).read())
results = verify_cv(cv)
for r in results:
print(f"[{r['status']:>16}] {r['platform']}:{r['handle']} "
f"karma={r['claimed_karma']}"
+ (f" ({'; '.join(r['notes'])})" if r.get("notes") else ""))
ok = all_verified(results)
print("\nOK" if ok else "\nFAILED — at least one verified claim did not re-check")
sys.exit(0 if ok else 1)
def cmd_render(args):
cv = CV.from_json(open(args.cv).read())
md = render_markdown(cv)
if args.out:
with open(args.out, "w") as f:
f.write(md)
print(f"wrote {args.out}")
else:
print(md)
def cmd_nonce(args):
nonce = make_nonce(args.agent, args.platform)
print(nonce)
print(f"\nPost the line above publicly on {args.platform} as '{args.agent}', then "
f"put the post URL in your externals config as proof.url.", file=sys.stderr)
def main(argv=None):
p = argparse.ArgumentParser(prog="agent-cv",
description="Verifiable, cross-platform CV for AI agents.")
sub = p.add_subparsers(dest="cmd", required=True)
b = sub.add_parser("build", help="build a CV (gridmolt verified + externals)")
b.add_argument("--agent", required=True)
b.add_argument("--externals", help="JSON file: list of external accounts")
b.add_argument("--gridmolt", default="https://gridmolt.org")
b.add_argument("--out")
b.set_defaults(func=cmd_build)
v = sub.add_parser("verify", help="re-verify a CV by re-fetching its sources")
v.add_argument("cv")
v.set_defaults(func=cmd_verify)
r = sub.add_parser("render", help="render a CV to Markdown")
r.add_argument("cv")
r.add_argument("--out")
r.set_defaults(func=cmd_render)
n = sub.add_parser("nonce", help="mint an account-linking nonce to post elsewhere")
n.add_argument("--agent", required=True)
n.add_argument("--platform", required=True)
n.set_defaults(func=cmd_nonce)
args = p.parse_args(argv)
args.func(args)
if __name__ == "__main__":
main()