From ac24fe637235cac170515ed074afef07458be49e Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 19 May 2026 15:32:44 +0400 Subject: [PATCH] v2.0.1: Add Codex CLI/Desktop installation verifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Detects codex CLI (via 'which codex' + --version) and Desktop (via /opt/codex-desktop/start.sh) - Shows green ✔ or yellow ✘ status bar on main page - 'Install' button opens guide dialog with install commands - Desktop/CLI launch buttons disabled when corresponding tool is missing - Dependency status logged on startup - _set_busy respects missing-state (won't re-enable disabled buttons) - Rebuilt .deb as v2.0.1 --- CHANGELOG.md | 9 +++ codex-launcher_2.0.0_all.deb | Bin 19766 -> 0 bytes codex-launcher_2.0.1_all.deb | Bin 0 -> 20504 bytes src/codex-launcher-gui | 135 ++++++++++++++++++++++++++++++++--- 4 files changed, 136 insertions(+), 8 deletions(-) delete mode 100644 codex-launcher_2.0.0_all.deb create mode 100644 codex-launcher_2.0.1_all.deb diff --git a/CHANGELOG.md b/CHANGELOG.md index 35e930b..6e019b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## v2.0.1 (2026-05-19) + +- Added Codex CLI/Desktop installation verifier to main page +- Green check (✔) when detected, yellow cross (✘) when missing +- "Install" button next to missing tools opens install guide dialog +- Desktop/CLI launch buttons disabled with tooltip when tool is missing +- Dependency status logged on startup +- Buttons respect missing-state after busy/unbusy cycles + ## v2.0.0 (2026-05-19) - Initial release: multi-provider Codex Launcher diff --git a/codex-launcher_2.0.0_all.deb b/codex-launcher_2.0.0_all.deb deleted file mode 100644 index 72613b11b4ece9cde2f5414d8f999db9c09e179c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19766 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%0AhZ9Ha<~(+FPEcf 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 diff --git a/codex-launcher_2.0.1_all.deb b/codex-launcher_2.0.1_all.deb new file mode 100644 index 0000000000000000000000000000000000000000..141678b51d90e3ac4e45803554a5768bf297e188 GIT binary patch literal 20504 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 literal 0 HcmV?d00001 diff --git a/src/codex-launcher-gui b/src/codex-launcher-gui index a7bf22e..6a65119 100755 --- a/src/codex-launcher-gui +++ b/src/codex-launcher-gui @@ -24,6 +24,11 @@ model_catalog_json = "" """ CHANGELOG = [ + ("2.0.1", "2026-05-19", [ + "Added Codex CLI/Desktop installation verifier to main page", + "Disables Desktop/CLI launch buttons when corresponding tool is missing", + "Shows install instructions in status area on startup", + ]), ("2.0.0", "2026-05-19", [ "Initial release: multi-provider Codex Launcher", "Translation proxy: Responses API to Chat Completions + Anthropic Messages", @@ -429,6 +434,22 @@ def _last_log_lines(n=15): except Exception: return "(no log file)" +def _detect_codex_cli(): + try: + path = shutil.which("codex") + if not path: + return None + out = subprocess.run(["codex", "--version"], capture_output=True, text=True, timeout=5) + ver = (out.stdout or "").strip() or (out.stderr or "").strip() or "unknown" + return (path, ver) + except Exception: + return None + +def _detect_codex_desktop(): + if START_SH.exists(): + return str(START_SH) + return None + # ═══════════════════════════════════════════════════════════════════ # Main window # ═══════════════════════════════════════════════════════════════════ @@ -448,7 +469,7 @@ class LauncherWin(Gtk.Window): # header row hdr = Gtk.Box(spacing=8) vbox.pack_start(hdr, False, False, 0) - lbl = Gtk.Label(label="Codex Launcher v2.0.0") + lbl = Gtk.Label(label="Codex Launcher v2.0.1") lbl.set_use_markup(True) hdr.pack_start(lbl, False, False, 0) changelog_btn = Gtk.Button(label="Changelog") @@ -458,6 +479,49 @@ class LauncherWin(Gtk.Window): mgr_btn.connect("clicked", lambda b: self._open_mgr()) hdr.pack_end(mgr_btn, False, False, 0) + # verification status bar + self._cli_info = _detect_codex_cli() + self._desktop_info = _detect_codex_desktop() + ver_box = Gtk.Box(spacing=12) + vbox.pack_start(ver_box, False, False, 0) + + if self._cli_info: + cli_path, cli_ver = self._cli_info + cli_lbl = Gtk.Label() + cli_lbl.set_markup(f"✔ Codex CLI {cli_ver} ({cli_path})") + cli_lbl.set_use_markup(True) + ver_box.pack_start(cli_lbl, False, False, 0) + else: + cli_lbl = Gtk.Label() + cli_lbl.set_markup("✘ Codex CLI — not found") + cli_lbl.set_use_markup(True) + ver_box.pack_start(cli_lbl, False, False, 0) + cli_install_btn = Gtk.Button(label="Install") + cli_install_btn.connect("clicked", lambda b: self._show_install_guide("cli")) + ver_box.pack_start(cli_install_btn, False, False, 0) + + ver_box.pack_start(Gtk.Label(label=" "), False, False, 0) + + if self._desktop_info: + desk_lbl = Gtk.Label() + desk_lbl.set_markup(f"✔ Codex Desktop ({self._desktop_info})") + desk_lbl.set_use_markup(True) + ver_box.pack_start(desk_lbl, False, False, 0) + else: + desk_lbl = Gtk.Label() + desk_lbl.set_markup("✘ Codex Desktop — not found") + desk_lbl.set_use_markup(True) + ver_box.pack_start(desk_lbl, False, False, 0) + desk_install_btn = Gtk.Button(label="Install") + desk_install_btn.connect("clicked", lambda b: self._show_install_guide("desktop")) + ver_box.pack_start(desk_install_btn, False, False, 0) + + self._missing = [] + if not self._cli_info: + self._missing.append("cli") + if not self._desktop_info: + self._missing.append("desktop") + ops_box = Gtk.Box(spacing=8) vbox.pack_start(ops_box, False, False, 0) self._refresh_all_btn = Gtk.Button(label="Refresh Models") @@ -488,18 +552,30 @@ class LauncherWin(Gtk.Window): vbox.pack_start(btn_box, False, False, 8) self._btn_desktop = Gtk.Button(label="Launch Desktop") self._btn_desktop.connect("clicked", lambda b: self._launch("desktop")) + if "desktop" in self._missing: + self._btn_desktop.set_tooltip_text("Codex Desktop is not installed") + self._btn_desktop.set_sensitive(False) btn_box.pack_start(self._btn_desktop, True, True, 0) self._btn_cli = Gtk.Button(label="Launch CLI") self._btn_cli.connect("clicked", lambda b: self._launch("cli")) + if "cli" in self._missing: + self._btn_cli.set_tooltip_text("Codex CLI is not installed") + self._btn_cli.set_sensitive(False) btn_box.pack_start(self._btn_cli, True, True, 0) btn_box2 = Gtk.Box(spacing=8, homogeneous=True) vbox.pack_start(btn_box2, False, False, 0) self._btn_codex_desktop = Gtk.Button(label="Codex Default (Desktop)") self._btn_codex_desktop.connect("clicked", lambda b: self._launch_codex_default("desktop")) + if "desktop" in self._missing: + self._btn_codex_desktop.set_tooltip_text("Codex Desktop is not installed") + self._btn_codex_desktop.set_sensitive(False) btn_box2.pack_start(self._btn_codex_desktop, True, True, 0) self._btn_codex_cli = Gtk.Button(label="Codex Default (CLI)") self._btn_codex_cli.connect("clicked", lambda b: self._launch_codex_default("cli")) + if "cli" in self._missing: + self._btn_codex_cli.set_tooltip_text("Codex CLI is not installed") + self._btn_codex_cli.set_sensitive(False) btn_box2.pack_start(self._btn_codex_cli, True, True, 0) # status @@ -529,6 +605,7 @@ class LauncherWin(Gtk.Window): self.show_all() self._rebuild_combo() + self._log_dependency_status() # ── helpers ────────────────────────────────────────────────── @@ -542,14 +619,31 @@ class LauncherWin(Gtk.Window): self._tv.scroll_to_mark(m, 0.0, True, 0.0, 0.5) self._buf.delete_mark(m) + def _log_dependency_status(self): + if self._cli_info: + _, ver = self._cli_info + self.log(f"✔ Codex CLI detected ({ver})") + else: + self.log("✘ Codex CLI NOT found — CLI launch disabled. Click 'Install' above.") + if self._desktop_info: + self.log(f"✔ Codex Desktop detected ({self._desktop_info})") + else: + self.log("✘ Codex Desktop NOT found — Desktop launch disabled. Click 'Install' above.") + if self._missing: + self.log("⚠ Install missing tools before using the launcher.") + else: + self.log("All dependencies OK.") + def _set_busy(self, busy): - GLib.idle_add(lambda: ( - self._btn_desktop.set_sensitive(not busy), - self._btn_cli.set_sensitive(not busy), - self._btn_codex_desktop.set_sensitive(not busy), - self._btn_codex_cli.set_sensitive(not busy), - self._kill_btn.set_sensitive(busy), - )) + def _update(): + has_cli = "cli" not in self._missing + has_desk = "desktop" not in self._missing + self._btn_desktop.set_sensitive(not busy and has_desk) + self._btn_cli.set_sensitive(not busy and has_cli) + self._btn_codex_desktop.set_sensitive(not busy and has_desk) + self._btn_codex_cli.set_sensitive(not busy and has_cli) + self._kill_btn.set_sensitive(busy) + GLib.idle_add(_update) def _rebuild_combo(self): self._endpoints_data = load_endpoints() @@ -746,6 +840,31 @@ class LauncherWin(Gtk.Window): d.run() d.destroy() + def _show_install_guide(self, which): + if which == "cli": + title = "Install Codex CLI" + guide = ( + "Codex CLI is required to use CLI launch features.\n\n" + "Install with npm:\n" + " npm install -g @openai/codex\n\n" + "Or download from:\n" + " https://github.com/openai/codex\n\n" + "After installing, restart the launcher." + ) + else: + title = "Install Codex Desktop" + guide = ( + "Codex Desktop is required to use Desktop launch features.\n\n" + "Expected location: /opt/codex-desktop/start.sh\n\n" + "Download from:\n" + " https://codex.desktop.openai.com\n\n" + "After installing, restart the launcher." + ) + d = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, guide) + d.set_title(title) + d.run() + d.destroy() + # ── launch ─────────────────────────────────────────────────── def _launch(self, target):