Compare commits

..
Author SHA1 Message Date
Ahmed Allam b0f5c102f9 chore(container): drop the idle-timeout comment 2026-08-09 23:38:36 +00:00
Ahmed Allam 5d6b5fdbd1 chore: trim the idle-timeout comment; show the named-session pattern once 2026-08-09 23:38:14 +00:00
Ahmed AllamandDevin AI a55245ffcc docs(prompts,skills): tell agents to own a browser session, not share one
A concurrent agent navigating the default session invalidates another
agent's page and refs, so a named session is required for correctness, not
just for separate cookies. Bound the cost with one session per agent, an
explicit close, and the idle timeout.
2026-08-09 23:33:04 +00:00
Ahmed AllamandDevin AI 55e15f89fd fix(container): reclaim abandoned browser sessions
Each agent-browser session is a separate Chromium (~340 MB, ~12 processes)
and nothing owns a browser's lifecycle, so finished, stopped and crashed
agents strand theirs for the life of the sandbox. Enable the daemon's idle
timeout and stop telling agents each of them has its own browser.
2026-08-09 23:33:04 +00:00
6 changed files with 8 additions and 69 deletions
-14
View File
@@ -118,20 +118,6 @@ ENV AGENT_BROWSER_USER_AGENT="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36
ENV AGENT_BROWSER_ARGS="--disable-blink-features=AutomationControlled,--no-first-run,--no-default-browser-check,--lang=en-US"
ENV AGENT_BROWSER_SCREENSHOT_DIR=/workspace/.agent-browser-screenshots
ENV AGENT_BROWSER_IDLE_TIMEOUT_MS=180000
USER root
RUN set -eu; \
{ \
for var in AGENT_BROWSER_EXECUTABLE_PATH AGENT_BROWSER_USER_AGENT \
AGENT_BROWSER_ARGS AGENT_BROWSER_SCREENSHOT_DIR \
AGENT_BROWSER_IDLE_TIMEOUT_MS; do \
eval "value=\${$var}"; \
printf 'export %s="${%s:-%s}"\n' "$var" "$var" "$value"; \
done; \
} > /tmp/agent-browser.sh; \
install -m 0644 /tmp/agent-browser.sh /etc/profile.d/agent-browser.sh; \
rm /tmp/agent-browser.sh; \
env -i bash -lc 'test "${AGENT_BROWSER_IDLE_TIMEOUT_MS}" = "180000"'
USER pentester
RUN /home/pentester/.npm-global/bin/agent-browser doctor --offline --quick
RUN set -eux; \
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "strix-agent"
version = "1.5.3"
version = "1.5.2"
description = "Open-source AI Hackers for your apps"
readme = "README.md"
license = "Apache-2.0"
+5 -9
View File
@@ -652,31 +652,27 @@ def _install_openrouter_stream_cost_capture() -> None:
litellm.OpenrouterConfig = _StrixOpenrouterConfig # type: ignore[misc]
OPENROUTER_ATTRIBUTION_HEADERS = {
_OPENROUTER_ATTRIBUTION_HEADERS = {
"HTTP-Referer": "https://strix.ai",
"X-Title": "Strix",
"X-OpenRouter-Categories": "cli-agent",
}
def is_openrouter_model(model_name: str | None) -> bool:
return bool(model_name) and "openrouter/" in (model_name or "").strip().lower()
def _configure_openrouter_attribution(model_name: str | None) -> None:
import litellm
current: object = litellm.headers
existing: dict[str, str] = current if isinstance(current, dict) else {}
if not is_openrouter_model(model_name):
if any(key in existing for key in OPENROUTER_ATTRIBUTION_HEADERS):
if not model_name or "openrouter/" not in model_name.strip().lower():
if any(key in existing for key in _OPENROUTER_ATTRIBUTION_HEADERS):
remaining = {
k: v for k, v in existing.items() if k not in OPENROUTER_ATTRIBUTION_HEADERS
k: v for k, v in existing.items() if k not in _OPENROUTER_ATTRIBUTION_HEADERS
}
litellm.headers = remaining or None # type: ignore[assignment]
return
litellm.headers = {**existing, **OPENROUTER_ATTRIBUTION_HEADERS} # type: ignore[assignment]
litellm.headers = {**existing, **_OPENROUTER_ATTRIBUTION_HEADERS} # type: ignore[assignment]
def _configure_extra_headers(llm: LlmSettings) -> None:
+1 -15
View File
@@ -10,12 +10,10 @@ from openai.types.shared import Reasoning
from strix.config.models import (
DEFAULT_MODEL_RETRY,
OPENROUTER_ATTRIBUTION_HEADERS,
bedrock_route_supports_prompt_caching,
is_bedrock_route,
is_claude_model,
is_known_openai_bare_model,
is_openrouter_model,
model_supports_reasoning,
request_timeout_extra_args,
)
@@ -205,13 +203,12 @@ def make_model_settings(
extra_headers: dict[str, str] | None = None,
has_tools: bool = True,
) -> ModelSettings:
headers = _request_headers(model_name, extra_headers)
model_settings = ModelSettings(
parallel_tool_calls=False if has_tools else None,
retry=DEFAULT_MODEL_RETRY,
include_usage=True,
extra_args=request_timeout_extra_args(request_timeout),
extra_headers=headers,
extra_headers=dict(extra_headers) if extra_headers else None,
)
if (
reasoning_effort is not None
@@ -234,17 +231,6 @@ def make_model_settings(
return model_settings
def _request_headers(
model_name: str, extra_headers: dict[str, str] | None
) -> dict[str, str] | None:
headers: dict[str, str] = {}
if is_openrouter_model(model_name):
headers.update(OPENROUTER_ATTRIBUTION_HEADERS)
if extra_headers:
headers.update(extra_headers)
return headers or None
def _reasoning_settings(
effort: ReasoningEffort,
extra_args: dict[str, Any] | None,
-29
View File
@@ -361,32 +361,3 @@ def test_make_model_settings_timeout_survives_reasoning_resolve() -> None:
assert settings.extra_args is not None
assert settings.extra_args["timeout"] == 120.0
def test_openrouter_attribution_rides_on_the_request_headers() -> None:
# litellm.headers is ignored once a request carries any header of its own,
# so the attribution must be part of the per-request headers.
headers = make_model_settings(
None, model_name="openrouter/anthropic/claude-sonnet-4-5"
).extra_headers
assert headers == {
"HTTP-Referer": "https://strix.ai",
"X-Title": "Strix",
"X-OpenRouter-Categories": "cli-agent",
}
def test_openrouter_attribution_absent_for_other_providers() -> None:
assert make_model_settings(None, model_name="anthropic/claude-sonnet-4-5").extra_headers is None
def test_user_headers_override_openrouter_attribution() -> None:
headers = make_model_settings(
None,
model_name="openrouter/anthropic/claude-sonnet-4-5",
extra_headers={"X-Title": "Custom", "X-Tenant": "acme"},
).extra_headers
assert headers is not None
assert headers["X-Title"] == "Custom"
assert headers["X-Tenant"] == "acme"
assert headers["HTTP-Referer"] == "https://strix.ai"
Generated
+1 -1
View File
@@ -2378,7 +2378,7 @@ wheels = [
[[package]]
name = "strix-agent"
version = "1.5.3"
version = "1.5.2"
source = { editable = "." }
dependencies = [
{ name = "caido-sdk-client" },