import os import time import requests import re import sys CLIENT_ID = "Iv1.b507a08c87ecfe98" # Standard VSCode/Copilot Client ID def initiate_device_flow(): print("\n🔐 [Jarvis Auth] Initiating GitHub Device Flow...") try: res = requests.post("https://github.com/login/device/code", data={ "client_id": CLIENT_ID, "scope": "read:user" }, headers={"Accept": "application/json"}, timeout=10) res.raise_for_status() return res.json() except Exception as e: print(f"❌ Failed to initiate auth: {e}") sys.exit(1) def poll_for_token(device_code, interval, expires_in): print(f"\n⏳ Polling for authorization (expires in {expires_in}s)...") start_time = time.time() while time.time() - start_time < expires_in: try: res = requests.post("https://github.com/login/oauth/access_token", data={ "client_id": CLIENT_ID, "device_code": device_code, "grant_type": "urn:ietf:params:oauth:grant-type:device_code" }, headers={"Accept": "application/json"}, timeout=10) res.raise_for_status() data = res.json() if "access_token" in data: return data["access_token"] error = data.get("error") if error == "authorization_pending": time.sleep(interval) elif error == "slow_down": interval += 5 time.sleep(interval) else: print(f"❌ Auth error: {error}") return None except KeyboardInterrupt: raise except Exception as e: print(f"⚠️ Polling error: {e}") time.sleep(interval) return None def update_env(token): # Find project root (assumed to be 2 levels up from this script in brain/) project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) env_path = os.path.join(project_root, ".env") content = "" if os.path.exists(env_path): with open(env_path, 'r', encoding='utf-8') as f: content = f.read() if "GITHUB_TOKEN=" in content: new_content = re.sub(r'GITHUB_TOKEN=.*', f'GITHUB_TOKEN={token}', content) else: new_content = content.rstrip() + f"\nGITHUB_TOKEN={token}\n" with open(env_path, 'w', encoding='utf-8') as f: f.write(new_content) print(f"\n✅ .env file updated with new GITHUB_TOKEN.") def main(): data = initiate_device_flow() user_code = data.get("user_code") verification_uri = data.get("verification_uri") print("\n" + "!"*50, flush=True) print(f" 인증 링크: {verification_uri}", flush=True) print(f" 인증 코드: {user_code}", flush=True) print("!"*50, flush=True) print("\n위 링크를 브라우저에서 열고 코드를 입력하여 승인해 주십시오.", flush=True) # Optional: try to open the browser automatically try: import webbrowser webbrowser.open(verification_uri) except: pass token = poll_for_token(data["device_code"], data.get("interval", 5), data.get("expires_in", 900)) if token: print("\n✨ Authentication Successful!") update_env(token) else: print("\n❌ Authentication failed or timed out.") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\n⚠️ [Jarvis Auth] 인증이 사용자에 의해 중단되었습니다.") sys.exit(0)