diff --git a/src/chatgpt_web2api/backend_client.py b/src/chatgpt_web2api/backend_client.py index 4ea582bb..e2f06d00 100644 --- a/src/chatgpt_web2api/backend_client.py +++ b/src/chatgpt_web2api/backend_client.py @@ -276,7 +276,7 @@ async def _fetch_recent_conversation_projection( on 401 (with breaker trip), ``_Transient404`` on 404, ``RuntimeError`` on other non-OK status, and ``CDPJSError`` on transport failure. """ - from .backend_projection import CONVERSATION_PROJECTION_JS, TURN_PROJECTION_LIMIT + from .backend_projection import CONVERSATION_PROJECTION_JS from .cdp_driver import AuthExpiredError, CDPJSError d = self._driver @@ -286,7 +286,6 @@ async def _fetch_recent_conversation_projection( { "conv_id": conversation_id, "token": d._access_token, - "limit": TURN_PROJECTION_LIMIT, }, timeout=15, ) diff --git a/src/chatgpt_web2api/backend_projection.py b/src/chatgpt_web2api/backend_projection.py index 6f40b9a7..4215cb59 100644 --- a/src/chatgpt_web2api/backend_projection.py +++ b/src/chatgpt_web2api/backend_projection.py @@ -41,7 +41,7 @@ CONVERSATION_PROJECTION_JS = """ (async function() { try { - var r = await fetch('/backend-api/conversation/' + __D.conv_id + '?offset=0&limit=' + __D.limit, { + var r = await fetch('/backend-api/conversation/' + __D.conv_id, { headers: {'Authorization': 'Bearer ' + __D.token} }); if (!r.ok) return JSON.stringify({__status: r.status}); diff --git a/src/chatgpt_web2api/cdp_driver.py b/src/chatgpt_web2api/cdp_driver.py index 3bc3eae4..ff104df3 100644 --- a/src/chatgpt_web2api/cdp_driver.py +++ b/src/chatgpt_web2api/cdp_driver.py @@ -1499,12 +1499,12 @@ async def _read_assistant_count_baseline(self) -> int: selector = ( "document.querySelectorAll(" - "'[data-message-author-role=\"assistant\"]'" + "'[data-message-author-role=\"assistant\"], [data-content-search-unit-key$=\":assistant\"], [data-chatgpt-search-unit-key$=\":assistant\"]'" ").length" ) user_selector = ( "document.querySelectorAll(" - "'[data-message-author-role=\"user\"]'" + "'[data-message-author-role=\"user\"], [data-content-search-unit-key$=\":user\"], [data-chatgpt-search-unit-key$=\":user\"]'" ").length" ) max_attempts = 3 @@ -1610,7 +1610,7 @@ async def _verify_send_acknowledged(self) -> bool | None: result = await self._js_strict( "(function() {" " var userMsgs = document.querySelectorAll(" - " '[data-message-author-role=\"user\"]').length;" + " '[data-message-author-role=\"user\"], [data-content-search-unit-key$=\":user\"], [data-chatgpt-search-unit-key$=\":user\"]').length;" f" var composer = document.querySelector('{COMPOSER_SELECTOR}')" f" || document.querySelector('{COMPOSER_FALLBACK_SELECTOR}');" " var composerPresent = !!composer;" diff --git a/src/chatgpt_web2api/completion_detector.py b/src/chatgpt_web2api/completion_detector.py index c5a47d8f..237973d5 100644 --- a/src/chatgpt_web2api/completion_detector.py +++ b/src/chatgpt_web2api/completion_detector.py @@ -377,7 +377,7 @@ async def stream_until_complete( try: raw = await d._js_strict( - "document.querySelectorAll('[data-message-author-role=\"assistant\"]').length" + "document.querySelectorAll('[data-message-author-role=\"assistant\"], [data-content-search-unit-key$=\":assistant\"], [data-chatgpt-search-unit-key$=\":assistant\"]').length" ) current_count = int(raw or 0) except CDPJSError: @@ -474,7 +474,7 @@ async def stream_until_complete( try: result = await d._js_strict( "(function() {" - " var msgs = document.querySelectorAll('[data-message-author-role=\"assistant\"]');" + " var msgs = document.querySelectorAll('[data-message-author-role=\"assistant\"], [data-content-search-unit-key$=\":assistant\"], [data-chatgpt-search-unit-key$=\":assistant\"]');" " if (!msgs.length) return JSON.stringify({text:'', md_text:'', html_len:0, child_count:0, has_action:false, is_thinking:false});" " var last = msgs[msgs.length - 1];" # Text: the clean answer lives in ``.markdown`` textContent. diff --git a/tests/test_backend_projection_js.py b/tests/test_backend_projection_js.py index c7df08ec..6dc7c499 100644 --- a/tests/test_backend_projection_js.py +++ b/tests/test_backend_projection_js.py @@ -34,13 +34,13 @@ def test_js_is_nonempty_string(self): def test_js_fetches_correct_endpoint(self): assert "/backend-api/conversation/" in CONVERSATION_PROJECTION_JS - assert "offset=0" in CONVERSATION_PROJECTION_JS - assert "limit=" in CONVERSATION_PROJECTION_JS + assert "?offset=" not in CONVERSATION_PROJECTION_JS + assert "&limit=" not in CONVERSATION_PROJECTION_JS def test_js_threads_data_slots(self): assert "__D.conv_id" in CONVERSATION_PROJECTION_JS assert "__D.token" in CONVERSATION_PROJECTION_JS - assert "__D.limit" in CONVERSATION_PROJECTION_JS + assert "__D.limit" not in CONVERSATION_PROJECTION_JS def test_js_status_decode(self): assert "__status" in CONVERSATION_PROJECTION_JS diff --git a/tests/test_current_dom_role_selectors.py b/tests/test_current_dom_role_selectors.py new file mode 100644 index 00000000..74674b4d --- /dev/null +++ b/tests/test_current_dom_role_selectors.py @@ -0,0 +1,9 @@ +import inspect +from chatgpt_web2api.cdp_driver import CDPDriver +from chatgpt_web2api.completion_detector import CompletionDetector + +def test_current_chatgpt_role_selectors_are_supported(): + src = inspect.getsource(CDPDriver) + inspect.getsource(CompletionDetector) + assert "data-content-search-unit-key$=\\\":assistant\\\"" in src + assert "data-content-search-unit-key$=\\\":user\\\"" in src + assert "data-message-author-role" in src