browser-use--browser-harness
ba8b22f1ff
* fix(run): pass globals to exec so comprehensions resolve free vars
exec(sys.stdin.read()) inside main() passes different dicts for globals
and locals. Python comprehensions and generator expressions compile to a
nested function whose free-variable lookups can only see the globals
dict, so code like
for it in items:
low = it['text'].lower()
hit = any(k in low for k in KEYS) # NameError: 'low'
fails at module level under exec. `low` is stored in the exec locals
dict which the generator's implicit function cannot see.
Passing globals() as the only extra arg makes exec use the same dict
for both globals and locals, and comprehensions resolve cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(skill): eyeball click coords from screenshots; no getBoundingClientRect
The previous Clicking bullet said "screenshot -> look -> click(x,y)" but
did not rule out roundtripping through js("...getBoundingClientRect()")
to compute coords. Agents coming from Playwright / Selenium habits tend
to locate-first-click-second even when the screenshot already shows the
target, which is slower and more brittle (hidden inputs placed at
x=-9999, CSS-transformed elements, pseudo-elements) than just reading
the pixel off the image.
Rewrite the bullet to explicitly suppress that reflex and scope the
DOM-fallback to elements with no visible geometry. Also replace the
loose "compositor level" phrasing with the actual mechanism: Chrome's
browser-process hit-testing, which is why clicks pass through iframes
/ shadow DOM / cross-origin without extra work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
68 行
1.7 KiB
Python
68 行
1.7 KiB
Python
import sys
|
|
|
|
from admin import (
|
|
_version,
|
|
ensure_daemon,
|
|
list_cloud_profiles,
|
|
list_local_profiles,
|
|
print_update_banner,
|
|
restart_daemon,
|
|
run_doctor,
|
|
run_setup,
|
|
run_update,
|
|
start_remote_daemon,
|
|
stop_remote_daemon,
|
|
sync_local_profile,
|
|
)
|
|
from helpers import *
|
|
|
|
HELP = """Browser Harness
|
|
|
|
Read SKILL.md for the default workflow and examples.
|
|
|
|
Typical usage:
|
|
uv run bh <<'PY'
|
|
ensure_real_tab()
|
|
print(page_info())
|
|
PY
|
|
|
|
Helpers are pre-imported. The daemon auto-starts and connects to the running browser.
|
|
|
|
Commands:
|
|
browser-harness --version print the installed version
|
|
browser-harness --doctor diagnose install, daemon, and browser state
|
|
browser-harness --setup interactively attach to your running browser
|
|
browser-harness --update [-y] pull the latest version (agents: pass -y)
|
|
"""
|
|
|
|
|
|
def main():
|
|
args = sys.argv[1:]
|
|
if args and args[0] in {"-h", "--help"}:
|
|
print(HELP)
|
|
return
|
|
if args and args[0] == "--version":
|
|
print(_version() or "unknown")
|
|
return
|
|
if args and args[0] == "--doctor":
|
|
sys.exit(run_doctor())
|
|
if args and args[0] == "--setup":
|
|
sys.exit(run_setup())
|
|
if args and args[0] == "--update":
|
|
yes = any(a in {"-y", "--yes"} for a in args[1:])
|
|
sys.exit(run_update(yes=yes))
|
|
if sys.stdin.isatty():
|
|
sys.exit(
|
|
"browser-harness reads Python from stdin. Use:\n"
|
|
" browser-harness <<'PY'\n"
|
|
" print(page_info())\n"
|
|
" PY"
|
|
)
|
|
print_update_banner()
|
|
ensure_daemon()
|
|
exec(sys.stdin.read(), globals())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|