From 5dab800d6587488fb42d115f748e0e1ed68fbe56 Mon Sep 17 00:00:00 2001 From: Alex Cube Date: Wed, 26 Aug 2026 17:18:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B2=D1=82=D0=BE=D1=80=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BB=D0=B5=20=D1=81=D0=BC=D0=B5=D1=80=D1=82=D0=B8?= =?UTF-8?q?=20=D0=B1=D1=80=D0=B0=D1=83=D0=B7=D0=B5=D1=80=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проверено вживую: браузер убит через 10 с после начала запроса. Сокет умирал честно, браузер поднимался, но повтор падал на «кнопка New chat не найдена» — ensureBrowser возвращался, едва отладочный порт отозвался. У холодного браузера адрес задан аргументом командной строки, поэтому вкладка есть в списке сразу, а разметки нет ещё несколько секунд, и ветка с ожиданием после /json/new в этом случае не выполнялась вовсе. Теперь ensureBrowser в обоих случаях ждёт поле ввода — примету того, что страницей можно пользоваться, — и отдельно распознаёт страницу входа, где ждать нечего. После правки тот же опыт даёт полный ответ: запрос пережил смерть браузера и вернул 9888 символов за 140 с. --- browser.mjs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/browser.mjs b/browser.mjs index 2e39a57..103b083 100644 --- a/browser.mjs +++ b/browser.mjs @@ -1068,7 +1068,7 @@ export async function ensureBrowser(log = () => {}) { .then(r => r.json()).catch(() => []); const isChat = t => String(t.url || '').includes('deepseek'); - if ((await tabs()).some(isChat)) return; + if ((await tabs()).some(isChat)) return waitPageReady(log); // Новая вкладка в свежих сборках Chromium открывается ТОЛЬКО методом PUT: // на GET протокол отвечает 405 и молча ничего не делает. // @@ -1078,13 +1078,39 @@ export async function ensureBrowser(log = () => {}) { const r = await fetch(`http://127.0.0.1:${PORT}/json/new?${BROWSER.url}`, { method: 'PUT' }); if (!r.ok) throw new Error(`Не удалось открыть вкладку DeepSeek: ${r.status}.`); - await sleep(4000); // дать чату прогрузиться до первого вопроса + await sleep(1000); // Открыл — убедись, что открылось именно то: молчаливый промах здесь уже был. if (!(await tabs()).some(isChat)) { throw new Error(`Вкладка открылась, но не с ${BROWSER.url}. ` + 'Похоже, браузер не принял адрес — закройте лишние вкладки и повторите.'); } log('вкладка с чатом открыта'); + await waitPageReady(log); +} + +// Открытая вкладка — ещё не готовый чат. У холодного браузера адрес задан +// аргументом командной строки, вкладка в списке появляется сразу, а разметки +// нет ещё несколько секунд: повтор после смерти браузера падал на «кнопка +// New chat не найдена». Ждём поле ввода — единственную примету, что страницей +// можно пользоваться. +async function waitPageReady(log = () => {}) { + let s; + try { s = await Session.connect((await findChatTab()).webSocketDebuggerUrl); } + catch { return; } // вкладку успели закрыть — разберётся вызвавший + try { + for (let i = 0; i < 60; i++) { // до ~60 с: холодный профиль неспешен + const st = await s.eval(`(() => { ${PAGE_HELPERS} + return { input: !!__input(), + login: /log ?in|войти|sign in/i.test(document.body.innerText.slice(0, 3000)) }; + })()`).catch(() => null); + if (st && st.input) { await sleep(800); return; } + // Вход руками — ждать нечего: страница жива, просто мы не залогинены. + if (st && st.login) { log('нужен вход в DeepSeek — сделайте это в окне браузера'); return; } + await sleep(1000); + } + throw new Error('Вкладка DeepSeek открыта, но чат так и не появился: ' + + 'страница не загрузилась или изменилась разметка.'); + } finally { s.close(); } } // Приметы того, что вкладка или браузер пропали посреди работы. По ним ask()