Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b880ed4
feat: browser-use tool initial migration
shanyu-strix Mar 11, 2026
d8b2a18
simplify entrypoint
shanyu-strix Mar 11, 2026
428ae57
fix greptile
shanyu-strix Mar 11, 2026
0e4307d
harden: authentication for cdp
shanyu-strix Mar 11, 2026
bbf6e08
debug: disable
shanyu-strix Mar 11, 2026
f99b7eb
Refines browser state handling and healthcheck
shanyu-strix Mar 11, 2026
9fc09e8
fix: improve support for non-vision models
shanyu-strix Mar 12, 2026
550690e
remove built-in llm, use langchain
shanyu-strix Mar 12, 2026
f3bb259
refactor
shanyu-strix Mar 13, 2026
79890b7
Update renderer
shanyu-strix Mar 13, 2026
4c2b368
small changes (QOL)
shanyu-strix Mar 13, 2026
3718943
qol
shanyu-strix Mar 13, 2026
9836e3f
streamline into tool-server
shanyu-strix Mar 13, 2026
d9d6fb2
metadata + cleanup some actions
shanyu-strix Mar 13, 2026
b6695cd
remove slop comments
shanyu-strix Mar 13, 2026
26a5586
qol on chat browser
shanyu-strix Mar 13, 2026
f35f287
Update docker_runtime.py
shanyu-strix Mar 13, 2026
e461905
prevent browseruse from killing cdp connection
shanyu-strix Mar 13, 2026
1ffcbcf
slim down browser-manager
shanyu-strix Mar 14, 2026
f91c9ef
important notes
shanyu-strix Mar 14, 2026
d5344ad
simplify actions, remove ones that cannot be used
shanyu-strix Mar 14, 2026
c4c953e
remove upload files
shanyu-strix Mar 14, 2026
b434d87
remove docker entrypoint slop
shanyu-strix Mar 14, 2026
57ddce1
slim down cdp functionality
shanyu-strix Mar 14, 2026
d80578c
suppress cdp + add logging
shanyu-strix Mar 14, 2026
c023468
cleanup renderer
shanyu-strix Mar 16, 2026
74061b7
remove file name parameter from schema definition
shanyu-strix Mar 16, 2026
eccc62b
Update schema with correct(er) names
shanyu-strix Mar 16, 2026
65fd716
base integration tests
shanyu-strix Mar 16, 2026
37942d0
cleanup logging in browser_actions (to test)
shanyu-strix Mar 16, 2026
3237661
add run test
shanyu-strix Mar 16, 2026
c7eb83b
comment cleanup
shanyu-strix Mar 16, 2026
48ea4d1
fix: properly isolate context
shanyu-strix Mar 17, 2026
0a5d0f2
cleanup + concurrency test
shanyu-strix Mar 17, 2026
3982d50
Lean up implementation
shanyu-strix Mar 17, 2026
6ae56c0
more extensive tests for edge cases
shanyu-strix Mar 17, 2026
940a23c
Update test_browser_isolation.py
shanyu-strix Mar 17, 2026
7d44be7
Improve concurrency test
shanyu-strix Mar 17, 2026
88a8232
Fix browser review regressions
0xallam Mar 20, 2026
32a4397
Fix CDP proxy and bump sandbox image
0xallam Mar 20, 2026
7e63b24
fix: debug + some rebase
shanyu-strix Mar 20, 2026
59040ee
feat: add feature flag for browser run tool
shanyu-strix Mar 23, 2026
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
17 changes: 14 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help install dev-install format lint type-check test test-cov clean pre-commit setup-dev
.PHONY: help install dev-install format lint type-check test test-cov clean pre-commit setup-dev integration

help:
@echo "Available commands:"
Expand All @@ -14,8 +14,10 @@ help:
@echo " check-all - Run all code quality checks"
@echo ""
@echo "Testing:"
@echo " test - Run tests with pytest"
@echo " test-cov - Run tests with coverage reporting"
@echo " test - Run tests with pytest"
@echo " test-cov - Run tests with coverage reporting"
@echo " integration - Run integration tests (verbose)"
@echo " PRETTY=1 integration - Run integration tests (clean TUI)"
@echo ""
@echo "Development:"
@echo " pre-commit - Run pre-commit hooks on all files"
Expand Down Expand Up @@ -70,6 +72,15 @@ test-cov:
@echo "✅ Tests with coverage complete!"
@echo "📊 Coverage report generated in htmlcov/"

integration:
ifdef PRETTY
poetry run pytest tests/integration/ -m integration --no-cov --no-header -q --tb=no -p no:logging -s --pretty
else
@echo "🧪 Running integration tests..."
poetry run pytest tests/integration/ -v -s --log-cli-level=INFO -m integration --no-cov
@echo "✅ Integration tests complete!"
endif

pre-commit:
@echo "🔧 Running pre-commit hooks..."
uv run pre-commit run --all-files
Expand Down
6 changes: 5 additions & 1 deletion containers/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ RUN echo 'export PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/p

USER root
COPY containers/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
COPY containers/healthcheck.sh /usr/local/bin/healthcheck.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh /usr/local/bin/healthcheck.sh

HEALTHCHECK --interval=15s --timeout=5s --start-period=60s --retries=3 \
CMD healthcheck.sh

USER pentester
WORKDIR /workspace
Expand Down
40 changes: 39 additions & 1 deletion containers/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,41 @@ sudo -u pentester certutil -N -d sql:/home/pentester/.pki/nssdb --empty-password
sudo -u pentester certutil -A -n "Testing Root CA" -t "C,," -i /app/certs/ca.crt -d sql:/home/pentester/.pki/nssdb
echo "✅ CA added to browser trust store"

# Chromium binds CDP to 127.0.0.1, tool server proxies WS via /cdp/ws
CDP_INTERNAL_PORT=19222
CHROMIUM_BIN=$(find /usr/lib/chromium* /usr/bin -name "chromium" -o -name "chromium-browser" -o -name "chrome" 2>/dev/null | head -1)
[ -z "$CHROMIUM_BIN" ] && CHROMIUM_BIN=$(find /home/pentester/.cache/ms-playwright -name "chrome" -type f 2>/dev/null | head -1)

if [ -n "$CHROMIUM_BIN" ]; then
rm -f /tmp/chromium-profile/SingletonLock /tmp/chromium-profile/SingletonCookie /tmp/chromium-profile/SingletonSocket 2>/dev/null || true

echo "Launching Chromium with CDP on internal port $CDP_INTERNAL_PORT..."
sudo -u pentester "$CHROMIUM_BIN" \
--headless \
--no-sandbox \
--disable-dev-shm-usage \
--disable-gpu \
--remote-debugging-port="$CDP_INTERNAL_PORT" \
--proxy-server="http://127.0.0.1:${CAIDO_PORT}" \
--ignore-certificate-errors \
--user-data-dir=/tmp/chromium-profile \
> /tmp/chromium.log 2>&1 &
CHROMIUM_PID=$!
echo "Started Chromium with PID $CHROMIUM_PID"

echo "Waiting for Chromium CDP to be ready..."
for i in {1..20}; do
if curl -s "http://127.0.0.1:${CDP_INTERNAL_PORT}/json/version" | grep -q "webSocketDebuggerUrl"; then
echo "Chromium CDP ready on port $CDP_INTERNAL_PORT (attempt $i)"
break
fi
[ $i -eq 20 ] && echo "WARNING: Chromium CDP did not become ready within 20s"
sleep 1
done
else
echo "WARNING: Chromium binary not found, browser CDP will not be available"
fi

echo "Starting tool server..."
cd /app
export PYTHONPATH=/app
Expand All @@ -163,7 +198,10 @@ sudo -E -u pentester \
--token="$TOOL_SERVER_TOKEN" \
--host=0.0.0.0 \
--port="$TOOL_SERVER_PORT" \
--timeout="$TOOL_SERVER_TIMEOUT" > "$TOOL_SERVER_LOG" 2>&1 &
--timeout="$TOOL_SERVER_TIMEOUT" \
--cdp-upstream="http://127.0.0.1:$CDP_INTERNAL_PORT" > "$TOOL_SERVER_LOG" 2>&1 &

TOOL_SERVER_PID=$!

for i in {1..10}; do
if curl -s "http://127.0.0.1:$TOOL_SERVER_PORT/health" | grep -q '"status":"healthy"'; then
Expand Down
31 changes: 31 additions & 0 deletions containers/healthcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# Healthcheck script for the strix sandbox container.
# Checks: tool server, Caido proxy, Chromium CDP.
# Exit 0 = healthy, exit 1 = unhealthy.

set -e

TOOL_SERVER_PORT="${TOOL_SERVER_PORT:-48081}"
CAIDO_PORT=48080

# 1. Tool server must respond healthy
if ! curl -sf --max-time 3 -H "Authorization: Bearer ${TOOL_SERVER_TOKEN}" "http://127.0.0.1:${TOOL_SERVER_PORT}/health" | grep -q '"status":"healthy"'; then
echo "UNHEALTHY: tool server not responding on port ${TOOL_SERVER_PORT}"
exit 1
fi

# 2. Caido proxy must be reachable. A bare /graphql/ probe may legitimately return
# 400, which the entrypoint already treats as ready.
if ! curl -s -o /dev/null -w "%{http_code}" --max-time 3 "http://127.0.0.1:${CAIDO_PORT}/graphql/" | grep -qE "^(200|400)$"; then
echo "UNHEALTHY: Caido proxy not responding on port ${CAIDO_PORT}"
exit 1
fi

# 3. Chromium CDP must be reachable (probe internal port directly — no auth needed inside the container)
if ! curl -sf --max-time 3 "http://127.0.0.1:${CDP_INTERNAL_PORT:-19222}/json/version" | grep -q "webSocketDebuggerUrl"; then
echo "UNHEALTHY: Chromium CDP not responding on internal port ${CDP_INTERNAL_PORT:-19222}"
exit 1
fi

echo "healthy"
exit 0
28 changes: 24 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ classifiers = [
"Programming Language :: Python :: 3.14",
]
dependencies = [
"litellm[proxy]>=1.81.1,<1.82.0",
"litellm>=1.81.1",
"tenacity>=9.0.0",
"pydantic[email]>=2.11.3",
"rich",
Expand All @@ -46,6 +46,7 @@ dependencies = [
"opentelemetry-exporter-otlp-proto-http>=1.40.0",
"scrubadub>=2.0.1",
"defusedxml>=0.7.1",
"browser-use>=0.12.2",
]

[project.scripts]
Expand Down Expand Up @@ -138,14 +139,25 @@ module = [
"opentelemetry.*",
"scrubadub.*",
"traceloop.*",
"browser_use.*",
"pytest_check.*",
"cdp_use.*",
"aiohttp.*",
"websockets.*",
]
ignore_missing_imports = true

# We need to override this for extending LLM base models
[[tool.mypy.overrides]]
module = ["strix.tools.browser.litellm.*"]
disallow_subclassing_any = false

Comment thread
0xallam marked this conversation as resolved.
# Relax strict rules for test files (pytest decorators are not fully typed)
[[tool.mypy.overrides]]
module = ["tests.*"]
disallow_untyped_decorators = false
disallow_untyped_defs = false
disallow_untyped_calls = false

# ============================================================================
# Ruff Configuration (Fast Python Linter & Formatter)
Expand Down Expand Up @@ -232,10 +244,13 @@ ignore = [

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
"S106", # Possible hardcoded password
"S108", # Possible insecure usage of temporary file/directory
"ARG001", # Unused function argument
"S106", # Possible hardcoded password
"S108", # Possible insecure usage of temporary file/directory
"S603", # subprocess call with untrusted input
"S607", # Partial executable path
"ARG001", # Unused function argument
"PLR2004", # Magic value used in comparison
"PLW0603", # Global statement (acceptable for test UI state)
]
"strix/tools/**/*.py" = [
"ARG001", # Unused function argument (tools may have unused args for interface consistency)
Expand Down Expand Up @@ -342,6 +357,11 @@ python_files = ["test_*.py", "*_test.py"]
python_functions = ["test_*"]
python_classes = ["Test*"]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
markers = [
"integration: end-to-end tests requiring Docker and network access",
"browsers(n): launch n isolated browser sessions for the test",
]

[tool.coverage.run]
source = ["strix"]
Expand Down
1 change: 1 addition & 0 deletions strix/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Config:
# Tool & Feature Configuration
perplexity_api_key = None
strix_disable_browser = "false"
strix_enable_browser_agent = "false"

# Runtime Configuration
strix_image = "ghcr.io/usestrix/strix-sandbox:0.1.13"
Expand Down
14 changes: 13 additions & 1 deletion strix/interface/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,17 @@
from strix.telemetry.tracer import get_global_tracer # noqa: E402


logging.getLogger().setLevel(logging.ERROR)
def configure_logging() -> None:
log_dir = Path("strix_runs")
log_dir.mkdir(exist_ok=True)

file_handler = logging.FileHandler(log_dir / "strix.log")
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s"))

root = logging.getLogger()
root.setLevel(logging.INFO)
root.handlers = [file_handler]


def validate_environment() -> None: # noqa: PLR0912, PLR0915
Expand Down Expand Up @@ -541,6 +551,8 @@ def main() -> None: # noqa: PLR0912, PLR0915
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

configure_logging()

args = parse_arguments()

if args.config:
Expand Down
Loading