Skip to content

fix: reliable answer capture + auth lifecycle hardening - #45

Open
jengchakhrit-ck wants to merge 3 commits into
PleasePrompto:masterfrom
jengchakhrit-ck:fix/auth-and-answer-capture
Open

fix: reliable answer capture + auth lifecycle hardening#45
jengchakhrit-ck wants to merge 3 commits into
PleasePrompto:masterfrom
jengchakhrit-ck:fix/auth-and-answer-capture

Conversation

@jengchakhrit-ck

Copy link
Copy Markdown

Summary

Three fixes that make ask_question.py reliable across persisted browser sessions and harden the auth lifecycle. All changes are confined to scripts/ (ask_question.py, auth_manager.py, browser_utils.py) — no config or dependency changes.

Problems fixed

1. Answer capture timed out even when the answer rendered.
NotebookLM persists the chat thread across browser sessions, so the poll locked onto the previous answer (returning it instantly) or never detected the new one. The fresh answer is not reliably the DOM-last container (NotebookLM does not render the thread strictly chronologically) and the container count does not always grow — so neither texts[-1] nor len() > pre_count detects it. An answer can also be textually identical to an earlier one (same question asked twice), so plain set-membership novelty rejects it.

  • Fix: snapshot a multiset (collections.Counter) of existing answers before submit, then accept the text whose occurrence count is now higher (novel by occurrence delta, found at any index) and pick the longest such candidate before waiting for it to stop streaming.

2. Send button missed on non-English UIs.
The send button is locale-dependent (e.g. Thai "ส่ง", icon arrow_forward) and only enables once real key events land. The old English-only ['Send'/'Submit'] text match missed the localized button, and the button[type=submit] fallback clicked the wrong element → silent no-send → the answer poll then hit its full timeout.

  • Fix: match the button by aria-label/icon across languages, nudge it with a real keystroke until it is clickable, and fall back to Enter.

3. validate_auth() false-positive + slow session decay.
Validation only loaded the home page, so a near-dead session passed while the actual notebook load bounced to the Google login screen. Separately, the read path never re-saved browser state, so the state.json session cookies (the playwright#36139 workaround) stayed frozen at login time — even daily use eventually forced a manual re-auth once Google rotated them.

  • Fix: a notebook-level deep-gate in validate_auth() (load the first library notebook, let the SSO bounce settle, require the query input to actually render), plus _save_browser_state() on every successful query so continuous use extends the session instead of letting it decay.

Notes

  • Verified end-to-end against a live notebook (multi-part answers returned cleanly).
  • No new dependencies; changes are additive to the existing hybrid-auth approach.

jengchakhrit-ck and others added 3 commits May 23, 2026 18:33
Three issues made ask_question.py non-functional against current NotebookLM:

1. human_type cached one ElementHandle then typed char-by-char; the Angular
   chat panel re-renders the textarea during hydration, detaching the handle
   ("Element is not attached to the DOM"). Replaced with a Locator retry-loop +
   atomic fill() + value verification.
2. Submit used keyboard Enter, which inserts a newline after a programmatic
   fill() and does not send. Now clicks the send button (aria-label/​type),
   Enter only as fallback.
3. Answer poll locked onto the previous chat message (NotebookLM persists chat
   history) and returned it instantly. Now baselines the pre-submit answer and
   accepts only a new, stable response.

Known limit: multiple questions in one notebook session share chat context and
return RAG-anchored repeats; ask one question per session for distinct answers.
Submit failed silently on a non-English NotebookLM UI. The send-button
selector list was English-only ('Send'/'Submit'), but the live button is
localized (e.g. Thai 'ส่ง', icon arrow_forward). No match -> the
button[type=submit] fallback clicked the WRONG element -> message never
sent -> 120s answer timeout. Replaced with a locale-agnostic finder
(aria-label /send|submit|ส่ง/i OR mat-icon send/arrow_forward/arrow_upward)
that nudges a real keystroke until the Angular send button enables.

Also fixed stale-answer capture: NotebookLM persists the chat thread across
sessions, so the text-baseline raced the thread render and returned the
previous query's answer. Now settle the thread, then gate acceptance on a
NEW answer container appearing (count increase) + reject loading placeholders.

Verified live: PONG smoke + real query both return fresh, source-grounded answers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three compounding failures found while testing a live query:

1. ask_question answer-capture timed out though the answer rendered.
   - texts[-1] is not reliably the newest answer (NotebookLM renders the
     thread non-chronologically), and the len()>pre_count gate never fired
     because the persisted thread does not grow the container count.
   - Fix: identify the answer by Counter-delta novelty (a text whose
     occurrence count now exceeds the pre-submit snapshot) at any index,
     picking the longest candidate. Robust to duplicate answers too.

2. auth_manager validate gave a false-positive when the session was stale.
   - It only loaded the home page; a near-dead session still passes that
     while a real /notebook/<id> load bounces to accounts.google.com.
   - Fix: add a notebook-level gate that loads the first library notebook
     and requires the query input to render (the actual usage surface).

3. Session decayed even under continuous use.
   - The state.json session cookies (Playwright #36139 workaround) were
     frozen at login and never refreshed by the read path, so Google
     rotation eventually forced a manual reauth regardless of usage.
   - Fix: persist browser state after every successful query (best-effort;
     a save failure does not drop the captured answer).

Verified: full source-grounded answers returned; validate now reports
STALE correctly; state.json mtime advances on each successful ask.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant