gemini-web2api / run.py
RYUK999's picture
fix: make workdir writable for config/cookie generation at runtime
a7fbd75
Raw
History Blame Contribute Delete
3.68 kB
#!/usr/bin/env python3
"""
Hugging Face Space launcher for gemini-web2api.
Builds a runtime config.json from the committed config.example.json, applying
overrides from Space Secrets / environment variables, then starts the server.
Supported environment variables (all optional):
PORT port to listen on (default 7860)
HOST bind address (default 0.0.0.0)
COOKIE raw Gemini cookie string (plain "k=v; k=v" or JSON)
-> written to cookie.txt and wired into config
API_KEY single API key for Bearer auth (default sk-gemini)
API_KEYS comma-separated list of API keys (overrides API_KEY)
DEFAULT_MODEL default model name
GEMINI_BL Gemini backend version string
PROXY HTTP/HTTPS proxy for outbound calls
"""
import json
import os
import sys
APP_DIR = os.path.dirname(os.path.abspath(__file__))
def main():
# 1. base config from the committed example
base_path = os.path.join(APP_DIR, "config.example.json")
with open(base_path) as f:
cfg = json.load(f)
# 2. apply env overrides
cfg["port"] = int(os.environ.get("PORT", cfg.get("port", 7860)))
cfg["host"] = os.environ.get("HOST", cfg.get("host", "0.0.0.0"))
if os.environ.get("DEFAULT_MODEL"):
cfg["default_model"] = os.environ["DEFAULT_MODEL"]
if os.environ.get("GEMINI_BL"):
cfg["gemini_bl"] = os.environ["GEMINI_BL"]
if os.environ.get("PROXY"):
cfg["proxy"] = os.environ["PROXY"]
# 3. API keys (Bearer auth). Empty list => no auth required.
if os.environ.get("API_KEYS", "").strip():
cfg["api_keys"] = [k.strip() for k in os.environ["API_KEYS"].split(",") if k.strip()]
elif os.environ.get("API_KEY", "").strip():
cfg["api_keys"] = [os.environ["API_KEY"].strip()]
else:
cfg.setdefault("api_keys", ["sk-gemini"])
# 5. persist resolved config (prefer app dir; fall back to HOME for safety)
cfg_path = os.path.join(APP_DIR, "config.json")
try:
with open(cfg_path, "w") as f:
json.dump(cfg, f, indent=2)
cookie_file_base = "cookie.txt"
except PermissionError:
# read-only app dir -> write into the user home instead
cfg_path = os.path.join(os.path.expanduser("~"), "config.json")
with open(cfg_path, "w") as f:
json.dump(cfg, f, indent=2)
cookie_file_base = os.path.join(os.path.expanduser("~"), "cookie.txt")
# 4. cookie (Pro / authenticated routing). Write to a file and wire it in.
cookie = os.environ.get("COOKIE", "").strip()
if cookie:
cookie_path = cookie_file_base
if not os.path.isabs(cookie_path):
cookie_path = os.path.join(APP_DIR, cookie_path)
with open(cookie_path, "w") as f:
f.write(cookie)
cfg["cookie_file"] = cookie_path
print("[run.py] COOKIE secret detected -> writing", cookie_path)
else:
cfg["cookie_file"] = None
print("[run.py] no COOKIE set -> anonymous mode")
# re-dump config so the final cookie_file value is persisted
with open(cfg_path, "w") as f:
json.dump(cfg, f, indent=2)
print(f"[run.py] listening on {cfg['host']}:{cfg['port']}")
print(f"[run.py] base url http://0.0.0.0:{cfg['port']}/v1")
print(f"[run.py] api keys {'set (' + str(len(cfg['api_keys'])) + ')' if cfg['api_keys'] else 'none (open)'}")
# 6. hand off to the server, passing explicit config so overrides win
os.chdir(APP_DIR)
os.execvp(sys.executable, [sys.executable, "-m", "gemini_web2api", "--config", cfg_path])
if __name__ == "__main__":
main()