Repository navigation
fix(targets): read tab URLs from Target.getTargets, not the renderer - #1
Merged
Merged
Conversation
Tab enumeration read each tab's URL via `await tab.current_url`, which evaluates `location.href` inside the page. Browsers that sleep background tabs (Wavebox, Edge, Chrome Memory Saver) discard the renderer while leaving the target attachable, so that evaluate is accepted and never answered — it burns the full 60s per-command timeout, sequentially, for every sleeping tab before selection can reach a live one. Measured on a Wavebox with 36 tabs, 11 of them slept: `tabs list` and `session start --tab-url` never completed (~11 min of stacked timeouts); `--tab N` hit the same sweep. Both now return in ~0.5s. CDP already reports url and title in TargetInfo, so one browser-level Target.getTargets call replaces N renderer round-trips — faster in the healthy case too, where it was N sequential evaluates. - targets: add target_info_map / tab_url / tab_title / visible_tabs_with_urls; resolve from TargetInfo with a bounded 5s in-page fallback for targets getTargets doesn't report - session, async_runner, commands.tabs: take URLs from the enumeration instead of re-reading each tab Tabs with no resolvable URL are still dropped, so --tab N indices keep their meaning. Sleeping tabs are not in that category — CDP reports their URL, so they stay listed and selectable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
uv keys its build cache on the version string, so with __version__ unchanged `uv tool install --force .` re-installs the previously cached wheel. Working-tree edits then never reach the installed console script and it keeps raising from code that is already fixed — which is how a mid-edit snapshot of commands/tabs.py (visible_tabs used but no longer imported) stayed installed and broke `tabs close` / `tabs focus` long after the tree was correct. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The repo keeps an [Unreleased] section between releases; this branch shipped a user-visible fix without one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Tab enumeration read each tab's URL via
await tab.current_url, which evaluateslocation.hrefinside the page. Browsers that sleep background tabs (Wavebox, Edge, Chrome Memory Saver) discard the renderer while leaving the target attachable — so that evaluate is accepted and never answered. It burns the full 60s per-command timeout, sequentially, for every sleeping tab before selection can reach a live one.Measured on a Wavebox with 36 tabs, 11 of them slept:
tabs listandsession start --tab-urlnever completed (~11 min of stacked timeouts);--tab Nhit the same sweep.Fix
CDP already reports
urlandtitleinTargetInfo, so one browser-levelTarget.getTargetscall replaces N renderer round-trips — faster in the healthy case too, where it was N sequential evaluates.pydoll_cli/targets.pyhelpers:target_info_map,tab_url,tab_title,visible_tabs_with_urls. In-page reads survive only as a time-boxed (5s) fallback for a targetTarget.getTargetsdidn't report.async_runner,session, andcommands/tabsall route through them, sotabs listindices stay in sync with what--tab Nresolves to.Both paths now return in ~0.5s.
Tests
tests/unit/test_tab_filtering.pygains a_SleepingTabfake whosecurrent_url/titlesleep for an hour and assert-fail if ever awaited, plus a_run_boundedhelper so a regression fails instead of hanging the suite. Five new cases covervisible_tabs,--tab-urlmatching a slept tab,--tab-urlreaching a live tab behind a slept one,_find_tab_matching, andtabs listoutput.289 unit tests pass; ruff, ruff format, and mypy clean.
Also
A README note in Development: uv keys its build cache on the version string, so with
__version__unchangeduv tool install --force .re-installs the previously cached wheel and working-tree edits silently never ship. Useuv cache clean pydoll-cli && uv tool install --force --no-cache .. This bit during development of this very fix — a mid-edit snapshot ofcommands/tabs.pystayed installed and kept raisingNameError: visible_tabsfromtabs close/tabs focuslong after the tree was correct.🤖 Generated with Claude Code