diff --git a/launcher/package.json b/launcher/package.json index 2615d85d6..b678025b9 100644 --- a/launcher/package.json +++ b/launcher/package.json @@ -1,6 +1,6 @@ { "name": "codex-web-gpt-launcher", - "version": "3.0.6", + "version": "3.0.7", "private": true, "description": "Desktop control center for Codex ChatGPT Web", "author": "miuuyy", diff --git a/package.json b/package.json index d46b0c77a..160e5090c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codex-chatgpt-web", - "version": "3.0.6", + "version": "3.0.7", "private": true, "description": "A focused local Responses bridge that runs Codex tasks through a user-authenticated ChatGPT web session.", "repository": { diff --git a/scripts/install.sh b/scripts/install.sh index b88692df8..e86558bc7 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -2,7 +2,7 @@ set -eu REPOSITORY="${CODEX_CHATGPT_WEB_REPOSITORY:-miuuyy/codex-chatgpt-web}" -VERSION="${CODEX_CHATGPT_WEB_VERSION:-3.0.6}" +VERSION="${CODEX_CHATGPT_WEB_VERSION:-3.0.7}" BIN_DIR="${CODEX_CHATGPT_WEB_BIN_DIR:-$HOME/.local/bin}" LIB_DIR="${CODEX_CHATGPT_WEB_LIB_DIR:-$HOME/.local/lib/codex-chatgpt-web}" DOC_DIR="${CODEX_CHATGPT_WEB_DOC_DIR:-$HOME/.local/share/doc/codex-chatgpt-web}" diff --git a/src/adapters/chatgpt-web/browser-worker.ts b/src/adapters/chatgpt-web/browser-worker.ts index 71403fdb6..414e90cc8 100644 --- a/src/adapters/chatgpt-web/browser-worker.ts +++ b/src/adapters/chatgpt-web/browser-worker.ts @@ -1207,7 +1207,20 @@ export class ChatGptBrowserWorker { const activated = await control.evaluate((element) => { if (!(element instanceof HTMLButtonElement)) return false; if (element.getAttribute("aria-haspopup") !== "menu") return false; - element.click(); + // ChatGPT's current Radix trigger opens on pointerdown. HTMLElement.click() dispatches only + // a synthetic click, so it is ignored even though the same button is the one authoritative + // effort control. Dispatch the trigger event in-document to avoid Playwright's 1x1 + // background viewport geometry while retaining the opened menu as the postcondition. + element.dispatchEvent(new PointerEvent("pointerdown", { + bubbles: true, + cancelable: true, + composed: true, + button: 0, + buttons: 1, + pointerId: 1, + pointerType: "mouse", + isPrimary: true, + })); return true; }); if (activated) return; diff --git a/src/version.ts b/src/version.ts index 94a9e1804..23cc2f234 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = "3.0.6"; +export const VERSION = "3.0.7"; diff --git a/tests/browser-worker-contract.test.ts b/tests/browser-worker-contract.test.ts index dea2d965e..40a2be52f 100644 --- a/tests/browser-worker-contract.test.ts +++ b/tests/browser-worker-contract.test.ts @@ -1008,7 +1008,8 @@ test("effort selection handles the known ChatGPT rate-limit dialog before backgr expect(selectionSource).toContain("effortControlCount !== 1"); expect(workerSource).toContain("element instanceof HTMLButtonElement"); expect(workerSource).toContain('element.getAttribute("aria-haspopup") !== "menu"'); - expect(workerSource).toContain("element.click()"); + expect(workerSource).toContain('new PointerEvent("pointerdown"'); + expect(workerSource).not.toContain("element.click()"); expect(selectionSource).toContain('effortChoice.press("Enter")'); expect(selectionSource).not.toContain("effortChoice.click("); expect(selectionSource).not.toContain("is unavailable");