Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/dupehound.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: dupehound

on:
pull_request:
paths:
- 'src/**'
- 'tests/**'
push:
branches: [main]
paths:
- 'src/**'
- 'tests/**'

permissions:
contents: read

jobs:
check:
name: Block new duplicates
runs-on: ubuntu-latest
timeout-minutes: 5
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- name: Install dupehound
run: |
curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv dupehound /usr/local/bin/
- name: Block new duplicates vs base
env:
PR_BASE: ${{ github.event.pull_request.base.ref }}
run: |
if [ -n "$PR_BASE" ]; then
dupehound check --diff "origin/$PR_BASE" .
else
dupehound check --diff HEAD~1 .
fi

scan:
name: Repo slop score
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install dupehound
run: |
curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv dupehound /usr/local/bin/
- name: Scan
run: |
dupehound scan . | tee /tmp/dh-scan.txt
SCORE=$(grep -oE 'SLOP SCORE[[:space:]]+[0-9.]+%' /tmp/dh-scan.txt | head -1 | grep -oE '[0-9.]+%' || echo "n/a")
echo "## dupehound slop score" >> "$GITHUB_STEP_SUMMARY"
echo "**${SCORE}**" >> "$GITHUB_STEP_SUMMARY"
22 changes: 1 addition & 21 deletions src/browser_harness/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,7 @@
from pathlib import Path

from . import _ipc as ipc


def _load_env():
repo_root = Path(__file__).resolve().parents[2]
workspace = Path(os.environ.get("BH_AGENT_WORKSPACE", repo_root / "agent-workspace")).expanduser()
for p in (repo_root / ".env", workspace / ".env"):
if not p.exists():
continue
_load_env_file(p)


def _load_env_file(p):
for line in p.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))


_load_env()
from .helpers import _load_env, _load_env_file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid importing helper side effects from admin

Importing .helpers here immediately runs its module-level _load_agent_helpers(), so agent-workspace/agent_helpers.py is executed while browser_harness.admin is only partially initialized. If a task helper imports an admin API such as from browser_harness.admin import start_remote_daemon, the CLI now fails with a circular-import ImportError before any command runs; this worked before because run.py loaded admin before loading helpers. Move the env loader to a side-effect-free module or defer agent-helper loading to the CLI helper path.

Useful? React with 👍 / 👎.


NAME = os.environ.get("BU_NAME", "default")
BU_API = "https://api.browser-use.com/api/v3"
Expand Down
23 changes: 2 additions & 21 deletions src/browser_harness/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,9 @@
from pathlib import Path

from . import _ipc as ipc
from cdp_use.client import CDPClient


def _load_env():
repo_root = Path(__file__).resolve().parents[2]
workspace = Path(os.environ.get("BH_AGENT_WORKSPACE", repo_root / "agent-workspace")).expanduser()
for p in (repo_root / ".env", workspace / ".env"):
if not p.exists():
continue
_load_env_file(p)

from .helpers import _load_env, _load_env_file

def _load_env_file(p):
for line in p.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))


_load_env()
from cdp_use.client import CDPClient

NAME = os.environ.get("BU_NAME", "default")
SOCK = ipc.sock_addr(NAME)
Expand Down
Loading