diff --git a/src/codex-launcher-gui b/src/codex-launcher-gui index dfe59b4..9bbf7bc 100755 --- a/src/codex-launcher-gui +++ b/src/codex-launcher-gui @@ -2790,6 +2790,64 @@ class LauncherWin(Gtk.Window): _stop_proxy() Gtk.main_quit() + def _edit_oauth_secrets(self): + secrets_path = os.path.expanduser("~/.config/codex-launcher/oauth-secrets.json") + try: + with open(secrets_path) as f: + data = json.load(f) + except Exception: + data = {"antigravity": {"client_id": "", "client_secret": ""}, + "gemini_cli": {"client_id": "", "client_secret": ""}} + + dlg = Gtk.Dialog(title="OAuth 2.0 Client Secrets", parent=self, modal=True) + dlg.add_button("Cancel", Gtk.ResponseType.CANCEL) + dlg.add_button("Save", Gtk.ResponseType.OK) + dlg.set_default_size(520, 340) + area = dlg.get_content_area() + area.set_margin_start(16) + area.set_margin_end(16) + area.set_margin_top(12) + area.set_margin_bottom(12) + area.set_spacing(6) + + area.pack_start(Gtk.Label(label="Google OAuth 2.0 credentials\nStored locally in ~/.config/codex-launcher/oauth-secrets.json", use_markup=True, xalign=0), False, False, 4) + + fields = {} + for section_key, section_label in [("antigravity", "Antigravity (CloudCode)"), ("gemini_cli", "Gemini CLI")]: + area.pack_start(Gtk.Label(label=f"\n{section_label}", use_markup=True, xalign=0), False, False, 2) + sec = data.get(section_key, {}) + for fk, fl in [("client_id", "Client ID"), ("client_secret", "Client Secret")]: + row = Gtk.Box(spacing=6) + lbl = Gtk.Label(label=fl + ":", xalign=0) + lbl.set_size_request(100, -1) + entry = Gtk.Entry() + entry.set_text(sec.get(fk, "")) + entry.set_size_request(380, -1) + if fk == "client_secret": + entry.set_visibility(False) + entry.set_invisible_char("*") + row.pack_start(lbl, False, False, 0) + row.pack_start(entry, True, True, 0) + area.pack_start(row, False, False, 2) + fields[(section_key, fk)] = entry + + area.pack_start(Gtk.Label(label="\nGet credentials from console.cloud.google.com → APIs & Services → Credentials", use_markup=True, xalign=0), False, False, 4) + area.show_all() + + if dlg.run() == Gtk.ResponseType.OK: + for (sk, fk), entry in fields.items(): + if sk not in data: + data[sk] = {} + data[sk][fk] = entry.get_text().strip() + try: + os.makedirs(os.path.dirname(secrets_path), exist_ok=True) + with open(secrets_path, "w") as f: + json.dump(data, f, indent=2) + os.chmod(secrets_path, 0o600) + except Exception as e: + self._show_error_dialog("Save failed", str(e)) + dlg.destroy() + # ═══════════════════════════════════════════════════════════════════ # Endpoint manager dialog # ═══════════════════════════════════════════════════════════════════ @@ -3267,64 +3325,6 @@ class EditEndpointDialog(Gtk.Dialog): else: self._lbl_reasoning.set_markup('OFF') - def _edit_oauth_secrets(self): - secrets_path = os.path.expanduser("~/.config/codex-launcher/oauth-secrets.json") - try: - with open(secrets_path) as f: - data = json.load(f) - except Exception: - data = {"antigravity": {"client_id": "", "client_secret": ""}, - "gemini_cli": {"client_id": "", "client_secret": ""}} - - dlg = Gtk.Dialog(title="OAuth 2.0 Client Secrets", parent=self, modal=True) - dlg.add_button("Cancel", Gtk.ResponseType.CANCEL) - dlg.add_button("Save", Gtk.ResponseType.OK) - dlg.set_default_size(520, 340) - area = dlg.get_content_area() - area.set_margin_start(16) - area.set_margin_end(16) - area.set_margin_top(12) - area.set_margin_bottom(12) - area.set_spacing(6) - - area.pack_start(Gtk.Label(label="Google OAuth 2.0 credentials\nStored locally in ~/.config/codex-launcher/oauth-secrets.json", use_markup=True, xalign=0), False, False, 4) - - fields = {} - for section_key, section_label in [("antigravity", "Antigravity (CloudCode)"), ("gemini_cli", "Gemini CLI")]: - area.pack_start(Gtk.Label(label=f"\n{section_label}", use_markup=True, xalign=0), False, False, 2) - sec = data.get(section_key, {}) - for fk, fl in [("client_id", "Client ID"), ("client_secret", "Client Secret")]: - row = Gtk.Box(spacing=6) - lbl = Gtk.Label(label=fl + ":", xalign=0) - lbl.set_size_request(100, -1) - entry = Gtk.Entry() - entry.set_text(sec.get(fk, "")) - entry.set_size_request(380, -1) - if fk == "client_secret": - entry.set_visibility(False) - entry.set_invisible_char("*") - row.pack_start(lbl, False, False, 0) - row.pack_start(entry, True, True, 0) - area.pack_start(row, False, False, 2) - fields[(section_key, fk)] = entry - - area.pack_start(Gtk.Label(label="\nGet credentials from console.cloud.google.com → APIs & Services → Credentials", use_markup=True, xalign=0), False, False, 4) - area.show_all() - - if dlg.run() == Gtk.ResponseType.OK: - for (sk, fk), entry in fields.items(): - if sk not in data: - data[sk] = {} - data[sk][fk] = entry.get_text().strip() - try: - os.makedirs(os.path.dirname(secrets_path), exist_ok=True) - with open(secrets_path, "w") as f: - json.dump(data, f, indent=2) - os.chmod(secrets_path, 0o600) - except Exception as e: - self._show_error_dialog("Save failed", str(e)) - dlg.destroy() - def _do_oauth_login(self): preset_name = self._combo_preset.get_active_text() or "Custom" preset = PROVIDER_PRESETS.get(preset_name, {})