75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import asyncio
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
|
|
from gibby.account_ops import (
|
|
PermanentAccountFailure,
|
|
handle_failed_account,
|
|
refresh_account_usage,
|
|
window_used_percent,
|
|
)
|
|
from gibby.client import OpenAIClient
|
|
from gibby.models import format_reset_in
|
|
from gibby.settings import Settings
|
|
from gibby.store import JsonStateStore
|
|
|
|
|
|
async def run(data_dir: Path | None = None) -> None:
|
|
settings = Settings()
|
|
if data_dir is not None:
|
|
settings.data_dir = data_dir
|
|
|
|
store = JsonStateStore(settings.accounts_file, settings.failed_file)
|
|
state = store.load()
|
|
if not state.accounts:
|
|
print("No accounts configured.")
|
|
return
|
|
|
|
client = OpenAIClient(settings)
|
|
try:
|
|
for account in list(state.accounts):
|
|
previous_id = account.id
|
|
try:
|
|
usage = await refresh_account_usage(
|
|
account,
|
|
client,
|
|
settings.exhausted_usage_threshold,
|
|
)
|
|
store.update_active_account_id(state, previous_id, account.id)
|
|
print(
|
|
f"token ready for {account.id}, "
|
|
f"primary {window_used_percent(usage.primary_window)}% "
|
|
f"reset in {format_reset_in(usage.primary_window.reset_at if usage.primary_window else None)}, "
|
|
f"secondary {window_used_percent(usage.secondary_window)}% "
|
|
f"reset in {format_reset_in(usage.secondary_window.reset_at if usage.secondary_window else None)}"
|
|
)
|
|
except PermanentAccountFailure as exc:
|
|
account.last_error = str(exc)
|
|
handle_failed_account(store, account)
|
|
store.remove_account(state, account.id)
|
|
print(f"{account.id}: removed={exc}")
|
|
except Exception as exc:
|
|
account.last_error = str(exc)
|
|
print(f"{account.id}: error={exc}")
|
|
store.save(state)
|
|
finally:
|
|
await client.aclose()
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-d", "--data-dir", type=Path)
|
|
args = parser.parse_args()
|
|
try:
|
|
asyncio.run(run(args.data_dir))
|
|
except KeyboardInterrupt:
|
|
print("\nCancelled.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|