Files
chaos d10009d639 Initial commit: grok-free-register-oss
Open-source Grok free registration CLI, xai_enroller auth pipeline,
local auth service, tests and docs.
2026-07-16 21:04:05 +08:00

112 lines
3.7 KiB
Python

import argparse
import asyncio
import httpx
from .config import Settings
from .coordinator import EnrollmentCoordinator
from .executors import HTTPProbeExecutor, PlaywrightExecutor
from .protocol import XAIProfile, XAIProtocol
from .sinks import CPAAuthFileSink
from .sources import FileSourceAdapter, SQLiteSourceAdapter
def build_parser():
parser = argparse.ArgumentParser(description="Bounded xAI OAuth Device Flow enroller")
parser.add_argument("--source", choices=("file", "sqlite"))
parser.add_argument("--target", type=int)
parser.add_argument("--concurrency", type=int)
parser.add_argument("--retry-attempts", type=int)
parser.add_argument("--executor", choices=("http", "playwright"))
parser.add_argument("--sink", choices=("cpa",))
return parser
async def main_async(args=None):
parsed = build_parser().parse_args(args)
env = dict()
if parsed.source:
env["XAI_ENROLLER_SOURCE_KIND"] = parsed.source
if parsed.target is not None:
env["XAI_ENROLLER_TARGET"] = str(parsed.target)
if parsed.concurrency is not None:
env["XAI_ENROLLER_CONCURRENCY"] = str(parsed.concurrency)
if parsed.retry_attempts is not None:
env["XAI_ENROLLER_RETRY_ATTEMPTS"] = str(parsed.retry_attempts)
if parsed.executor:
env["XAI_ENROLLER_AUTH_EXECUTOR"] = parsed.executor
if parsed.sink:
env["XAI_ENROLLER_SINK"] = parsed.sink
import os
merged = dict(os.environ)
merged.update(env)
settings = Settings.from_environ(merged)
if settings.source_kind == "remote":
raise ValueError("remote source requires the local auth service entrypoint")
source = (
FileSourceAdapter(settings.source_file)
if settings.source_kind == "file"
else SQLiteSourceAdapter(settings.source_db, settings.source_salt)
)
# CF prewarm (external FlareSolverr) + register-side proxy for httpx/Playwright
try:
from grok_register.clearance import (
format_prewarm_log,
httpx_proxy_mounts,
prewarm_clearance,
)
print(format_prewarm_log(prewarm_clearance()))
proxy_url = httpx_proxy_mounts()
except Exception as exc: # noqa: BLE001
print(f"[clearance] skip: {exc}")
proxy_url = None
client = httpx.AsyncClient(proxy=proxy_url) if proxy_url else httpx.AsyncClient()
protocol = XAIProtocol(
client,
XAIProfile.default(),
default_poll_interval=settings.poll_interval,
)
executor = (
HTTPProbeExecutor(client)
if settings.executor == "http"
else PlaywrightExecutor(settings.concurrency)
)
sink = None
sink_client = None
if settings.sink == "cpa":
sink_client = (
httpx.AsyncClient(proxy=proxy_url) if proxy_url else httpx.AsyncClient()
)
sink = CPAAuthFileSink(settings.cpa_base_url, settings.cpa_management_secret, sink_client)
try:
coordinator = EnrollmentCoordinator(
source=source,
protocol=protocol,
executor=executor,
sink=sink,
ledger_path=settings.ledger_path,
ledger_salt=settings.source_salt,
concurrency=settings.concurrency,
timeout=settings.timeout_sec,
retry_attempts=settings.retry_attempts,
)
results = await coordinator.run(settings.target)
for index, result in enumerate(results, 1):
print(f"job {index}: {result.status.value} ({result.reason_code})")
finally:
await client.aclose()
if sink_client:
await sink_client.aclose()
def main():
asyncio.run(main_async())
if __name__ == "__main__":
main()