"""One-shot Colab training status over the HTTP runtime proxy (no ssh).
python3 scripts/colab_status.py --host <instance.url netloc> --token <instance.token> \\
[--lines 4] [--dir content/swift15/checkpoints/agent_persona_lora_v1]
Reads only `/api/contents`, so it works while the ssh slot is refused; see scripts/pull_colab_http.py
for why that happens. Credentials come from the caller because they must be re-listed from
`colab.instances()` each time -- both the url and the token expire in about an hour -- and the kernel's
plugin is not importable from a subprocess.
"""
import argparse
import json
import sys
import urllib.parse
import urllib.request
def contents(host, token, path, text=False, content=True):
q = urllib.parse.urlencode({
"colab-runtime-proxy-token": token,
**({"format": "text"} if text else {}),
"content": "1" if content else "0",
})
url = f"https://{host}/api/contents/{path.lstrip('/')}?{q}"
req = urllib.request.Request(url, headers={"X-Colab-Client-Agent": "colab-cli"})
with urllib.request.urlopen(req, timeout=40) as r:
return json.loads(r.read())
def main(argv=None):
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("--host", required=True)
ap.add_argument("--token", required=True)
ap.add_argument("--lines", type=int, default=4)
ap.add_argument("--dir", default="content/swift15/checkpoints/agent_persona_lora_v1")
a = ap.parse_args(argv)
log = contents(a.host, a.token, f"{a.dir}/train.log", text=True)
lines = (log.get("content") or "").splitlines()
print(f"train.log {log.get('size', 0):,} B / {len(lines)} lines")
for line in lines[-a.lines:]:
print(" " + line)
for item in sorted((contents(a.host, a.token, a.dir).get("content") or []), key=lambda x: x["name"]):
if item["name"].endswith((".pt", ".bin", ".pid")):
print(f" {item['name']:24s} {item.get('size', 0):>12,} {item['last_modified'][11:19]}")
return 0
if __name__ == "__main__":
sys.exit(main())