|
|
|
|
@@ -5,6 +5,7 @@ No vendor requests or real credentials are used. The token URL alone is redirect
|
|
|
|
|
the production parser, command, pool refresh, HTTP client, and persistence execute.
|
|
|
|
|
"""
|
|
|
|
|
import argparse
|
|
|
|
|
import base64
|
|
|
|
|
import json
|
|
|
|
|
import os
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
@@ -32,8 +33,10 @@ def main():
|
|
|
|
|
def do_POST(self):
|
|
|
|
|
payload = parse_qs(self.rfile.read(int(self.headers["Content-Length"])).decode())
|
|
|
|
|
requests.append({"grant_type": payload.get("grant_type"),
|
|
|
|
|
"target_grant": payload.get("refresh_token") == ["fixture-refresh-1"]})
|
|
|
|
|
body = ({"access_token": "fixture-new-access", "refresh_token": "fixture-new-refresh"}
|
|
|
|
|
"target_grant": (payload.get("refresh_token") == ["fixture-refresh-1"]
|
|
|
|
|
or self.headers.get("x-nous-refresh-token") == "fixture-refresh-1")})
|
|
|
|
|
body = ({"access_token": nous_new_token if self.path == "/api/oauth/token" else "fixture-new-access",
|
|
|
|
|
"refresh_token": "fixture-new-refresh", "expires_in": 3600, "scope": "inference:invoke"}
|
|
|
|
|
if response_status == 200 else {"error": "invalid_grant" if response_status == 401 else "unavailable"})
|
|
|
|
|
self.send_response(response_status)
|
|
|
|
|
self.send_header("Content-Type", "application/json")
|
|
|
|
|
@@ -43,6 +46,12 @@ def main():
|
|
|
|
|
def log_message(self, format, *values):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def token(subject):
|
|
|
|
|
encode = lambda value: base64.urlsafe_b64encode(json.dumps(value).encode()).decode().rstrip("=")
|
|
|
|
|
return encode({"alg": "none"}) + "." + encode({"sub": subject, "exp": int(time.time()) + 3600,
|
|
|
|
|
"scope": "inference:invoke"}) + ".fixture"
|
|
|
|
|
|
|
|
|
|
nous_new_token = token("singleton-renewed")
|
|
|
|
|
server = ThreadingHTTPServer(("127.0.0.1", 0), Endpoint)
|
|
|
|
|
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
|
|
|
|
thread.start()
|
|
|
|
|
@@ -59,6 +68,8 @@ def main():
|
|
|
|
|
*[(f"refresh-{status}", "openai-codex", ["refresh", "openai-codex", "row1"], status)
|
|
|
|
|
for status in (200, 503, 401)],
|
|
|
|
|
]
|
|
|
|
|
cases.extend((name, "nous", ["refresh", "nous", target], None) for name, target in
|
|
|
|
|
(("nous-independent", "row0"), ("nous-singleton", "row1")))
|
|
|
|
|
results = []
|
|
|
|
|
try:
|
|
|
|
|
for name, provider, command, status in cases:
|
|
|
|
|
@@ -73,12 +84,24 @@ def main():
|
|
|
|
|
access_token=f"fixture-access-{i}", refresh_token=f"fixture-refresh-{i}",
|
|
|
|
|
priority=i, last_status="exhausted", last_status_at=now,
|
|
|
|
|
last_error_code=429, last_error_reset_at=now+3600) for i in range(2)]
|
|
|
|
|
providers = {}
|
|
|
|
|
if provider == "nous":
|
|
|
|
|
for row in rows:
|
|
|
|
|
row.update(auth_type="oauth", source="manual:device_code")
|
|
|
|
|
state = dict(access_token=token("singleton"), refresh_token="fixture-refresh-1",
|
|
|
|
|
expires_at=now+3600, portal_base_url=f"http://127.0.0.1:{server.server_port}",
|
|
|
|
|
scope="inference:invoke", inference_base_url="https://inference-api.nousresearch.com/v1")
|
|
|
|
|
rows[1].update(source="device_code", **state)
|
|
|
|
|
providers["nous"] = state
|
|
|
|
|
store = home / "auth.json"
|
|
|
|
|
store.write_text(json.dumps({"version": 1, "providers": {}, "credential_pool": {provider: rows}}), encoding="utf-8")
|
|
|
|
|
store.write_text(json.dumps({"version": 1, "providers": providers, "active_provider": provider, "credential_pool": {provider: rows}}), encoding="utf-8")
|
|
|
|
|
env = {k: v for k, v in os.environ.items() if not any(t in k for t in
|
|
|
|
|
("TOKEN", "API_KEY", "SECRET", "PASSWORD", "HERMES", "PYTEST"))}
|
|
|
|
|
env.update(HOME=temp, HERMES_HOME=temp, PYTHONPATH=str(Path(args.repo).absolute()), TERM="xterm")
|
|
|
|
|
bootstrap = ("import sys; from hermes_cli import auth_codex; "
|
|
|
|
|
env.update(HOME=temp, HERMES_HOME=temp, HERMES_SHARED_AUTH_DIR=str(home / "shared"), PYTHONPATH=str(Path(args.repo).absolute()), TERM="xterm")
|
|
|
|
|
bootstrap = ("import sys, httpx; original_send=httpx.Client.send; "
|
|
|
|
|
"httpx.Client.send=lambda self, request, **kw: original_send(self, request, **kw) "
|
|
|
|
|
"if request.url.host == '127.0.0.1' else (_ for _ in ()).throw(AssertionError('NONLOCAL_NETWORK')); "
|
|
|
|
|
"from hermes_cli import auth_codex; "
|
|
|
|
|
f"auth_codex.CODEX_OAUTH_TOKEN_URL='http://127.0.0.1:{server.server_port}/token'; "
|
|
|
|
|
"from hermes_cli.main import main; "
|
|
|
|
|
f"sys.argv=['hermes','auth',*{command!r}]; main()")
|
|
|
|
|
@@ -102,16 +125,26 @@ def main():
|
|
|
|
|
exit_code = child.wait(timeout=30)
|
|
|
|
|
disk = json.loads(store.read_text(encoding="utf-8"))["credential_pool"][provider]
|
|
|
|
|
results.append({"case": name, "exit": exit_code, "output": output,
|
|
|
|
|
"wire": list(requests), "secrets_printed": "fixture-" in output,
|
|
|
|
|
"wire": list(requests), "secrets_printed": "fixture-" in output or ".fixture" in output,
|
|
|
|
|
"disk": [{k: e.get(k) for k in ("id", "priority", "last_status", "last_error_reset_at", "request_count")}
|
|
|
|
|
for e in disk],
|
|
|
|
|
"target_rotated": any(e["id"] == "row1" and e.get("access_token") == "fixture-new-access" for e in disk),
|
|
|
|
|
"target_refresh_rotated": any(e["id"] == "row1" and e.get("refresh_token") == "fixture-new-refresh" for e in disk),
|
|
|
|
|
"target_rotated": any(e["id"] == "row1" and e.get("access_token") == (nous_new_token if provider == "nous" else "fixture-new-access") for e in disk),
|
|
|
|
|
"independent_tokens_preserved": all(next(e for e in disk if e["id"] == "row0").get(k) == rows[0].get(k) for k in ("access_token", "refresh_token")),
|
|
|
|
|
"sibling_cooldown_preserved": next(e for e in disk if e["id"] == "row0").get("last_error_reset_at") == now+3600})
|
|
|
|
|
finally:
|
|
|
|
|
server.shutdown()
|
|
|
|
|
thread.join(timeout=5)
|
|
|
|
|
server.server_close()
|
|
|
|
|
Path(args.output).write_text(json.dumps({"repo": args.repo, "cases": results}, indent=2), encoding="utf-8")
|
|
|
|
|
independent = next(r for r in results if r["case"] == "nous-independent")
|
|
|
|
|
assert independent["exit"] != 0 and not independent["wire"], independent
|
|
|
|
|
assert independent["independent_tokens_preserved"] and independent["sibling_cooldown_preserved"], independent
|
|
|
|
|
singleton = next(r for r in results if r["case"] == "nous-singleton")
|
|
|
|
|
assert singleton["exit"] == 0 and singleton["target_rotated"] and singleton["target_refresh_rotated"], singleton
|
|
|
|
|
assert len(singleton["wire"]) == 1 and singleton["wire"][0]["target_grant"], singleton
|
|
|
|
|
assert singleton["sibling_cooldown_preserved"] and singleton["independent_tokens_preserved"], singleton
|
|
|
|
|
assert all(not r["secrets_printed"] and "NONLOCAL_NETWORK" not in r["output"] for r in results)
|
|
|
|
|
print(json.dumps([{"case": r["case"], "exit": r["exit"], "posts": len(r["wire"]),
|
|
|
|
|
"target_rotated": r["target_rotated"], "secrets_printed": r["secrets_printed"]} for r in results], indent=2))
|
|
|
|
|
|
|
|
|
|
|