From ea18535f1c042a663696a38db5bdd9c385d50d4d Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 20 May 2026 15:07:42 +0400 Subject: [PATCH] v2.3.2: fix Add/Edit dialog crash, smarter Google OAuth UX - Fix missing _on_reasoning_toggled method (caused Add button crash) - Redesigned Google OAuth flow with proper dialog: - Shows clickable auth URL link in dialog - Auto-opens browser for Google authorization - Live status updates while waiting for callback - Success/error shown in dialog (no popup chain) - Spinner animation during auth wait - Better setup instructions if client_secret.json missing --- codex-launcher_2.3.2_all.deb | Bin 27444 -> 28090 bytes src/codex-launcher-gui | 160 +++++++++++++++++++++++++---------- 2 files changed, 113 insertions(+), 47 deletions(-) diff --git a/codex-launcher_2.3.2_all.deb b/codex-launcher_2.3.2_all.deb index 2385cf9daa1111ae5c84be1247449de4b92a3a61..c002ee0a9fc418a40444c3148e8f8887a317da86 100644 GIT binary patch delta 27362 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 Zsopw%n!!r6SFkj-nmpxL2V7iaGS>umH@*M> delta 26711 zcmV(=J(Kn)@5d>*MIEGTj$xyIIAAc+`bYB-;--J-s0?yOdIZ55AARyz&bY7UX0y~)xv}B z;`aR3AA7ND{hj*#rxcfS1Xt<&l=ss(FJtesA1Le`kL$ z&UB^TZGYXk&w2e>>(AT9?d`t3F4pt2~zkb}oNYMNAC#iV7wfhNw zyJ0-x^eL4<309CPQcVqz3Id@PCAtx#n3`k8VC=&95v7l5gA}l5hNWlOV%LM~oNU)GhC^i$LB1j%cXgj>At!fv# zV}c@KQGwtzwIc`@iLpp97eF0ML1M}Dqfh0j#o7GvMpb+Pd|HTX{~n&uw>r@(PyMJ-LRpb*(aDs0tCd2wUxO>aR)#+EQ-fxPZJ6)@h zdz}+#nA*x^pXa6Zv>9|bwuc>%UYvLK_Wjn`dFLw!`_5lX85gbe{lB~&0kDC|oq?%4 z5E~�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') + else: + self._lbl_reasoning.set_markup('OFF') + def _do_oauth_login(self): preset_name = self._combo_preset.get_active_text() or "Custom" preset = PROVIDER_PRESETS.get(preset_name, {}) @@ -1657,21 +1665,36 @@ class EditEndpointDialog(Gtk.Dialog): client_secret_path = os.path.expanduser("~/.cache/codex-proxy/client_secret.json") if not os.path.exists(client_secret_path): - d = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, - "Google OAuth Setup\n\n" - "1. Go to https://console.cloud.google.com/\n" - "2. Create a project → Enable 'Generative Language API'\n" - "3. Go to APIs & Services → Credentials → Create OAuth 2.0 Client ID\n" - "4. Application type: Desktop app\n" - "5. Add redirect URI: http://localhost:8085\n" - "6. Download client_secret.json\n" - f"7. Save it to: {client_secret_path}\n\n" - "Then click OAuth Login again.") - d.run(); d.destroy() + dlg = Gtk.Dialog(title="Google OAuth Setup", parent=self, modal=True) + dlg.add_button("Open Google Console", 1) + dlg.add_button("I have client_secret.json", 2) + dlg.add_button("Cancel", Gtk.ResponseType.CANCEL) + dlg.set_default_size(500, 320) + 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(8) + area.pack_start(Gtk.Label(label="One-time Google OAuth Setup", use_markup=True), False, False, 0) + steps = Gtk.Label(label=( + "1. Create project at Google Cloud Console\n" + " (enable 'Generative Language API')\n" + "2. APIs & Services → Credentials\n" + " → Create OAuth 2.0 Client ID (Desktop app)\n" + "3. Add redirect URI: http://localhost:8085\n" + "4. Download client_secret.json\n" + f"5. Save to: {client_secret_path}\n\n" + "Then click 'I have client_secret.json'" + ), xalign=0) + area.pack_start(steps, False, False, 4) + area.show_all() + r = dlg.run() + dlg.destroy() + if r == 1: + subprocess.Popen(["xdg-open", "https://console.cloud.google.com/apis/credentials"]) return - import http.server, threading, urllib.parse, json, urllib.request - with open(client_secret_path) as f: cs = json.load(f) installed = cs.get("installed", cs.get("web", {})) @@ -1686,7 +1709,36 @@ class EditEndpointDialog(Gtk.Dialog): f"&response_type=code&scope={urllib.parse.quote(scope)}&access_type=offline&prompt=consent" ) + dlg = Gtk.Dialog(title="Google OAuth", parent=self, modal=True) + dlg.add_button("Cancel", Gtk.ResponseType.CANCEL) + dlg.set_default_size(520, 260) + 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(8) + + area.pack_start(Gtk.Label(label="Step 1: Authorize with Google", use_markup=True, xalign=0), False, False, 0) + link_lbl = Gtk.Label(label=f'Click here to open Google authorization', use_markup=True) + area.pack_start(link_lbl, False, False, 4) + + area.pack_start(Gtk.Label(label="Opening browser automatically…", xalign=0), False, False, 0) + + area.pack_start(Gtk.Label(label="Waiting for authorization…", use_markup=True, xalign=0), False, False, 12) + self._oauth_status = Gtk.Label(label="Listening on http://localhost:8085 …", xalign=0) + area.pack_start(self._oauth_status, False, False, 0) + + spinner = Gtk.Spinner() + spinner.start() + area.pack_start(spinner, False, False, 8) + + area.show_all() + + import http.server code_holder = [None] + error_holder = [None] + class OAuthHandler(http.server.BaseHTTPRequestHandler): def do_GET(self2): qs = urllib.parse.urlparse(self2.path).query @@ -1696,37 +1748,59 @@ class EditEndpointDialog(Gtk.Dialog): self2.send_response(200) self2.send_header("Content-Type", "text/html") self2.end_headers() - self2.wfile.write(b"

Authorization successful! You can close this tab.

") + self2.wfile.write(b"" + b"

✓ Authorization successful!

" + b"

You can close this tab and return to Codex Launcher.

") else: + error_holder[0] = params.get("error", ["unknown"])[0] self2.send_response(400) + self2.send_header("Content-Type", "text/html") self2.end_headers() - self2.wfile.write(b"Authorization failed.") + self2.wfile.write(b"" + b"

Authorization failed.

" + b"

Please close this tab and try again.

") def log_message(self2, *a): pass - server = http.server.HTTPServer(("127.0.0.1", 8085), OAuthHandler) - t = threading.Thread(target=server.handle_request, daemon=True) - t.start() - - os.system(f"xdg-open '{auth_url}' 2>/dev/null &") - - t.join(timeout=120) - server.server_close() - - if not code_holder[0]: - d = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "OAuth timed out or failed.") - d.run(); d.destroy() + try: + server = http.server.HTTPServer(("127.0.0.1", 8085), OAuthHandler) + except OSError: + self._oauth_status.set_text("Port 8085 already in use — close other apps and retry.") + spinner.stop() + dlg.run(); dlg.destroy() return - token_data = urllib.parse.urlencode({ - "code": code_holder[0], - "client_id": client_id, - "client_secret": client_secret, - "redirect_uri": redirect_uri, - "grant_type": "authorization_code", - }).encode() - req = urllib.request.Request("https://oauth2.googleapis.com/token", data=token_data, - headers={"Content-Type": "application/x-www-form-urlencoded"}) + def wait_for_code(): + server.handle_request() + server.server_close() + GLib.idle_add(self._google_oauth_complete, dlg, code_holder, error_holder, + client_id, client_secret, redirect_uri, token_path, spinner) + + threading.Thread(target=wait_for_code, daemon=True).start() + subprocess.Popen(["xdg-open", auth_url], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + dlg.run() + dlg.destroy() + + def _google_oauth_complete(self, dlg, code_holder, error_holder, + client_id, client_secret, redirect_uri, token_path, spinner): + spinner.stop() + if error_holder[0]: + self._oauth_status.set_markup(f'Error: {error_holder[0]}') + return + if not code_holder[0]: + self._oauth_status.set_text("No authorization code received.") + return + + self._oauth_status.set_text("Exchanging code for token…") try: + token_data = urllib.parse.urlencode({ + "code": code_holder[0], + "client_id": client_id, + "client_secret": client_secret, + "redirect_uri": redirect_uri, + "grant_type": "authorization_code", + }).encode() + req = urllib.request.Request("https://oauth2.googleapis.com/token", data=token_data, + headers={"Content-Type": "application/x-www-form-urlencoded"}) resp = urllib.request.urlopen(req, timeout=30) tokens = json.loads(resp.read()) tokens["client_id"] = client_id @@ -1735,18 +1809,10 @@ class EditEndpointDialog(Gtk.Dialog): with open(token_path, "w") as f: json.dump(tokens, f, indent=2) self._entry_key.set_text(tokens.get("access_token", "")) - d = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, - f"Google OAuth successful!\n\nAccess token saved.\nIt will auto-refresh when expired.") - d.run(); d.destroy() + self._oauth_status.set_markup('✓ Authorization successful! Token saved.') + dlg.set_title("Google OAuth — Success") except Exception as e: - d = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, f"Token exchange failed:\n{e}") - d.run(); d.destroy() - active = self._switch_reasoning.get_active() - self._combo_effort.set_sensitive(active) - if active: - self._lbl_reasoning.set_markup('ON') - else: - self._lbl_reasoning.set_markup('OFF') + self._oauth_status.set_markup(f'Token exchange failed: {e}') def _remove_model(self, path): current = self._combo_default.get_active_text()