mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-04-29 03:00:45 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a815ad2c10 |
@@ -72,7 +72,7 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: "pip"
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: "pip"
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: "pip"
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
name: PR Review by OpenHands
|
||||
|
||||
on:
|
||||
# Use pull_request for same-repo PRs so workflow changes can self-verify in PRs.
|
||||
# TEMPORARY MITIGATION (Clinejection hardening)
|
||||
#
|
||||
# We temporarily avoid `pull_request_target` here. We'll restore it after the PR review
|
||||
# workflow is fully hardened for untrusted execution.
|
||||
pull_request:
|
||||
types: [opened, ready_for_review, labeled, review_requested]
|
||||
# Use pull_request_target for fork PRs.
|
||||
# The bot token used here is intentionally scoped to PR review operations,
|
||||
# so the remaining blast radius is bounded even though PR content is untrusted.
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review, labeled, review_requested]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -18,33 +16,13 @@ permissions:
|
||||
|
||||
jobs:
|
||||
pr-review:
|
||||
# Run on same-repo PRs via pull_request and on fork PRs via pull_request_target.
|
||||
# Trigger when one of the following conditions is met:
|
||||
# 1. A new non-draft PR is opened by a non-first-time contributor, OR
|
||||
# 2. A draft PR is converted to ready for review by a non-first-time contributor, OR
|
||||
# 3. The 'review-this' label is added, OR
|
||||
# 4. openhands-agent or all-hands-bot is requested as a reviewer
|
||||
# Note: FIRST_TIME_CONTRIBUTOR and NONE PRs require manual trigger via label/reviewer request.
|
||||
# Trigger logic:
|
||||
# 1. Route same-repo PRs through `pull_request` and fork PRs through `pull_request_target`
|
||||
# 2. Auto-trigger on `opened` / `ready_for_review` for non-first-time contributors
|
||||
# 3. Always allow manual triggers via `review-this` or reviewer request
|
||||
# The author association check is duplicated intentionally for both
|
||||
# auto-triggered actions (`opened` and `ready_for_review`).
|
||||
# Note: fork PRs will not have access to repository secrets under `pull_request`.
|
||||
# Skip forks to avoid noisy failures until we restore a hardened `pull_request_target` flow.
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository &&
|
||||
(
|
||||
(
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
) ||
|
||||
(
|
||||
github.event_name == 'pull_request_target' &&
|
||||
github.event.pull_request.head.repo.full_name != github.repository
|
||||
)
|
||||
) &&
|
||||
(
|
||||
(github.event.action == 'opened' && github.event.pull_request.draft == false && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') ||
|
||||
(github.event.action == 'ready_for_review' && github.event.pull_request.author_association != 'FIRST_TIME_CONTRIBUTOR' && github.event.pull_request.author_association != 'NONE') ||
|
||||
(github.event.action == 'opened' && github.event.pull_request.draft == false) ||
|
||||
github.event.action == 'ready_for_review' ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'review-this') ||
|
||||
(
|
||||
github.event.action == 'review_requested' &&
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
- name: Install poetry via pipx
|
||||
run: pipx install poetry
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: "poetry"
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
- name: Install poetry via pipx
|
||||
run: pipx install poetry
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: "poetry"
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
|| (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-cli') && !startsWith(github.ref, 'refs/tags/cloud-'))
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
- name: Install Poetry
|
||||
|
||||
@@ -1304,10 +1304,7 @@ class LiveStatusAppConversationService(AppConversationServiceBase):
|
||||
plan_path = self._compute_plan_path(project_dir, git_provider)
|
||||
tools = get_planning_tools(plan_path=plan_path)
|
||||
else:
|
||||
tools = get_default_tools(
|
||||
enable_browser=True,
|
||||
enable_sub_agents=user.agent_settings.enable_sub_agents,
|
||||
)
|
||||
tools = get_default_tools(enable_browser=True)
|
||||
|
||||
# --- build AgentSettings and create agent ---------------------------
|
||||
from fastmcp.mcp_config import MCPConfig
|
||||
|
||||
@@ -71,7 +71,7 @@ def get_agent_server_image() -> str:
|
||||
|
||||
# Prefixes for environment variables that should be auto-forwarded to agent-server
|
||||
# These are typically configuration variables that affect the agent's behavior
|
||||
AUTO_FORWARD_PREFIXES = ('LLM_', 'LMNR_')
|
||||
AUTO_FORWARD_PREFIXES = ('LLM_',)
|
||||
|
||||
|
||||
def get_agent_server_env() -> dict[str, str]:
|
||||
@@ -80,10 +80,9 @@ def get_agent_server_env() -> dict[str, str]:
|
||||
This function combines two sources of environment variables:
|
||||
|
||||
1. **Auto-forwarded variables**: Environment variables with certain prefixes
|
||||
(e.g., LLM_*, LMNR_*) are automatically forwarded to the agent-server container.
|
||||
(e.g., LLM_*) are automatically forwarded to the agent-server container.
|
||||
This ensures that LLM configuration like timeouts and retry settings
|
||||
work correctly in the two-container V1 architecture, as well as
|
||||
Laminar monitoring/analytics configuration.
|
||||
work correctly in the two-container V1 architecture.
|
||||
|
||||
2. **Explicit overrides via OH_AGENT_SERVER_ENV**: A JSON string that allows
|
||||
setting arbitrary environment variables in the agent-server container.
|
||||
@@ -91,7 +90,6 @@ def get_agent_server_env() -> dict[str, str]:
|
||||
|
||||
Auto-forwarded prefixes:
|
||||
- LLM_* : LLM configuration (timeout, retries, model settings, etc.)
|
||||
- LMNR_* : Laminar monitoring/analytics configuration
|
||||
|
||||
Usage:
|
||||
# Auto-forwarding (no action needed):
|
||||
@@ -99,11 +97,6 @@ def get_agent_server_env() -> dict[str, str]:
|
||||
export LLM_NUM_RETRIES=10
|
||||
# These will automatically be available in the agent-server
|
||||
|
||||
# Auto-forwarding for Laminar:
|
||||
export LMNR_PROJECT_API_KEY=your-api-key
|
||||
export LMNR_BASE_URL=https://app.lmnr.ai
|
||||
# These will automatically be available in the agent-server
|
||||
|
||||
# Explicit override via JSON:
|
||||
OH_AGENT_SERVER_ENV='{"DEBUG": "true", "CUSTOM_VAR": "value"}'
|
||||
|
||||
|
||||
@@ -295,68 +295,6 @@ class TestLLMAutoForwarding:
|
||||
assert 'Llm_Timeout' not in result
|
||||
|
||||
|
||||
class TestLMNRAutoForwarding:
|
||||
"""Test cases for automatic forwarding of LMNR_* environment variables."""
|
||||
|
||||
def test_auto_forward_prefixes_contains_lmnr(self):
|
||||
"""Test that LMNR_ is in the auto-forward prefixes."""
|
||||
assert 'LMNR_' in AUTO_FORWARD_PREFIXES
|
||||
|
||||
def test_lmnr_project_api_key_auto_forwarded(self):
|
||||
"""Test that LMNR_PROJECT_API_KEY is automatically forwarded."""
|
||||
env_vars = {
|
||||
'LMNR_PROJECT_API_KEY': 'sk-test-key-12345',
|
||||
'OTHER_VAR': 'should_not_be_included',
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, env_vars, clear=True):
|
||||
result = get_agent_server_env()
|
||||
assert 'LMNR_PROJECT_API_KEY' in result
|
||||
assert result['LMNR_PROJECT_API_KEY'] == 'sk-test-key-12345'
|
||||
assert 'OTHER_VAR' not in result
|
||||
|
||||
def test_lmnr_base_url_auto_forwarded(self):
|
||||
"""Test that LMNR_BASE_URL is automatically forwarded."""
|
||||
env_vars = {
|
||||
'LMNR_BASE_URL': 'https://app.lmnr.ai',
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, env_vars, clear=True):
|
||||
result = get_agent_server_env()
|
||||
assert 'LMNR_BASE_URL' in result
|
||||
assert result['LMNR_BASE_URL'] == 'https://app.lmnr.ai'
|
||||
|
||||
def test_multiple_lmnr_vars_auto_forwarded(self):
|
||||
"""Test that multiple LMNR_* variables are automatically forwarded."""
|
||||
env_vars = {
|
||||
'LMNR_PROJECT_API_KEY': 'sk-test-key-12345',
|
||||
'LMNR_BASE_URL': 'https://app.lmnr.ai',
|
||||
'LMNR_VERBOSITY': 'debug',
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, env_vars, clear=True):
|
||||
result = get_agent_server_env()
|
||||
assert result['LMNR_PROJECT_API_KEY'] == 'sk-test-key-12345'
|
||||
assert result['LMNR_BASE_URL'] == 'https://app.lmnr.ai'
|
||||
assert result['LMNR_VERBOSITY'] == 'debug'
|
||||
|
||||
def test_lmnr_prefix_is_case_sensitive(self):
|
||||
"""Test that LMNR_ prefix matching is case-sensitive."""
|
||||
env_vars = {
|
||||
'LMNR_PROJECT_API_KEY': 'sk-test-key', # Should be included
|
||||
'lmnr_project_api_key': 'lowercase', # Should NOT be included
|
||||
'Lmnr_Project_Api_Key': 'mixed', # Should NOT be included
|
||||
}
|
||||
|
||||
with patch.dict(os.environ, env_vars, clear=True):
|
||||
result = get_agent_server_env()
|
||||
assert 'LMNR_PROJECT_API_KEY' in result
|
||||
assert result['LMNR_PROJECT_API_KEY'] == 'sk-test-key'
|
||||
# Lowercase variants should not be included
|
||||
assert 'lmnr_project_api_key' not in result
|
||||
assert 'Lmnr_Project_Api_Key' not in result
|
||||
|
||||
|
||||
class TestDockerSandboxSpecEnvironmentOverride:
|
||||
"""Test environment variable override integration in Docker sandbox specs."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user