mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 05:37:20 +08:00
fix: Add WORKER_1 and WORKER_2 env vars to remote sandbox service (#12424)
Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
@@ -30,6 +30,20 @@ GLOBAL_SKILLS_DIR = os.path.join(
|
||||
WORK_HOSTS_SKILL = """The user has access to the following hosts for accessing a web application,
|
||||
each of which has a corresponding port:"""
|
||||
|
||||
WORK_HOSTS_SKILL_FOOTER = """
|
||||
When starting a web server, use the corresponding ports via environment variables:
|
||||
- $WORKER_1 for the first port
|
||||
- $WORKER_2 for the second port
|
||||
|
||||
**CRITICAL: You MUST enable CORS and bind to 0.0.0.0.** Without CORS headers, the App tab cannot detect your server and will show an empty state.
|
||||
|
||||
Example (Flask):
|
||||
```python
|
||||
from flask_cors import CORS
|
||||
CORS(app)
|
||||
app.run(host='0.0.0.0', port=int(os.environ.get('WORKER_1', 12000)))
|
||||
```"""
|
||||
|
||||
|
||||
def _find_and_load_global_skill_files(skill_dir: Path) -> list[Skill]:
|
||||
"""Find and load all .md files from the global skills directory.
|
||||
@@ -73,6 +87,7 @@ def load_sandbox_skills(sandbox: SandboxInfo) -> list[Skill]:
|
||||
content_list = [WORK_HOSTS_SKILL]
|
||||
for url in urls:
|
||||
content_list.append(f'* {url.url} (port {url.port})')
|
||||
content_list.append(WORK_HOSTS_SKILL_FOOTER)
|
||||
content = '\n'.join(content_list)
|
||||
return [Skill(name='work_hosts', content=content, trigger=None)]
|
||||
|
||||
|
||||
@@ -272,6 +272,12 @@ class RemoteSandboxService(SandboxService):
|
||||
# we are probably in local development and the only url in use is localhost
|
||||
environment[ALLOW_CORS_ORIGINS_VARIABLE] = self.web_url
|
||||
|
||||
# Add worker port environment variables so the agent knows which ports to use
|
||||
# for web applications. These match the ports exposed via the WORKER_1 and
|
||||
# WORKER_2 URLs.
|
||||
environment[WORKER_1] = str(WORKER_1_PORT)
|
||||
environment[WORKER_2] = str(WORKER_2_PORT)
|
||||
|
||||
return environment
|
||||
|
||||
async def search_sandboxes(
|
||||
|
||||
@@ -295,6 +295,9 @@ class TestEnvironmentInitialization:
|
||||
assert environment['EXISTING_VAR'] == 'existing_value'
|
||||
assert environment[WEBHOOK_CALLBACK_VARIABLE] == expected_webhook_url
|
||||
assert environment[ALLOW_CORS_ORIGINS_VARIABLE] == 'https://web.example.com'
|
||||
# Verify worker port environment variables are set
|
||||
assert environment[WORKER_1] == '12000'
|
||||
assert environment[WORKER_2] == '12001'
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_init_environment_without_web_url(self, remote_sandbox_service):
|
||||
@@ -318,6 +321,9 @@ class TestEnvironmentInitialization:
|
||||
assert environment['EXISTING_VAR'] == 'existing_value'
|
||||
assert WEBHOOK_CALLBACK_VARIABLE not in environment
|
||||
assert ALLOW_CORS_ORIGINS_VARIABLE not in environment
|
||||
# Worker port environment variables should still be set regardless of web_url
|
||||
assert environment[WORKER_1] == '12000'
|
||||
assert environment[WORKER_2] == '12001'
|
||||
|
||||
|
||||
class TestSandboxInfoConversion:
|
||||
|
||||
Reference in New Issue
Block a user