-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathrun.py
More file actions
129 lines (113 loc) · 4.23 KB
/
Copy pathrun.py
File metadata and controls
129 lines (113 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import os, sys, urllib.request
# Windows default terminal encoding is often cp1252, which can't encode the 🐴 marker
# helpers prepend to tab titles (or anything else outside Latin-1). Force UTF-8
# so `print(page_info())` doesn't UnicodeEncodeError on Windows. Issue #124(4), #359.
for _stream in (sys.stdout, sys.stderr):
try: _stream.reconfigure(encoding="utf-8", errors="replace")
except Exception: pass
from .admin import (
_version,
NAME,
daemon_alive,
ensure_daemon,
list_cloud_profiles,
list_local_profiles,
print_update_banner,
restart_daemon,
run_doctor,
run_doctor_fix_snap,
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:
browser-harness <<'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 doctor same as --doctor
browser-harness doctor --fix-snap print how to fix Snap Chromium blocking CDP (Linux)
browser-harness --update [-y] pull the latest version (agents: pass -y)
browser-harness --reload stop the daemon so next call picks up code changes
"""
USAGE = """Usage:
browser-harness <<'PY'
print(page_info())
PY
"""
# Probe /json/version (not a bare TCP connect) so a non-Chrome process bound to
# 9222/9223 doesn't masquerade as Chrome and skip the cloud bootstrap. Mirrors
# daemon.py's fallback probe.
def _local_chrome_listening():
for port in (9222, 9223):
try:
urllib.request.urlopen(f"http://127.0.0.1:{port}/json/version", timeout=0.3).close()
return True
except OSError: pass
return False
# BU_CDP_URL / BU_CDP_WS are documented to override local Chrome discovery
# (install.md:58-59), so they must also block cloud auto-bootstrap. Without this
# guard, start_remote_daemon() in admin.py overwrites BU_CDP_WS in the daemon
# env with a cloud WebSocket URL, silently replacing the user's explicit endpoint
# *and* billing them for a cloud browser they never asked for.
def _explicit_cdp_configured():
return bool(os.environ.get("BU_CDP_URL") or os.environ.get("BU_CDP_WS"))
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] == "doctor":
rest = args[1:]
if rest == ["--fix-snap"]:
sys.exit(run_doctor_fix_snap())
if rest:
print("usage: browser-harness doctor [--fix-snap]", file=sys.stderr)
sys.exit(2)
sys.exit(run_doctor())
if args and args[0] == "--update":
yes = any(a in {"-y", "--yes"} for a in args[1:])
sys.exit(run_update(yes=yes))
if args and args[0] == "--reload":
restart_daemon()
print("daemon stopped — will restart fresh on next call")
return
if args and args[0] == "--debug-clicks":
os.environ["BH_DEBUG_CLICKS"] = "1"
args = args[1:]
if not args and not sys.stdin.isatty():
code = sys.stdin.read()
if not code.strip():
sys.exit(USAGE)
else:
sys.exit(USAGE)
print_update_banner()
# Auto-bootstrap a cloud browser is opt-in via BU_AUTOSPAWN — BROWSER_USE_API_KEY alone
# is not enough, since the key is commonly set for unrelated reasons (profile sync,
# cloud API calls, parent agents managing their own session). An explicit BU_CDP_URL
# or BU_CDP_WS also blocks the spawn so we honour the precedence install.md promises.
if (
not daemon_alive()
and not _local_chrome_listening()
and not _explicit_cdp_configured()
and os.environ.get("BROWSER_USE_API_KEY")
and os.environ.get("BU_AUTOSPAWN")
):
start_remote_daemon(NAME)
ensure_daemon()
exec(code, globals())
if __name__ == "__main__":
main()