From 972837ff73f4afb9b4b14be81aef00cd271930d7 Mon Sep 17 00:00:00 2001 From: Rohit Malhotra Date: Fri, 30 May 2025 18:18:34 -0400 Subject: [PATCH 01/88] [Feat]: Gitlab resolver (#8770) --- ...issue_comment_conversation_instructions.j2 | 2 +- ...issue_labeled_conversation_instructions.j2 | 2 +- ...issue_comment_conversation_instructions.j2 | 18 ++++++++++++++++ .../resolver/gitlab/issue_comment_prompt.j2 | 1 + ...issue_labeled_conversation_instructions.j2 | 12 +++++++++++ .../resolver/gitlab/issue_labeled_prompt.j2 | 1 + .../mr_update_conversation_instructions.j2 | 21 +++++++++++++++++++ .../resolver/gitlab/mr_update_prompt.j2 | 1 + 8 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 openhands/integrations/templates/resolver/gitlab/issue_comment_conversation_instructions.j2 create mode 100644 openhands/integrations/templates/resolver/gitlab/issue_comment_prompt.j2 create mode 100644 openhands/integrations/templates/resolver/gitlab/issue_labeled_conversation_instructions.j2 create mode 100644 openhands/integrations/templates/resolver/gitlab/issue_labeled_prompt.j2 create mode 100644 openhands/integrations/templates/resolver/gitlab/mr_update_conversation_instructions.j2 create mode 100644 openhands/integrations/templates/resolver/gitlab/mr_update_prompt.j2 diff --git a/openhands/integrations/templates/resolver/github/issue_comment_conversation_instructions.j2 b/openhands/integrations/templates/resolver/github/issue_comment_conversation_instructions.j2 index 3862a97858c5..1eeb5cd8aafe 100644 --- a/openhands/integrations/templates/resolver/github/issue_comment_conversation_instructions.j2 +++ b/openhands/integrations/templates/resolver/github/issue_comment_conversation_instructions.j2 @@ -12,7 +12,7 @@ A comment on the issue has been addressed to you. When you're done, make sure to 1. Re-read the issue title, body, and comments and make sure that you have successfully implemented all requirements. -2. Use the `GITHUB_TOKEN` environment variable and GitHub API to open a new PR +2. Use the `create_pr` tool to open a new PR 3. Name the branch using `openhands/` as a prefix (e.g `openhands/update-readme`) 4. The PR description should mention that it "fixes" or "closes" the issue number 5. Make sure to leave the following sentence at the end of the PR description: `@{{ username }} can click here to [continue refining the PR]({{ conversation_url }})` diff --git a/openhands/integrations/templates/resolver/github/issue_labeled_conversation_instructions.j2 b/openhands/integrations/templates/resolver/github/issue_labeled_conversation_instructions.j2 index aac2b542dc80..ddd8424df5e5 100644 --- a/openhands/integrations/templates/resolver/github/issue_labeled_conversation_instructions.j2 +++ b/openhands/integrations/templates/resolver/github/issue_labeled_conversation_instructions.j2 @@ -7,6 +7,6 @@ Your tasking is to fix an issue in your repository. Do the following When you're done, make sure to -1. Use the `GITHUB_TOKEN` environment variable and GitHub API to open a new PR +1. Use the `create_pr` tool to open a new PR 2. The PR description should mention that it "fixes" or "closes" the issue number 3. Make sure to leave the following sentence at the end of the PR description: `@{{ username }} can click here to [continue refining the PR]({{ conversation_url }})` diff --git a/openhands/integrations/templates/resolver/gitlab/issue_comment_conversation_instructions.j2 b/openhands/integrations/templates/resolver/gitlab/issue_comment_conversation_instructions.j2 new file mode 100644 index 000000000000..beb8be821e1a --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/issue_comment_conversation_instructions.j2 @@ -0,0 +1,18 @@ +You are requested to fix issue number #{{ issue_number }} in a repository. + +A comment on the issue has been addressed to you. + +# Steps to Handle the Comment + +1. Address the comment. Use the GitLab API to read issue title, body, and comments if you need more context +2. For all changes to actual application code (e.g. in Python or Javascript), add an appropriate test to the testing directory to make sure that the issue has been fixed +3. Run the tests, and if they pass you are done! +4. You do NOT need to write new tests if there are only changes to documentation or configuration files. + +When you're done, make sure to + +1. Re-read the issue title, body, and comments and make sure that you have successfully implemented all requirements. +2. Use the `create_mr` tool to open a new MR +3. Name the branch using `openhands/` as a prefix (e.g `openhands/update-readme`) +4. The MR description should mention that it "fixes" or "closes" the issue number +5. Make sure to leave the following sentence at the end of the MR description: `@{{ username }} can click here to [continue refining the MR]({{ conversation_url }})` diff --git a/openhands/integrations/templates/resolver/gitlab/issue_comment_prompt.j2 b/openhands/integrations/templates/resolver/gitlab/issue_comment_prompt.j2 new file mode 100644 index 000000000000..352927cfd773 --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/issue_comment_prompt.j2 @@ -0,0 +1 @@ +{{ issue_comment }} \ No newline at end of file diff --git a/openhands/integrations/templates/resolver/gitlab/issue_labeled_conversation_instructions.j2 b/openhands/integrations/templates/resolver/gitlab/issue_labeled_conversation_instructions.j2 new file mode 100644 index 000000000000..17313595fde2 --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/issue_labeled_conversation_instructions.j2 @@ -0,0 +1,12 @@ +Your tasking is to fix an issue in your repository. Do the following + +1. Read the issue body and comments using the GitLab API +2. For all changes to actual application code (e.g. in Python or Javascript), add an appropriate test to the testing directory to make sure that the issue has been fixed +3. Run the tests, and if they pass you are done! +4. You do NOT need to write new tests if there are only changes to documentation or configuration files. + +When you're done, make sure to + +1. Use the `create_mr` tool to open a new MR +2. The MR description should mention that it "fixes" or "closes" the issue number +3. Make sure to leave the following sentence at the end of the MR description: `@{{ username }} can click here to [continue refining the MR]({{ conversation_url }})` diff --git a/openhands/integrations/templates/resolver/gitlab/issue_labeled_prompt.j2 b/openhands/integrations/templates/resolver/gitlab/issue_labeled_prompt.j2 new file mode 100644 index 000000000000..eece89fec26b --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/issue_labeled_prompt.j2 @@ -0,0 +1 @@ +Please fix issue number #{{ issue_number }} in your repository. \ No newline at end of file diff --git a/openhands/integrations/templates/resolver/gitlab/mr_update_conversation_instructions.j2 b/openhands/integrations/templates/resolver/gitlab/mr_update_conversation_instructions.j2 new file mode 100644 index 000000000000..33813825e8a0 --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/mr_update_conversation_instructions.j2 @@ -0,0 +1,21 @@ +You are checked out to branch {{ branch_name }}, which has an open MR #{{ mr_number }}. +A comment on the MR has been addressed to you. Do NOT respond to this comment via the GitLab API. + +{% if file_location %} The comment is in the file `{{ file_location }}` on line #{{ line_number }}{% endif %}. + +# Steps to Handle the Comment + +## Understand the MR Context +Use the GitLab API to: + 1. Retrieve the diff against main to understand the changes + 2. Fetch the MR body and the linked issue for context + +## Process the Comment +If it's a question: + 1. Answer the question asked + 2. DO NOT leave any comments on the MR + +If it requests a code update: + 1. Modify the code accordingly in the current branch + 2. Push the changes to update the MR + 3. DO NOT leave any comments on the MR diff --git a/openhands/integrations/templates/resolver/gitlab/mr_update_prompt.j2 b/openhands/integrations/templates/resolver/gitlab/mr_update_prompt.j2 new file mode 100644 index 000000000000..4d26730c5f92 --- /dev/null +++ b/openhands/integrations/templates/resolver/gitlab/mr_update_prompt.j2 @@ -0,0 +1 @@ +{{ mr_comment }} From 277b87413baa76af8fff1ec1fbeccdac47094d04 Mon Sep 17 00:00:00 2001 From: Xingyao Wang Date: Sat, 31 May 2025 06:35:19 +0800 Subject: [PATCH 02/88] chore: log stack trace when failed to connect in mcp (#8804) --- openhands/mcp/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openhands/mcp/utils.py b/openhands/mcp/utils.py index 9beb19bc4959..7c7a1cf23868 100644 --- a/openhands/mcp/utils.py +++ b/openhands/mcp/utils.py @@ -69,7 +69,9 @@ async def create_mcp_clients( mcp_clients.append(client) logger.info(f'Connected to MCP server {server_url} via SSE') except Exception as e: - logger.error(f'Failed to connect to {server_url}: {str(e)}') + logger.error( + f'Failed to connect to {server_url}: {str(e)}', exc_info=True + ) try: await client.disconnect() except Exception as disconnect_error: From 59858dc73bf7d7e4e7dab16d89a5efdd82057245 Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Sat, 31 May 2025 02:15:35 -0400 Subject: [PATCH 03/88] Add OpenHands app support on windows without WSL (#8674) Co-authored-by: openhands Co-authored-by: Boxuan Li --- docs/modules/usage/installation.mdx | 5 + docs/modules/usage/windows-without-wsl.md | 195 ++++++++++++++++++ openhands/mcp/utils.py | 32 +++ openhands/runtime/action_execution_server.py | 94 ++++++--- openhands/runtime/base.py | 102 +++++---- .../action_execution_client.py | 17 ++ openhands/runtime/impl/local/local_runtime.py | 1 + openhands/runtime/plugins/vscode/__init__.py | 25 ++- openhands/utils/chunk_localizer.py | 6 +- poetry.lock | 45 +--- pyproject.toml | 18 +- tests/unit/test_runtime_git_tokens.py | 74 +++++-- 12 files changed, 471 insertions(+), 143 deletions(-) create mode 100644 docs/modules/usage/windows-without-wsl.md diff --git a/docs/modules/usage/installation.mdx b/docs/modules/usage/installation.mdx index 11f8640bbd8f..56f2465d9ab8 100644 --- a/docs/modules/usage/installation.mdx +++ b/docs/modules/usage/installation.mdx @@ -5,6 +5,7 @@ - MacOS with [Docker Desktop support](https://docs.docker.com/desktop/setup/install/mac-install/#system-requirements) - Linux - Windows with [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) and [Docker Desktop support](https://docs.docker.com/desktop/setup/install/windows-install/#system-requirements) +- Windows without WSL (see [Windows Without WSL Guide](./windows-without-wsl)) A system with a modern processor and a minimum of **4GB RAM** is recommended to run OpenHands. @@ -51,6 +52,10 @@ A system with a modern processor and a minimum of **4GB RAM** is recommended to The docker command below to start the app must be run inside the WSL terminal. ::: + **Alternative: Windows without WSL** + + If you prefer to run OpenHands on Windows without WSL or Docker, see our [Windows Without WSL Guide](./windows-without-wsl). + ## Start the App diff --git a/docs/modules/usage/windows-without-wsl.md b/docs/modules/usage/windows-without-wsl.md new file mode 100644 index 000000000000..805b08ed59ff --- /dev/null +++ b/docs/modules/usage/windows-without-wsl.md @@ -0,0 +1,195 @@ +# Running OpenHands GUI on Windows Without WSL + +This guide provides step-by-step instructions for running OpenHands on a Windows machine without using WSL or Docker. + +## Prerequisites + +1. **Windows 10/11** - A modern Windows operating system +2. **PowerShell 7+** - While Windows PowerShell comes pre-installed on Windows 10/11, PowerShell 7+ is strongly recommended to avoid compatibility issues (see Troubleshooting section for "System.Management.Automation" errors) +3. **.NET Core Runtime** - Required for the PowerShell integration via pythonnet +4. **Python 3.12 or 3.13** - Python 3.12 or 3.13 is required (Python 3.14 is not supported due to pythonnet compatibility) +5. **Git** - For cloning the repository and version control +6. **Node.js and npm** - For running the frontend + +## Step 1: Install Required Software + +1. **Install Python 3.12 or 3.13** + - Download Python 3.12.x or 3.13.x from [python.org](https://www.python.org/downloads/) + - During installation, check "Add Python to PATH" + - Verify installation by opening PowerShell and running: + ```powershell + python --version + ``` + +2. **Install PowerShell 7** + - Download and install PowerShell 7 from the [official PowerShell GitHub repository](https://github.com/PowerShell/PowerShell/releases) + - Choose the MSI installer appropriate for your system (x64 for most modern computers) + - Run the installer with default options + - Verify installation by opening a new terminal and running: + ```powershell + pwsh --version + ``` + - Using PowerShell 7 (pwsh) instead of Windows PowerShell will help avoid "System.Management.Automation" errors + +3. **Install .NET Core Runtime** + - Download and install the .NET Core Runtime from [Microsoft's .NET download page](https://dotnet.microsoft.com/download) + - Choose the latest .NET Core Runtime (not SDK) + - Verify installation by opening PowerShell and running: + ```powershell + dotnet --info + ``` + - This step is required for the PowerShell integration via pythonnet. Without it, OpenHands will fall back to a more limited PowerShell implementation. + +4. **Install Git** + - Download Git from [git-scm.com](https://git-scm.com/download/win) + - Use default installation options + - Verify installation: + ```powershell + git --version + ``` + +5. **Install Node.js and npm** + - Download Node.js from [nodejs.org](https://nodejs.org/) (LTS version recommended) + - During installation, accept the default options which will install npm as well + - Verify installation: + ```powershell + node --version + npm --version + ``` + +6. **Install Poetry** + - Open PowerShell as Administrator and run: + ```powershell + (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python - + ``` + - Add Poetry to your PATH: + ```powershell + $env:Path += ";$env:APPDATA\Python\Scripts" + ``` + - Verify installation: + ```powershell + poetry --version + ``` + +## Step 2: Clone and Set Up OpenHands + +1. **Clone the Repository** + ```powershell + git clone https://github.com/All-Hands-AI/OpenHands.git + cd OpenHands + ``` + +2. **Install Dependencies** + ```powershell + poetry install + ``` + + This will install all required dependencies, including: + - pythonnet - Required for Windows PowerShell integration + - All other OpenHands dependencies + +## Step 3: Run OpenHands + +1. **Build the Frontend** + ```powershell + cd frontend + npm install + npm run build + cd .. + ``` + + This will build the frontend files that the backend will serve. + +2. **Start the Backend** + ```powershell + # Make sure to use PowerShell 7 (pwsh) instead of Windows PowerShell + pwsh + $env:RUNTIME="local"; poetry run uvicorn openhands.server.listen:app --host 0.0.0.0 --port 3000 --reload --reload-exclude "./workspace" + ``` + + This will start the OpenHands app using the local runtime with PowerShell integration, available at `localhost:3000`. + + > **Note**: If you encounter a `RuntimeError: Directory './frontend/build' does not exist` error, make sure you've built the frontend first using the command above. + + > **Important**: Using PowerShell 7 (pwsh) instead of Windows PowerShell is recommended to avoid "System.Management.Automation" errors. If you encounter this error, see the Troubleshooting section below. + +3. **Alternatively, Run the Frontend in Development Mode (in a separate PowerShell window)** + ```powershell + cd frontend + npm run dev + ``` + +4. **Access the OpenHands GUI** + + Open your browser and navigate to: + ``` + http://localhost:3000 + ``` + + > **Note**: If you're running the frontend in development mode (using `npm run dev`), use port 3001 instead: `http://localhost:3001` + +## Limitations on Windows + +When running OpenHands on Windows without WSL or Docker, be aware of the following limitations: + +1. **Browser Tool Not Supported**: The browser tool is not currently supported on Windows. + +2. **.NET Core Requirement**: The PowerShell integration requires .NET Core Runtime to be installed. If .NET Core is not available, OpenHands will automatically fall back to a more limited PowerShell implementation with reduced functionality. + +3. **Interactive Shell Commands**: Some interactive shell commands may not work as expected. The PowerShell session implementation has limitations compared to the bash session used on Linux/macOS. + +4. **Path Handling**: Windows uses backslashes (`\`) in paths, which may require adjustments when working with code examples designed for Unix-like systems. + +## Troubleshooting + +### "System.Management.Automation" Not Found Error + +If you encounter an error message stating that "System.Management.Automation" was not found, this typically indicates that you have a minimal version of PowerShell installed or that the .NET components required for PowerShell integration are missing. + +> **IMPORTANT**: This error is most commonly caused by using the built-in Windows PowerShell (powershell.exe) instead of PowerShell 7 (pwsh.exe). Even if you installed PowerShell 7 during the prerequisites, you may still be using the older Windows PowerShell by default. + +To resolve this issue: + +1. **Install the latest version of PowerShell 7** from the official Microsoft repository: + - Visit [https://github.com/PowerShell/PowerShell/releases](https://github.com/PowerShell/PowerShell/releases) + - Download and install the latest MSI package for your system architecture (x64 for most systems) + - During installation, ensure you select the following options: + - "Add PowerShell to PATH environment variable" + - "Register Windows PowerShell 7 as the default shell" + - "Enable PowerShell remoting" + - The installer will place PowerShell 7 in `C:\Program Files\PowerShell\7` by default + +2. **Restart your terminal or command prompt** to ensure the new PowerShell is available + +3. **Verify the installation** by running: + ```powershell + pwsh --version + ``` + + You should see output indicating PowerShell 7.x.x + +4. **Run OpenHands using PowerShell 7** instead of Windows PowerShell: + ```powershell + pwsh + cd path\to\openhands + $env:RUNTIME="local"; poetry run uvicorn openhands.server.listen:app --host 0.0.0.0 --port 3000 --reload --reload-exclude "./workspace" + ``` + + > **Note**: Make sure you're explicitly using `pwsh` (PowerShell 7) and not `powershell` (Windows PowerShell). The command prompt or terminal title should say "PowerShell 7" rather than just "Windows PowerShell". + +5. **If the issue persists**, ensure that you have the .NET Runtime installed: + - Download and install the latest .NET Runtime from [Microsoft's .NET download page](https://dotnet.microsoft.com/download) + - Choose ".NET Runtime" (not SDK) version 6.0 or later + - After installation, verify it's properly installed by running: + ```powershell + dotnet --info + ``` + - Restart your computer after installation + - Try running OpenHands again + +6. **Ensure that the .NET Framework is properly installed** on your system: + - Go to Control Panel > Programs > Programs and Features > Turn Windows features on or off + - Make sure ".NET Framework 4.8 Advanced Services" is enabled + - Click OK and restart if prompted + +This error occurs because OpenHands uses the pythonnet package to interact with PowerShell, which requires the System.Management.Automation assembly from the .NET framework. A minimal PowerShell installation or older Windows PowerShell (rather than PowerShell 7+) might not include all the necessary components for this integration. diff --git a/openhands/mcp/utils.py b/openhands/mcp/utils.py index 7c7a1cf23868..fb932edee3a8 100644 --- a/openhands/mcp/utils.py +++ b/openhands/mcp/utils.py @@ -50,6 +50,15 @@ def convert_mcp_clients_to_tools(mcp_clients: list[MCPClient] | None) -> list[di async def create_mcp_clients( sse_servers: list[MCPSSEServerConfig], conversation_id: str | None = None ) -> list[MCPClient]: + import sys + + # Skip MCP clients on Windows + if sys.platform == 'win32': + logger.info( + 'MCP functionality is disabled on Windows, skipping client creation' + ) + return [] + mcp_clients: list[MCPClient] = [] # Initialize SSE connections if sse_servers: @@ -89,6 +98,13 @@ async def fetch_mcp_tools_from_config(mcp_config: MCPConfig) -> list[dict]: Returns: A list of tool dictionaries. Returns an empty list if no connections could be established. """ + import sys + + # Skip MCP tools on Windows + if sys.platform == 'win32': + logger.info('MCP functionality is disabled on Windows, skipping tool fetching') + return [] + mcp_clients = [] mcp_tools = [] try: @@ -131,6 +147,15 @@ async def call_tool_mcp(mcp_clients: list[MCPClient], action: MCPAction) -> Obse Returns: The observation from the MCP server """ + import sys + + from openhands.events.observation import ErrorObservation + + # Skip MCP tools on Windows + if sys.platform == 'win32': + logger.info('MCP functionality is disabled on Windows') + return ErrorObservation('MCP functionality is not available on Windows') + if not mcp_clients: raise ValueError('No MCP clients found') @@ -169,6 +194,13 @@ async def add_mcp_tools_to_agent( """ Add MCP tools to an agent. """ + import sys + + # Skip MCP tools on Windows + if sys.platform == 'win32': + logger.info('MCP functionality is disabled on Windows, skipping MCP tools') + agent.set_mcp_tools([]) + return assert runtime.runtime_initialized, ( 'Runtime must be initialized before adding MCP tools' diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index 30a48df1a56d..113aff9d772a 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -677,44 +677,53 @@ async def lifespan(app: FastAPI): await client.ainit() logger.info('ActionExecutor initialized.') - # Initialize and mount MCP Router - logger.info('Initializing MCP Router...') - mcp_router = MCPRouter( - profile_path=MCP_ROUTER_PROFILE_PATH, - router_config=RouterConfig( - api_key=SESSION_API_KEY, - auth_enabled=bool(SESSION_API_KEY), - ), - ) - allowed_origins = ['*'] - sse_app = await mcp_router.get_sse_server_app( - allow_origins=allowed_origins, include_lifespan=False - ) - - # Check for route conflicts before mounting - main_app_routes = {route.path for route in app.routes} - sse_app_routes = {route.path for route in sse_app.routes} - conflicting_routes = main_app_routes.intersection(sse_app_routes) + # Check if we're on Windows + is_windows = sys.platform == 'win32' - if conflicting_routes: - logger.error(f'Route conflicts detected: {conflicting_routes}') - raise RuntimeError( - f'Cannot mount SSE app - conflicting routes found: {conflicting_routes}' + # Initialize and mount MCP Router (skip on Windows) + if is_windows: + logger.info('Skipping MCP Router initialization on Windows') + mcp_router = None + else: + logger.info('Initializing MCP Router...') + mcp_router = MCPRouter( + profile_path=MCP_ROUTER_PROFILE_PATH, + router_config=RouterConfig( + api_key=SESSION_API_KEY, + auth_enabled=bool(SESSION_API_KEY), + ), + ) + allowed_origins = ['*'] + sse_app = await mcp_router.get_sse_server_app( + allow_origins=allowed_origins, include_lifespan=False ) - app.mount('/', sse_app) - logger.info( - f'Mounted MCP Router SSE app at root path with allowed origins: {allowed_origins}' - ) + # Only mount SSE app if MCP Router is initialized (not on Windows) + if mcp_router is not None: + # Check for route conflicts before mounting + main_app_routes = {route.path for route in app.routes} + sse_app_routes = {route.path for route in sse_app.routes} + conflicting_routes = main_app_routes.intersection(sse_app_routes) + + if conflicting_routes: + logger.error(f'Route conflicts detected: {conflicting_routes}') + raise RuntimeError( + f'Cannot mount SSE app - conflicting routes found: {conflicting_routes}' + ) - # Additional debug logging - if logger.isEnabledFor(logging.DEBUG): - logger.debug('Main app routes:') - for route in main_app_routes: - logger.debug(f' {route}') - logger.debug('MCP SSE server app routes:') - for route in sse_app_routes: - logger.debug(f' {route}') + app.mount('/', sse_app) + logger.info( + f'Mounted MCP Router SSE app at root path with allowed origins: {allowed_origins}' + ) + + # Additional debug logging + if logger.isEnabledFor(logging.DEBUG): + logger.debug('Main app routes:') + for route in main_app_routes: + logger.debug(f' {route}') + logger.debug('MCP SSE server app routes:') + for route in sse_app_routes: + logger.debug(f' {route}') yield @@ -816,6 +825,23 @@ async def execute_action(action_request: ActionRequest): @app.post('/update_mcp_server') async def update_mcp_server(request: Request): + # Check if we're on Windows + is_windows = sys.platform == 'win32' + + if is_windows: + # On Windows, just return a success response without doing anything + logger.info( + 'MCP server update request received on Windows - skipping as MCP is disabled' + ) + return JSONResponse( + status_code=200, + content={ + 'detail': 'MCP server update skipped (MCP is disabled on Windows)', + 'router_error_log': '', + }, + ) + + # Non-Windows implementation assert mcp_router is not None assert os.path.exists(MCP_ROUTER_PROFILE_PATH) diff --git a/openhands/runtime/base.py b/openhands/runtime/base.py index 70135cacd331..9325bc6d3b04 100644 --- a/openhands/runtime/base.py +++ b/openhands/runtime/base.py @@ -218,35 +218,66 @@ def add_env_vars(self, env_vars: dict[str, str]) -> None: # Note: we don't log the vars values, they're leaking info logger.debug('Added env vars to IPython') - # Add env vars to the Bash shell and .bashrc for persistence - cmd = '' - bashrc_cmd = '' - for key, value in env_vars.items(): - # Note: json.dumps gives us nice escaping for free - cmd += f'export {key}={json.dumps(value)}; ' - # Add to .bashrc if not already present - bashrc_cmd += f'grep -q "^export {key}=" ~/.bashrc || echo "export {key}={json.dumps(value)}" >> ~/.bashrc; ' - if not cmd: - return - cmd = cmd.strip() - logger.debug( - 'Adding env vars to bash' - ) # don't log the vars values, they're leaking info + # Check if we're on Windows + import os + import sys - obs = self.run(CmdRunAction(cmd)) - if not isinstance(obs, CmdOutputObservation) or obs.exit_code != 0: - raise RuntimeError( - f'Failed to add env vars [{env_vars.keys()}] to environment: {obs.content}' - ) + is_windows = os.name == 'nt' or sys.platform == 'win32' - # Add to .bashrc for persistence - bashrc_cmd = bashrc_cmd.strip() - logger.debug(f'Adding env var to .bashrc: {env_vars.keys()}') - obs = self.run(CmdRunAction(bashrc_cmd)) - if not isinstance(obs, CmdOutputObservation) or obs.exit_code != 0: - raise RuntimeError( - f'Failed to add env vars [{env_vars.keys()}] to .bashrc: {obs.content}' - ) + if is_windows: + # Add env vars using PowerShell commands for Windows + cmd = '' + for key, value in env_vars.items(): + # Use PowerShell's $env: syntax for environment variables + # Note: json.dumps gives us nice escaping for free + cmd += f'$env:{key} = {json.dumps(value)}; ' + + if not cmd: + return + + cmd = cmd.strip() + logger.debug('Adding env vars to PowerShell') # don't log the values + + obs = self.run(CmdRunAction(cmd)) + if not isinstance(obs, CmdOutputObservation) or obs.exit_code != 0: + raise RuntimeError( + f'Failed to add env vars [{env_vars.keys()}] to environment: {obs.content}' + ) + + # We don't add to profile persistence on Windows as it's more complex + # and varies between PowerShell versions + logger.debug(f'Added env vars to PowerShell session: {env_vars.keys()}') + + else: + # Original bash implementation for Unix systems + cmd = '' + bashrc_cmd = '' + for key, value in env_vars.items(): + # Note: json.dumps gives us nice escaping for free + cmd += f'export {key}={json.dumps(value)}; ' + # Add to .bashrc if not already present + bashrc_cmd += f'grep -q "^export {key}=" ~/.bashrc || echo "export {key}={json.dumps(value)}" >> ~/.bashrc; ' + + if not cmd: + return + + cmd = cmd.strip() + logger.debug('Adding env vars to bash') # don't log the values + + obs = self.run(CmdRunAction(cmd)) + if not isinstance(obs, CmdOutputObservation) or obs.exit_code != 0: + raise RuntimeError( + f'Failed to add env vars [{env_vars.keys()}] to environment: {obs.content}' + ) + + # Add to .bashrc for persistence + bashrc_cmd = bashrc_cmd.strip() + logger.debug(f'Adding env var to .bashrc: {env_vars.keys()}') + obs = self.run(CmdRunAction(bashrc_cmd)) + if not isinstance(obs, CmdOutputObservation) or obs.exit_code != 0: + raise RuntimeError( + f'Failed to add env vars [{env_vars.keys()}] to .bashrc: {obs.content}' + ) def on_event(self, event: Event) -> None: if isinstance(event, Action): @@ -406,9 +437,13 @@ async def clone_or_init_repo( else f'git checkout -b {openhands_workspace_branch}' ) - action = CmdRunAction( - command=f'{clone_command} ; cd {dir_name} ; {checkout_command}', + clone_action = CmdRunAction(command=clone_command) + self.run_action(clone_action) + + cd_checkout_action = CmdRunAction( + command=f'cd {dir_name} && {checkout_command}' ) + action = cd_checkout_action self.log('info', f'Cloning repo: {selected_repository}') self.run_action(action) return dir_name @@ -649,16 +684,13 @@ def get_microagents_from_org_or_user( # Get authenticated URL and do a shallow clone (--depth 1) for efficiency remote_url = self._get_authenticated_git_url(org_openhands_repo) - clone_cmd = f"git clone --depth 1 {remote_url} {org_repo_dir} 2>/dev/null || echo 'Org repo not found'" + + clone_cmd = f'git clone --depth 1 {remote_url} {org_repo_dir}' action = CmdRunAction(command=clone_cmd) obs = self.run_action(action) - if ( - isinstance(obs, CmdOutputObservation) - and obs.exit_code == 0 - and 'Org repo not found' not in obs.content - ): + if isinstance(obs, CmdOutputObservation) and obs.exit_code == 0: self.log( 'info', f'Successfully cloned org-level microagents from {org_openhands_repo}', diff --git a/openhands/runtime/impl/action_execution/action_execution_client.py b/openhands/runtime/impl/action_execution/action_execution_client.py index b35e0be92ee5..dd13d24d3b73 100644 --- a/openhands/runtime/impl/action_execution/action_execution_client.py +++ b/openhands/runtime/impl/action_execution/action_execution_client.py @@ -354,6 +354,14 @@ def browse_interactive(self, action: BrowseInteractiveAction) -> Observation: def get_mcp_config( self, extra_stdio_servers: list[MCPStdioServerConfig] | None = None ) -> MCPConfig: + import sys + + # Check if we're on Windows - MCP is disabled on Windows + if sys.platform == 'win32': + # Return empty MCP config on Windows + self.log('debug', 'MCP is disabled on Windows, returning empty config') + return MCPConfig(sse_servers=[], stdio_servers=[]) + # Add the runtime as another MCP server updated_mcp_config = self.config.mcp.model_copy() @@ -436,6 +444,15 @@ def get_mcp_config( return updated_mcp_config async def call_tool_mcp(self, action: MCPAction) -> Observation: + import sys + + from openhands.events.observation import ErrorObservation + + # Check if we're on Windows - MCP is disabled on Windows + if sys.platform == 'win32': + self.log('info', 'MCP functionality is disabled on Windows') + return ErrorObservation('MCP functionality is not available on Windows') + # Import here to avoid circular imports from openhands.mcp.utils import call_tool_mcp as call_tool_mcp_handler from openhands.mcp.utils import create_mcp_clients diff --git a/openhands/runtime/impl/local/local_runtime.py b/openhands/runtime/impl/local/local_runtime.py index 0d50270baed6..1be1acb7b14d 100644 --- a/openhands/runtime/impl/local/local_runtime.py +++ b/openhands/runtime/impl/local/local_runtime.py @@ -238,6 +238,7 @@ async def connect(self) -> None: env['PYTHONPATH'] = os.pathsep.join([code_repo_path, env.get('PYTHONPATH', '')]) env['OPENHANDS_REPO_PATH'] = code_repo_path env['LOCAL_RUNTIME_MODE'] = '1' + env['VSCODE_PORT'] = str(self._vscode_port) # Derive environment paths using sys.executable interpreter_path = sys.executable diff --git a/openhands/runtime/plugins/vscode/__init__.py b/openhands/runtime/plugins/vscode/__init__.py index e583e2a107df..6dd80c16295d 100644 --- a/openhands/runtime/plugins/vscode/__init__.py +++ b/openhands/runtime/plugins/vscode/__init__.py @@ -1,6 +1,7 @@ import asyncio import os import shutil +import sys import uuid from dataclasses import dataclass from pathlib import Path @@ -26,6 +27,15 @@ class VSCodePlugin(Plugin): gateway_process: asyncio.subprocess.Process async def initialize(self, username: str) -> None: + # Check if we're on Windows - VSCode plugin is not supported on Windows + if os.name == 'nt' or sys.platform == 'win32': + self.vscode_port = None + self.vscode_connection_token = None + logger.warning( + 'VSCode plugin is not supported on Windows. Plugin will be disabled.' + ) + return + if username not in ['root', 'openhands']: self.vscode_port = None self.vscode_connection_token = None @@ -38,9 +48,20 @@ async def initialize(self, username: str) -> None: # Set up VSCode settings.json self._setup_vscode_settings() - self.vscode_port = int(os.environ['VSCODE_PORT']) + try: + self.vscode_port = int(os.environ['VSCODE_PORT']) + except (KeyError, ValueError): + logger.warning( + 'VSCODE_PORT environment variable not set or invalid. VSCode plugin will be disabled.' + ) + return + self.vscode_connection_token = str(uuid.uuid4()) - assert check_port_available(self.vscode_port) + if not check_port_available(self.vscode_port): + logger.warning( + f'Port {self.vscode_port} is not available. VSCode plugin will be disabled.' + ) + return cmd = ( f"su - {username} -s /bin/bash << 'EOF'\n" f'sudo chown -R {username}:{username} /openhands/.openvscode-server\n' diff --git a/openhands/utils/chunk_localizer.py b/openhands/utils/chunk_localizer.py index 8b2e986c14b0..9f1437dd3d42 100644 --- a/openhands/utils/chunk_localizer.py +++ b/openhands/utils/chunk_localizer.py @@ -4,8 +4,8 @@ for a given query (e.g. edit draft produced by the agent). """ -import pylcs from pydantic import BaseModel +from rapidfuzz.distance import LCSseq from tree_sitter_languages import get_parser from openhands.core.logger import openhands_logger as logger @@ -65,7 +65,9 @@ def normalized_lcs(chunk: str, query: str) -> float: """ if len(chunk) == 0: return 0.0 - _score = pylcs.lcs_sequence_length(chunk, query) + + _score = LCSseq.similarity(chunk, query) + return _score / len(chunk) diff --git a/poetry.lock b/poetry.lock index eb01eea8793c..457a534b4343 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3011,7 +3011,7 @@ grpcio = {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_versi grpcio-status = {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} proto-plus = [ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, - {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, + {version = ">=1.22.3,<2.0.0"}, ] protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" requests = ">=2.18.0,<3.0.0" @@ -3230,7 +3230,7 @@ google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0" grpc-google-iam-v1 = ">=0.14.0,<1.0.0" proto-plus = [ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, - {version = ">=1.22.3,<2.0.0"}, + {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, ] protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" @@ -5403,11 +5403,8 @@ files = [ {file = "lxml-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7ce1a171ec325192c6a636b64c94418e71a1964f56d002cc28122fceff0b6121"}, {file = "lxml-5.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:795f61bcaf8770e1b37eec24edf9771b307df3af74d1d6f27d812e15a9ff3872"}, {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29f451a4b614a7b5b6c2e043d7b64a15bd8304d7e767055e8ab68387a8cacf4e"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:891f7f991a68d20c75cb13c5c9142b2a3f9eb161f1f12a9489c82172d1f133c0"}, {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4aa412a82e460571fad592d0f93ce9935a20090029ba08eca05c614f99b0cc92"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:ac7ba71f9561cd7d7b55e1ea5511543c0282e2b6450f122672a2694621d63b7e"}, {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:c5d32f5284012deaccd37da1e2cd42f081feaa76981f0eaa474351b68df813c5"}, - {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:ce31158630a6ac85bddd6b830cffd46085ff90498b397bd0a259f59d27a12188"}, {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:31e63621e073e04697c1b2d23fcb89991790eef370ec37ce4d5d469f40924ed6"}, {file = "lxml-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:be2ba4c3c5b7900246a8f866580700ef0d538f2ca32535e991027bdaba944063"}, {file = "lxml-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:09846782b1ef650b321484ad429217f5154da4d6e786636c38e434fa32e94e49"}, @@ -7593,21 +7590,6 @@ files = [ [package.dependencies] pyasn1 = ">=0.6.1,<0.7.0" -[[package]] -name = "pybind11" -version = "2.13.6" -description = "Seamless operability between C++11 and Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pybind11-2.13.6-py3-none-any.whl", hash = "sha256:237c41e29157b962835d356b370ededd57594a26d5894a795960f0047cb5caf5"}, - {file = "pybind11-2.13.6.tar.gz", hash = "sha256:ba6af10348c12b24e92fa086b39cfba0eff619b61ac77c406167d813b096d39a"}, -] - -[package.extras] -global = ["pybind11-global (==2.13.6)"] - [[package]] name = "pycodestyle" version = "2.13.0" @@ -7959,27 +7941,6 @@ files = [ {file = "pylatexenc-2.10.tar.gz", hash = "sha256:3dd8fd84eb46dc30bee1e23eaab8d8fb5a7f507347b23e5f38ad9675c84f40d3"}, ] -[[package]] -name = "pylcs" -version = "0.1.1" -description = "super fast cpp implementation of longest common subsequence" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pylcs-0.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b8adea6b41dff27332c967533ec3c42a5e94171be778d6f01f0c5cee82e7604"}, - {file = "pylcs-0.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ff06e037c54056cb67d6ef5ad946c0360afeff7d43be67ce09e55201ecc15cc"}, - {file = "pylcs-0.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:d2ebf340aa180d841939d9ec1168dfd072992dda1d48148ceb07b65b1ab62ffa"}, - {file = "pylcs-0.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b6c43b63e20048f8fec7e122fbc08c238940a0ee5302bf84a70db22c7f8cc836"}, - {file = "pylcs-0.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:db52d55cfdf813af974bcc164aedbd29274da83086877bf05778aa7fbf777f7f"}, - {file = "pylcs-0.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:954495f1c164ccb722b835e7028783f8a38d85ed5f6ff7b9d50143896c6cff9b"}, - {file = "pylcs-0.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:0f4c82fad8c0429abef9e98fb98904459c4f5f9fb9b6ce20e0df0841a6a48a54"}, - {file = "pylcs-0.1.1.tar.gz", hash = "sha256:632c69235d77cda0ba524d82796878801d2f46131fc59e730c98767fc4ce1307"}, -] - -[package.dependencies] -pybind11 = ">=2.2" - [[package]] name = "pynacl" version = "1.5.0" @@ -12193,4 +12154,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.1" python-versions = "^3.12,<3.14" -content-hash = "509493c2d53d5923054d7521079a212c6e67323389b75886b6e1dccc9869127c" +content-hash = "071b19070a00bfbae9cab2332a58ce9e0f31fcf594bc4ad32fd647783611396c" diff --git a/pyproject.toml b/pyproject.toml index e880b75b665f..9fa939087e55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,12 +20,12 @@ packages = [ [tool.poetry.dependencies] python = "^3.12,<3.14" -litellm = "^1.60.0, !=1.64.4, !=1.67.*" # avoid 1.64.4 (known bug) & 1.67.* (known bug #10272) -aiohttp = ">=3.9.0,!=3.11.13" # Pin to avoid yanked version 3.11.13 -google-generativeai = "*" # To use litellm with Gemini Pro API -google-api-python-client = "^2.164.0" # For Google Sheets API -google-auth-httplib2 = "*" # For Google Sheets authentication -google-auth-oauthlib = "*" # For Google Sheets OAuth +litellm = "^1.60.0, !=1.64.4, !=1.67.*" # avoid 1.64.4 (known bug) & 1.67.* (known bug #10272) +aiohttp = ">=3.9.0,!=3.11.13" # Pin to avoid yanked version 3.11.13 +google-generativeai = "*" # To use litellm with Gemini Pro API +google-api-python-client = "^2.164.0" # For Google Sheets API +google-auth-httplib2 = "*" # For Google Sheets authentication +google-auth-oauthlib = "*" # For Google Sheets OAuth termcolor = "*" docker = "*" fastapi = "*" @@ -34,7 +34,7 @@ uvicorn = "*" types-toml = "*" numpy = "*" json-repair = "*" -browsergym-core = "0.13.3" # integrate browsergym-core as the browsing interface +browsergym-core = "0.13.3" # integrate browsergym-core as the browsing interface html2text = "*" e2b = ">=1.0.5,<1.4.0" pexpect = "*" @@ -58,9 +58,9 @@ python-pptx = "*" pylatexenc = "*" tornado = "*" python-dotenv = "*" -pylcs = "^0.1.1" +rapidfuzz = "^3.9.0" whatthepatch = "^1.0.6" -protobuf = "^4.21.6,<5.0.0" # chromadb currently fails on 5.0+ +protobuf = "^4.21.6,<5.0.0" # chromadb currently fails on 5.0+ opentelemetry-api = "1.25.0" opentelemetry-exporter-otlp-proto-grpc = "1.25.0" modal = ">=0.66.26,<0.78.0" diff --git a/tests/unit/test_runtime_git_tokens.py b/tests/unit/test_runtime_git_tokens.py index d88fe1712b66..fb880d9aecd4 100644 --- a/tests/unit/test_runtime_git_tokens.py +++ b/tests/unit/test_runtime_git_tokens.py @@ -327,8 +327,22 @@ async def test_clone_or_init_repo_github_with_token(temp_dir, monkeypatch): result = await runtime.clone_or_init_repo(git_provider_tokens, 'owner/repo', None) - cmd = runtime.run_action_calls[0].command - assert f'git clone https://{github_token}@github.com/owner/repo.git repo' in cmd + # Verify that git clone and checkout were called as separate commands + assert len(runtime.run_action_calls) == 2 + assert isinstance(runtime.run_action_calls[0], CmdRunAction) + assert isinstance(runtime.run_action_calls[1], CmdRunAction) + + # Check that the first command is the git clone with the correct URL format with token + clone_cmd = runtime.run_action_calls[0].command + assert ( + f'git clone https://{github_token}@github.com/owner/repo.git repo' in clone_cmd + ) + + # Check that the second command is the checkout + checkout_cmd = runtime.run_action_calls[1].command + assert 'cd repo' in checkout_cmd + assert 'git checkout -b openhands-workspace-' in checkout_cmd + assert result == 'repo' @@ -346,15 +360,20 @@ async def test_clone_or_init_repo_github_no_token(temp_dir, monkeypatch): mock_repo_and_patch(monkeypatch, provider=ProviderType.GITHUB) result = await runtime.clone_or_init_repo(None, 'owner/repo', None) - # Verify that git clone was called with the public URL - assert len(runtime.run_action_calls) == 1 + # Verify that git clone and checkout were called as separate commands + assert len(runtime.run_action_calls) == 2 assert isinstance(runtime.run_action_calls[0], CmdRunAction) + assert isinstance(runtime.run_action_calls[1], CmdRunAction) + + # Check that the first command is the git clone with the correct URL format without token + clone_cmd = runtime.run_action_calls[0].command + assert 'git clone https://github.com/owner/repo.git repo' in clone_cmd + + # Check that the second command is the checkout + checkout_cmd = runtime.run_action_calls[1].command + assert 'cd repo' in checkout_cmd + assert 'git checkout -b openhands-workspace-' in checkout_cmd - # Check that the command contains the correct URL format without token - cmd = runtime.run_action_calls[0].command - assert 'git clone https://github.com/owner/repo.git repo' in cmd - assert 'cd repo' in cmd - assert 'git checkout -b openhands-workspace-' in cmd assert result == 'repo' @@ -381,10 +400,23 @@ async def test_clone_or_init_repo_gitlab_with_token(temp_dir, monkeypatch): result = await runtime.clone_or_init_repo(git_provider_tokens, 'owner/repo', None) - cmd = runtime.run_action_calls[0].command + # Verify that git clone and checkout were called as separate commands + assert len(runtime.run_action_calls) == 2 + assert isinstance(runtime.run_action_calls[0], CmdRunAction) + assert isinstance(runtime.run_action_calls[1], CmdRunAction) + + # Check that the first command is the git clone with the correct URL format with token + clone_cmd = runtime.run_action_calls[0].command assert ( - f'git clone https://oauth2:{gitlab_token}@gitlab.com/owner/repo.git repo' in cmd + f'git clone https://oauth2:{gitlab_token}@gitlab.com/owner/repo.git repo' + in clone_cmd ) + + # Check that the second command is the checkout + checkout_cmd = runtime.run_action_calls[1].command + assert 'cd repo' in checkout_cmd + assert 'git checkout -b openhands-workspace-' in checkout_cmd + assert result == 'repo' @@ -402,14 +434,18 @@ async def test_clone_or_init_repo_with_branch(temp_dir, monkeypatch): mock_repo_and_patch(monkeypatch, provider=ProviderType.GITHUB) result = await runtime.clone_or_init_repo(None, 'owner/repo', 'feature-branch') - # Verify that git clone was called with the correct branch checkout - assert len(runtime.run_action_calls) == 1 + # Verify that git clone and checkout were called as separate commands + assert len(runtime.run_action_calls) == 2 assert isinstance(runtime.run_action_calls[0], CmdRunAction) + assert isinstance(runtime.run_action_calls[1], CmdRunAction) + + # Check that the first command is the git clone + clone_cmd = runtime.run_action_calls[0].command - # Check that the command contains the correct branch checkout - cmd = runtime.run_action_calls[0].command - assert 'git clone https://github.com/owner/repo.git repo' in cmd - assert 'cd repo' in cmd - assert 'git checkout feature-branch' in cmd - assert 'git checkout -b' not in cmd # Should not create a new branch + # Check that the second command contains the correct branch checkout + checkout_cmd = runtime.run_action_calls[1].command + assert 'git clone https://github.com/owner/repo.git repo' in clone_cmd + assert 'cd repo' in checkout_cmd + assert 'git checkout feature-branch' in checkout_cmd + assert 'git checkout -b' not in checkout_cmd # Should not create a new branch assert result == 'repo' From 6d2074d69b18016ecd641a3bb0ece1321a0eb7a3 Mon Sep 17 00:00:00 2001 From: llamantino <213239228+llamantino@users.noreply.github.com> Date: Sun, 1 Jun 2025 01:08:51 +0200 Subject: [PATCH 04/88] Fix broken links in README after docs site upgrade (#8829) Co-authored-by: llamantino <12345678+yourusername@users.noreply.github.com> --- README.md | 22 +++++++++++----------- README_CN.md | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 60c18e962928..cdeba9b4c90a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Join our Discord community Credits
- Check out the documentation + Check out the documentation Paper on Arxiv Evaluation Benchmark Score
@@ -42,11 +42,11 @@ which comes with $50 in free credits for new users. ## 💻 Running OpenHands Locally OpenHands can also run on your local system using Docker. -See the [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) guide for +See the [Running OpenHands](https://docs.all-hands.dev/usage/installation) guide for system requirements and more information. > [!WARNING] -> On a public network? See our [Hardened Docker Installation Guide](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation) +> On a public network? See our [Hardened Docker Installation Guide](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation) > to secure your deployment by restricting network binding and implementing additional security measures. @@ -68,7 +68,7 @@ You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)! When you open the application, you'll be asked to choose an LLM provider and add an API key. [Anthropic's Claude Sonnet 4](https://www.anthropic.com/api) (`anthropic/claude-sonnet-4-20250514`) -works best, but you have [many options](https://docs.all-hands.dev/modules/usage/llms). +works best, but you have [many options](https://docs.all-hands.dev/usage/llms). ## 💡 Other ways to run OpenHands @@ -80,22 +80,22 @@ works best, but you have [many options](https://docs.all-hands.dev/modules/usage > [get in touch with us](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform) > for advanced deployment options. -You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode), -interact with it via a [friendly CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), -or run it on tagged issues with [a github action](https://docs.all-hands.dev/modules/usage/how-to/github-action). +You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/usage/how-to/headless-mode), +interact with it via a [friendly CLI](https://docs.all-hands.dev/usage/how-to/cli-mode), +or run it on tagged issues with [a github action](https://docs.all-hands.dev/usage/how-to/github-action). -Visit [Running OpenHands](https://docs.all-hands.dev/modules/usage/installation) for more information and setup instructions. +Visit [Running OpenHands](https://docs.all-hands.dev/usage/installation) for more information and setup instructions. If you want to modify the OpenHands source code, check out [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). -Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting) can help. +Having issues? The [Troubleshooting Guide](https://docs.all-hands.dev/usage/troubleshooting) can help. ## 📖 Documentation Ask DeepWiki To learn more about the project, and for tips on using OpenHands, -check out our [documentation](https://docs.all-hands.dev/modules/usage/getting-started). +check out our [documentation](https://docs.all-hands.dev/usage/getting-started). There you'll find resources on how to use different LLM providers, troubleshooting resources, and advanced configuration options. diff --git a/README_CN.md b/README_CN.md index df43b9c1739c..d4e876ce6bd4 100644 --- a/README_CN.md +++ b/README_CN.md @@ -16,7 +16,7 @@ 加入我们的Discord社区 致谢
- 查看文档 + 查看文档 Arxiv论文 评估基准分数
@@ -42,11 +42,11 @@ OpenHands代理可以完成人类开发者能做的任何事情:修改代码 ## 💻 在本地运行OpenHands OpenHands也可以使用Docker在本地系统上运行。 -查看[运行OpenHands](https://docs.all-hands.dev/modules/usage/installation)指南了解 +查看[运行OpenHands](https://docs.all-hands.dev/usage/installation)指南了解 系统要求和更多信息。 > [!WARNING] -> 在公共网络上?请参阅我们的[强化Docker安装指南](https://docs.all-hands.dev/modules/usage/runtimes/docker#hardened-docker-installation) +> 在公共网络上?请参阅我们的[强化Docker安装指南](https://docs.all-hands.dev/usage/runtimes/docker#hardened-docker-installation) > 通过限制网络绑定和实施其他安全措施来保护您的部署。 @@ -68,7 +68,7 @@ docker run -it --rm --pull=always \ 打开应用程序时,您将被要求选择一个LLM提供商并添加API密钥。 [Anthropic的Claude Sonnet 4](https://www.anthropic.com/api)(`anthropic/claude-sonnet-4-20250514`) -效果最佳,但您还有[许多选择](https://docs.all-hands.dev/modules/usage/llms)。 +效果最佳,但您还有[许多选择](https://docs.all-hands.dev/usage/llms)。 ## 💡 运行OpenHands的其他方式 @@ -80,22 +80,22 @@ docker run -it --rm --pull=always \ > [与我们联系](https://docs.google.com/forms/d/e/1FAIpQLSet3VbGaz8z32gW9Wm-Grl4jpt5WgMXPgJ4EDPVmCETCBpJtQ/viewform) > 了解高级部署选项。 -您还可以[将OpenHands连接到本地文件系统](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -以可编程的[无头模式](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)运行OpenHands, -通过[友好的CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode)与其交互, -或使用[GitHub Action](https://docs.all-hands.dev/modules/usage/how-to/github-action)在标记的问题上运行它。 +您还可以[将OpenHands连接到本地文件系统](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +以可编程的[无头模式](https://docs.all-hands.dev/usage/how-to/headless-mode)运行OpenHands, +通过[友好的CLI](https://docs.all-hands.dev/usage/how-to/cli-mode)与其交互, +或使用[GitHub Action](https://docs.all-hands.dev/usage/how-to/github-action)在标记的问题上运行它。 -访问[运行OpenHands](https://docs.all-hands.dev/modules/usage/installation)获取更多信息和设置说明。 +访问[运行OpenHands](https://docs.all-hands.dev/usage/installation)获取更多信息和设置说明。 如果您想修改OpenHands源代码,请查看[Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)。 -遇到问题?[故障排除指南](https://docs.all-hands.dev/modules/usage/troubleshooting)可以提供帮助。 +遇到问题?[故障排除指南](https://docs.all-hands.dev/usage/troubleshooting)可以提供帮助。 ## 📖 文档 Ask DeepWiki 要了解有关项目的更多信息,以及使用OpenHands的技巧, -请查看我们的[文档](https://docs.all-hands.dev/modules/usage/getting-started)。 +请查看我们的[文档](https://docs.all-hands.dev/usage/getting-started)。 在那里,您将找到有关如何使用不同LLM提供商、 故障排除资源和高级配置选项的资源。 From 880c05ed94dd69a97b749d3f7ece43e9c5648487 Mon Sep 17 00:00:00 2001 From: llamantino <213239228+llamantino@users.noreply.github.com> Date: Sun, 1 Jun 2025 03:24:59 +0200 Subject: [PATCH 05/88] Fix all broken docs links across the project (#8830) Co-authored-by: llamantino <12345678+yourusername@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- Development.md | 2 +- .../current/usage/how-to/github-action.md | 2 +- .../current/usage/installation.mdx | 10 +++++----- .../current/usage/intro.mdx | 2 +- .../current/usage/how-to/github-action.md | 2 +- .../current/usage/installation.mdx | 10 +++++----- .../current/usage/intro.mdx | 2 +- .../current/usage/how-to/github-action.md | 2 +- .../current/usage/installation.mdx | 10 +++++----- .../current/usage/custom_sandbox_guide.md | 2 +- .../current/usage/how-to/github-action.md | 2 +- .../current/usage/installation.mdx | 10 +++++----- .../current/usage/intro.mdx | 2 +- docs/modules/usage/how-to/github-action.md | 2 +- docs/modules/usage/installation.mdx | 10 +++++----- docs/modules/usage/llms/local-llms.md | 2 +- evaluation/README.md | 2 +- .../features/settings/api-keys-manager.test.tsx | 2 +- .../src/components/features/home/home-header.tsx | 2 +- .../features/settings/api-keys-manager.tsx | 2 +- .../settings/mcp-settings/mcp-config-editor.tsx | 2 +- .../settings/mcp-settings/mcp-config-viewer.tsx | 2 +- frontend/src/components/shared/hero-heading.tsx | 2 +- .../src/components/shared/inputs/api-key-input.tsx | 2 +- .../shared/modals/settings/settings-form.tsx | 2 +- frontend/src/routes/llm-settings.tsx | 4 ++-- frontend/src/utils/tips.ts | 12 ++++++------ microagents/add_agent.md | 4 ++-- openhands/README.md | 2 +- openhands/cli/tui.py | 2 +- openhands/core/const/guide_url.py | 2 +- openhands/resolver/README.md | 2 +- openhands/runtime/README.md | 2 +- openhands/runtime/utils/runtime_build.py | 2 +- 35 files changed, 62 insertions(+), 62 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2ffc73c9c65b..994d0c4ef8c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ We have a separate doc [Development.md](https://github.com/All-Hands-AI/OpenHand There are many ways that you can contribute: 1. **Download and use** OpenHands, and send [issues](https://github.com/All-Hands-AI/OpenHands/issues) when you encounter something that isn't working or a feature that you'd like to see. -2. **Send feedback** after each session by [clicking the thumbs-up thumbs-down buttons](https://docs.all-hands.dev/modules/usage/feedback), so we can see where things are working and failing, and also build an open dataset for training code agents. +2. **Send feedback** after each session by [clicking the thumbs-up thumbs-down buttons](https://docs.all-hands.dev/usage/feedback), so we can see where things are working and failing, and also build an open dataset for training code agents. 3. **Improve the Codebase** by sending [PRs](#sending-pull-requests-to-openhands) (see details below). In particular, we have some [good first issues](https://github.com/All-Hands-AI/OpenHands/labels/good%20first%20issue) that may be ones to start on. ## What Can I Build? diff --git a/Development.md b/Development.md index b150db84aa37..e098ba32120d 100644 --- a/Development.md +++ b/Development.md @@ -76,7 +76,7 @@ variables in your terminal. The final configurations are set from highest to low Environment variables > config.toml variables > default variables **Note on Alternative Models:** -See [our documentation](https://docs.all-hands.dev/modules/usage/llms) for recommended models. +See [our documentation](https://docs.all-hands.dev/usage/llms) for recommended models. ### 4. Running the application diff --git a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md index 9bf02c6fd2bd..e70013b9b883 100644 --- a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md +++ b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md @@ -47,5 +47,5 @@ Les options de personnalisation que vous pouvez définir sont : | `LLM_MODEL` | Variable | Définir le LLM à utiliser avec OpenHands | `LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"` | | `OPENHANDS_MAX_ITER` | Variable | Définir la limite maximale d'itérations de l'agent | `OPENHANDS_MAX_ITER=10` | | `OPENHANDS_MACRO` | Variable | Personnaliser la macro par défaut pour invoquer le résolveur | `OPENHANDS_MACRO=@resolveit` | -| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variable | Sandbox personnalisé ([en savoir plus](https://docs.all-hands.dev/modules/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | +| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variable | Sandbox personnalisé ([en savoir plus](https://docs.all-hands.dev/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | | `TARGET_BRANCH` | Variable | Fusionner vers une branche autre que `main` | `TARGET_BRANCH="dev"` | diff --git a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/installation.mdx b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/installation.mdx index 68dbe576f254..0e8714aaad2d 100644 --- a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/installation.mdx +++ b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/installation.mdx @@ -73,10 +73,10 @@ docker run -it --rm --pull=always \ Vous trouverez OpenHands en cours d'exécution à l'adresse http://localhost:3000 ! -Vous pouvez également [connecter OpenHands à votre système de fichiers local](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -exécuter OpenHands en [mode headless](https://docs.all-hands.dev/modules/usage/how-to/headless-mode) scriptable, -interagir avec lui via une [CLI conviviale](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), -ou l'exécuter sur des problèmes étiquetés avec [une action GitHub](https://docs.all-hands.dev/modules/usage/how-to/github-action). +Vous pouvez également [connecter OpenHands à votre système de fichiers local](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +exécuter OpenHands en [mode headless](https://docs.all-hands.dev/usage/how-to/headless-mode) scriptable, +interagir avec lui via une [CLI conviviale](https://docs.all-hands.dev/usage/how-to/cli-mode), +ou l'exécuter sur des problèmes étiquetés avec [une action GitHub](https://docs.all-hands.dev/usage/how-to/github-action). ## Configuration @@ -118,4 +118,4 @@ Cette version est instable et est recommandée uniquement à des fins de test ou Pour le flux de travail de développement, consultez [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). -Vous rencontrez des problèmes ? Consultez notre [Guide de dépannage](https://docs.all-hands.dev/modules/usage/troubleshooting). +Vous rencontrez des problèmes ? Consultez notre [Guide de dépannage](https://docs.all-hands.dev/usage/troubleshooting). diff --git a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/intro.mdx b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/intro.mdx index c09eb6b2502b..ccb8af7822a4 100644 --- a/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/intro.mdx +++ b/docs/i18n/fr/docusaurus-plugin-content-docs/current/usage/intro.mdx @@ -91,7 +91,7 @@ Si vous souhaitez utiliser la version **(instable !)** la plus récente, vous po Pour le workflow de développement, consultez [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). -Avez-vous des problèmes ? Consultez notre [Guide de dépannage](https://docs.all-hands.dev/modules/usage/troubleshooting). +Avez-vous des problèmes ? Consultez notre [Guide de dépannage](https://docs.all-hands.dev/usage/troubleshooting). :::warning OpenHands est actuellement en cours de développement, mais vous pouvez déjà exécuter la version alpha pour voir le système de bout en bout en action. diff --git a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md index 3e8dc8b921ef..b614f9a3795b 100644 --- a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md +++ b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md @@ -47,5 +47,5 @@ GitHub resolverは、動作をカスタマイズするために有効な[リポ | `LLM_MODEL` | 変数 | OpenHandsで使用するLLMを設定 | `LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"` | | `OPENHANDS_MAX_ITER` | 変数 | エージェントの反復回数の最大制限を設定 | `OPENHANDS_MAX_ITER=10` | | `OPENHANDS_MACRO` | 変数 | リゾルバーを呼び出すためのデフォルトマクロをカスタマイズ | `OPENHANDS_MACRO=@resolveit` | -| `OPENHANDS_BASE_CONTAINER_IMAGE` | 変数 | カスタムサンドボックス([詳細](https://docs.all-hands.dev/modules/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | +| `OPENHANDS_BASE_CONTAINER_IMAGE` | 変数 | カスタムサンドボックス([詳細](https://docs.all-hands.dev/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | | `TARGET_BRANCH` | 変数 | `main`以外のブランチにマージ | `TARGET_BRANCH="dev"` | diff --git a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/installation.mdx b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/installation.mdx index 9de2b79bd2c2..8bbcd014a694 100644 --- a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/installation.mdx +++ b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/installation.mdx @@ -73,10 +73,10 @@ docker run -it --rm --pull=always \ OpenHandsは http://localhost:3000 で実行されています! -また、[OpenHandsをローカルファイルシステムに接続](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem)したり、 -OpenHandsを[ヘッドレスモード](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)でスクリプト実行したり、 -[使いやすいCLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode)を介して操作したり、 -[GitHubアクション](https://docs.all-hands.dev/modules/usage/how-to/github-action)でタグ付けされた課題に対して実行したりすることもできます。 +また、[OpenHandsをローカルファイルシステムに接続](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem)したり、 +OpenHandsを[ヘッドレスモード](https://docs.all-hands.dev/usage/how-to/headless-mode)でスクリプト実行したり、 +[使いやすいCLI](https://docs.all-hands.dev/usage/how-to/cli-mode)を介して操作したり、 +[GitHubアクション](https://docs.all-hands.dev/usage/how-to/github-action)でタグ付けされた課題に対して実行したりすることもできます。 ## セットアップ @@ -117,4 +117,4 @@ SemVerを使用しているため、`0.9`は自動的に最新の`0.9.x`リリ 開発ワークフローについては、[Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)を参照してください。 -問題がありますか?[トラブルシューティングガイド](https://docs.all-hands.dev/modules/usage/troubleshooting)をご確認ください。 +問題がありますか?[トラブルシューティングガイド](https://docs.all-hands.dev/usage/troubleshooting)をご確認ください。 diff --git a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/intro.mdx b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/intro.mdx index e5cc0abe7cea..3bfb4d3dc1a8 100644 --- a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/intro.mdx +++ b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/intro.mdx @@ -91,7 +91,7 @@ OpenHandsはこのワークスペースフォルダにのみアクセスでき 開発ワークフローについては、[Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)を参照してください。 -問題がありますか?[トラブルシューティングガイド](https://docs.all-hands.dev/modules/usage/troubleshooting)をご確認ください。 +問題がありますか?[トラブルシューティングガイド](https://docs.all-hands.dev/usage/troubleshooting)をご確認ください。 :::warning OpenHandsは現在開発中ですが、アルファ版を実行してエンドツーエンドのシステムを動作させることができます。 diff --git a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md index d9073fa5e6f9..c67d967f58f0 100644 --- a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md +++ b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md @@ -47,5 +47,5 @@ As opções de personalização que você pode definir são: | `LLM_MODEL` | Variável | Define o LLM a ser usado com OpenHands | `LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"` | | `OPENHANDS_MAX_ITER` | Variável | Define o limite máximo para iterações do agente | `OPENHANDS_MAX_ITER=10` | | `OPENHANDS_MACRO` | Variável | Personaliza a macro padrão para invocar o resolver | `OPENHANDS_MACRO=@resolveit` | -| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variável | Sandbox personalizado ([saiba mais](https://docs.all-hands.dev/modules/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | +| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variável | Sandbox personalizado ([saiba mais](https://docs.all-hands.dev/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | | `TARGET_BRANCH` | Variável | Mesclar para uma branch diferente de `main` | `TARGET_BRANCH="dev"` | diff --git a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/installation.mdx b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/installation.mdx index 77157d4af98b..f238ddeb13a1 100644 --- a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/installation.mdx +++ b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/installation.mdx @@ -73,10 +73,10 @@ docker run -it --rm --pull=always \ Você encontrará o OpenHands rodando em http://localhost:3000! -Você também pode [conectar o OpenHands ao seu sistema de arquivos local](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -executar o OpenHands em um [modo headless](https://docs.all-hands.dev/modules/usage/how-to/headless-mode) programável, -interagir com ele através de uma [CLI amigável](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), -ou executá-lo em issues marcadas com [uma ação do GitHub](https://docs.all-hands.dev/modules/usage/how-to/github-action). +Você também pode [conectar o OpenHands ao seu sistema de arquivos local](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +executar o OpenHands em um [modo headless](https://docs.all-hands.dev/usage/how-to/headless-mode) programável, +interagir com ele através de uma [CLI amigável](https://docs.all-hands.dev/usage/how-to/cli-mode), +ou executá-lo em issues marcadas com [uma ação do GitHub](https://docs.all-hands.dev/usage/how-to/github-action). ## Configuração @@ -118,4 +118,4 @@ Esta versão é instável e é recomendada apenas para fins de teste ou desenvol Para o fluxo de trabalho de desenvolvimento, consulte [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). -Está tendo problemas? Confira nosso [Guia de Solução de Problemas](https://docs.all-hands.dev/modules/usage/troubleshooting). +Está tendo problemas? Confira nosso [Guia de Solução de Problemas](https://docs.all-hands.dev/usage/troubleshooting). diff --git a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/custom_sandbox_guide.md b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/custom_sandbox_guide.md index 55a0a6e44f5a..ec5c5662a22d 100644 --- a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/custom_sandbox_guide.md +++ b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/custom_sandbox_guide.md @@ -78,7 +78,7 @@ base_container_image="custom_image" ## 技术解释 -请参考[运行时文档中自定义 Docker 镜像的章节](https://docs.all-hands.dev/modules/usage/architecture/runtime#advanced-how-openhands-builds-and-maintains-od-runtime-images)获取更详细的解释。 +请参考[运行时文档中自定义 Docker 镜像的章节](https://docs.all-hands.dev/usage/architecture/runtime#advanced-how-openhands-builds-and-maintains-od-runtime-images)获取更详细的解释。 ## 故障排除 / 错误 diff --git a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md index 92533dbdda18..b192774ecf1b 100644 --- a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md +++ b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/how-to/github-action.md @@ -47,5 +47,5 @@ GitHub resolver 将自动检查有效的[仓库密钥](https://docs.github.com/e | `LLM_MODEL` | 变量 | 设置与 OpenHands 一起使用的 LLM | `LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"` | | `OPENHANDS_MAX_ITER` | 变量 | 设置代理迭代的最大限制 | `OPENHANDS_MAX_ITER=10` | | `OPENHANDS_MACRO` | 变量 | 自定义用于调用 resolver 的默认宏 | `OPENHANDS_MACRO=@resolveit` | -| `OPENHANDS_BASE_CONTAINER_IMAGE` | 变量 | 自定义沙箱([了解更多](https://docs.all-hands.dev/modules/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | +| `OPENHANDS_BASE_CONTAINER_IMAGE` | 变量 | 自定义沙箱([了解更多](https://docs.all-hands.dev/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | | `TARGET_BRANCH` | 变量 | 合并到 `main` 以外的分支 | `TARGET_BRANCH="dev"` | diff --git a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/installation.mdx b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/installation.mdx index a71e1ded1a35..ffc3b74cc385 100644 --- a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/installation.mdx +++ b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/installation.mdx @@ -73,10 +73,10 @@ docker run -it --rm --pull=always \ OpenHands 将在 http://localhost:3000 运行! -你还可以[将 OpenHands 连接到本地文件系统](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -以[无头模式](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)运行 OpenHands, -通过[友好的 CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode)与其交互, -或者使用 [GitHub action](https://docs.all-hands.dev/modules/usage/how-to/github-action) 在标记的问题上运行它。 +你还可以[将 OpenHands 连接到本地文件系统](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +以[无头模式](https://docs.all-hands.dev/usage/how-to/headless-mode)运行 OpenHands, +通过[友好的 CLI](https://docs.all-hands.dev/usage/how-to/cli-mode)与其交互, +或者使用 [GitHub action](https://docs.all-hands.dev/usage/how-to/github-action) 在标记的问题上运行它。 ## 设置 @@ -116,4 +116,4 @@ OpenHands 需要 API 密钥才能访问大多数语言模型。以下是从推 有关开发工作流程,请参阅 [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)。 -遇到问题?请查看我们的[故障排除指南](https://docs.all-hands.dev/modules/usage/troubleshooting)。 +遇到问题?请查看我们的[故障排除指南](https://docs.all-hands.dev/usage/troubleshooting)。 diff --git a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/intro.mdx b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/intro.mdx index 7e30ef835264..8110b8ffb403 100644 --- a/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/intro.mdx +++ b/docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/usage/intro.mdx @@ -91,7 +91,7 @@ OpenHands 只会访问这个工作区文件夹。它在一个安全的 docker 有关开发工作流程,请参阅 [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)。 -遇到问题了吗?查看我们的 [故障排除指南](https://docs.all-hands.dev/modules/usage/troubleshooting)。 +遇到问题了吗?查看我们的 [故障排除指南](https://docs.all-hands.dev/usage/troubleshooting)。 :::warning OpenHands 目前正在开发中,但你已经可以运行 alpha 版本来查看端到端系统的运作情况。 diff --git a/docs/modules/usage/how-to/github-action.md b/docs/modules/usage/how-to/github-action.md index 2c985eec625e..b1429289724e 100644 --- a/docs/modules/usage/how-to/github-action.md +++ b/docs/modules/usage/how-to/github-action.md @@ -47,6 +47,6 @@ The customization options you can set are: | `LLM_MODEL` | Variable | Set the LLM to use with OpenHands | `LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"` | | `OPENHANDS_MAX_ITER` | Variable | Set max limit for agent iterations | `OPENHANDS_MAX_ITER=10` | | `OPENHANDS_MACRO` | Variable | Customize default macro for invoking the resolver | `OPENHANDS_MACRO=@resolveit` | -| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variable | Custom Sandbox ([learn more](https://docs.all-hands.dev/modules/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | +| `OPENHANDS_BASE_CONTAINER_IMAGE` | Variable | Custom Sandbox ([learn more](https://docs.all-hands.dev/usage/how-to/custom-sandbox-guide)) | `OPENHANDS_BASE_CONTAINER_IMAGE="custom_image"` | | `TARGET_BRANCH` | Variable | Merge to branch other than `main` | `TARGET_BRANCH="dev"` | | `TARGET_RUNNER` | Variable | Target runner to execute the agent workflow (default ubuntu-latest) | `TARGET_RUNNER="custom-runner"` | diff --git a/docs/modules/usage/installation.mdx b/docs/modules/usage/installation.mdx index 56f2465d9ab8..9f843898384c 100644 --- a/docs/modules/usage/installation.mdx +++ b/docs/modules/usage/installation.mdx @@ -78,10 +78,10 @@ docker run -it --rm --pull=always \ You'll find OpenHands running at http://localhost:3000! -You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/modules/usage/runtimes/docker#connecting-to-your-filesystem), -run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode), -interact with it via a [friendly CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), -or run it on tagged issues with [a GitHub action](https://docs.all-hands.dev/modules/usage/how-to/github-action). +You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/usage/runtimes/docker#connecting-to-your-filesystem), +run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/usage/how-to/headless-mode), +interact with it via a [friendly CLI](https://docs.all-hands.dev/usage/how-to/cli-mode), +or run it on tagged issues with [a GitHub action](https://docs.all-hands.dev/usage/how-to/github-action). ## Setup @@ -123,4 +123,4 @@ This version is unstable and is recommended for testing or development purposes For the development workflow, see [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md). -Are you having trouble? Check out our [Troubleshooting Guide](https://docs.all-hands.dev/modules/usage/troubleshooting). +Are you having trouble? Check out our [Troubleshooting Guide](https://docs.all-hands.dev/usage/troubleshooting). diff --git a/docs/modules/usage/llms/local-llms.md b/docs/modules/usage/llms/local-llms.md index f9fd17b3228f..d7e6aab813b3 100644 --- a/docs/modules/usage/llms/local-llms.md +++ b/docs/modules/usage/llms/local-llms.md @@ -50,7 +50,7 @@ We recommend using [LMStudio](https://lmstudio.ai/) for serving these models loc ### Start OpenHands with locally served model -Check [the installation guide](https://docs.all-hands.dev/modules/usage/installation) to make sure you have all the prerequisites for running OpenHands. +Check [the installation guide](https://docs.all-hands.dev/usage/installation) to make sure you have all the prerequisites for running OpenHands. ```bash export LMSTUDIO_MODEL_NAME="imported-models/uncategorized/devstralq4_k_m.gguf" # <- Replace this with the model name you copied from LMStudio diff --git a/evaluation/README.md b/evaluation/README.md index 91d608d8f531..b0cddcbea564 100644 --- a/evaluation/README.md +++ b/evaluation/README.md @@ -120,7 +120,7 @@ You can start your own fork of [our huggingface evaluation outputs](https://hugg ## For Benchmark Developers -To learn more about how to integrate your benchmark into OpenHands, check out [tutorial here](https://docs.all-hands.dev/modules/usage/how-to/evaluation-harness). Briefly, +To learn more about how to integrate your benchmark into OpenHands, check out [tutorial here](https://docs.all-hands.dev/usage/how-to/evaluation-harness). Briefly, - Each subfolder contains a specific benchmark or experiment. For example, [`evaluation/benchmarks/swe_bench`](./benchmarks/swe_bench) should contain all the preprocessing/evaluation/analysis scripts. diff --git a/frontend/__tests__/components/features/settings/api-keys-manager.test.tsx b/frontend/__tests__/components/features/settings/api-keys-manager.test.tsx index 2f8570e8596e..711c50a19443 100644 --- a/frontend/__tests__/components/features/settings/api-keys-manager.test.tsx +++ b/frontend/__tests__/components/features/settings/api-keys-manager.test.tsx @@ -52,7 +52,7 @@ describe("ApiKeysManager", () => { // Find the link to the API documentation const link = screen.getByRole("link"); expect(link).toBeInTheDocument(); - expect(link).toHaveAttribute("href", "https://docs.all-hands.dev/modules/usage/cloud/cloud-api"); + expect(link).toHaveAttribute("href", "https://docs.all-hands.dev/usage/cloud/cloud-api"); expect(link).toHaveAttribute("target", "_blank"); expect(link).toHaveAttribute("rel", "noopener noreferrer"); }); diff --git a/frontend/src/components/features/home/home-header.tsx b/frontend/src/components/features/home/home-header.tsx index 176421c9ced1..cf04a167ae23 100644 --- a/frontend/src/components/features/home/home-header.tsx +++ b/frontend/src/components/features/home/home-header.tsx @@ -43,7 +43,7 @@ export function HomeHeader() {

{t("HOME$NOT_SURE_HOW_TO_START")}{" "}

diff --git a/frontend/src/routes/llm-settings.tsx b/frontend/src/routes/llm-settings.tsx index 9c719519c933..29ae2a4c935d 100644 --- a/frontend/src/routes/llm-settings.tsx +++ b/frontend/src/routes/llm-settings.tsx @@ -304,7 +304,7 @@ function LlmSettingsScreen() { testId="llm-api-key-help-anchor" text={t(I18nKey.SETTINGS$DONT_KNOW_API_KEY)} linkText={t(I18nKey.SETTINGS$CLICK_FOR_INSTRUCTIONS)} - href="https://docs.all-hands.dev/modules/usage/installation#getting-an-api-key" + href="https://docs.all-hands.dev/usage/installation#getting-an-api-key" /> None: # Footer print_formatted_text( HTML( - 'Learn more at: https://docs.all-hands.dev/modules/usage/getting-started' + 'Learn more at: https://docs.all-hands.dev/usage/getting-started' ) ) diff --git a/openhands/core/const/guide_url.py b/openhands/core/const/guide_url.py index c401de8bb6a1..62af6e547583 100644 --- a/openhands/core/const/guide_url.py +++ b/openhands/core/const/guide_url.py @@ -1 +1 @@ -TROUBLESHOOTING_URL = 'https://docs.all-hands.dev/modules/usage/troubleshooting' +TROUBLESHOOTING_URL = 'https://docs.all-hands.dev/usage/troubleshooting' diff --git a/openhands/resolver/README.md b/openhands/resolver/README.md index 29c43398f128..1e7612c61ced 100644 --- a/openhands/resolver/README.md +++ b/openhands/resolver/README.md @@ -40,7 +40,7 @@ Follow these steps to use this workflow in your own repository: Note: You can set these secrets at the organization level to use across multiple repositories. -6. Set up any [custom configurations required](https://docs.all-hands.dev/modules/usage/how-to/github-action#custom-configurations) +6. Set up any [custom configurations required](https://docs.all-hands.dev/usage/how-to/github-action#custom-configurations) 7. Usage: There are two ways to trigger the OpenHands agent: diff --git a/openhands/runtime/README.md b/openhands/runtime/README.md index 61347656b502..69501f31add7 100644 --- a/openhands/runtime/README.md +++ b/openhands/runtime/README.md @@ -3,7 +3,7 @@ ## Introduction The OpenHands Runtime folder contains the core components responsible for executing actions and managing the runtime environment for the OpenHands project. This README provides an overview of the main components and their interactions. -You can learn more about how the runtime works in the [Docker Runtime](https://docs.all-hands.dev/modules/usage/architecture/runtime) documentation. +You can learn more about how the runtime works in the [Docker Runtime](https://docs.all-hands.dev/usage/architecture/runtime) documentation. ## Main Components diff --git a/openhands/runtime/utils/runtime_build.py b/openhands/runtime/utils/runtime_build.py index 0f2b26174d2c..ff85c7d68173 100644 --- a/openhands/runtime/utils/runtime_build.py +++ b/openhands/runtime/utils/runtime_build.py @@ -129,7 +129,7 @@ def build_runtime_image( Returns: - str: :. Where MD5 hash is the hash of the docker build folder - See https://docs.all-hands.dev/modules/usage/architecture/runtime for more details. + See https://docs.all-hands.dev/usage/architecture/runtime for more details. """ if build_folder is None: with tempfile.TemporaryDirectory() as temp_dir: From 9fb5d2109a1146a14c7d052204d081492a8fafc4 Mon Sep 17 00:00:00 2001 From: KianoshArian <68875392+KianoshArian@users.noreply.github.com> Date: Sun, 1 Jun 2025 16:31:08 +0330 Subject: [PATCH 06/88] fix(frontend): fix mobile view of settings page (#8826) --- .../settings/app-settings/language-input.tsx | 2 +- .../git-settings/github-token-input.tsx | 4 ++-- .../git-settings/gitlab-token-input.tsx | 4 ++-- .../settings/secrets-settings/secret-form.tsx | 10 +++++----- frontend/src/routes/llm-settings.tsx | 18 +++++++++--------- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/features/settings/app-settings/language-input.tsx b/frontend/src/components/features/settings/app-settings/language-input.tsx index 67af79bebe14..4e41c71f6221 100644 --- a/frontend/src/components/features/settings/app-settings/language-input.tsx +++ b/frontend/src/components/features/settings/app-settings/language-input.tsx @@ -28,7 +28,7 @@ export function LanguageInput({ }))} defaultSelectedKey={defaultKey} isClearable={false} - wrapperClassName="w-[680px]" + wrapperClassName="w-full max-w-[680px]" /> ); } diff --git a/frontend/src/components/features/settings/git-settings/github-token-input.tsx b/frontend/src/components/features/settings/git-settings/github-token-input.tsx index bec0f4fffe6b..15b51b5ef59e 100644 --- a/frontend/src/components/features/settings/git-settings/github-token-input.tsx +++ b/frontend/src/components/features/settings/git-settings/github-token-input.tsx @@ -29,7 +29,7 @@ export function GitHubTokenInput({ onChange={onChange} label={t(I18nKey.GITHUB$TOKEN_LABEL)} type="password" - className="w-[680px]" + className="w-full max-w-[680px]" placeholder={isGitHubTokenSet ? "" : ""} startContent={ isGitHubTokenSet && ( @@ -47,7 +47,7 @@ export function GitHubTokenInput({ testId="github-host-input" label={t(I18nKey.GITHUB$HOST_LABEL)} type="text" - className="w-[680px]" + className="w-full max-w-[680px]" placeholder="github.com" defaultValue={githubHostSet || undefined} startContent={ diff --git a/frontend/src/components/features/settings/git-settings/gitlab-token-input.tsx b/frontend/src/components/features/settings/git-settings/gitlab-token-input.tsx index 991ada89428a..fa0e1e77e3d2 100644 --- a/frontend/src/components/features/settings/git-settings/gitlab-token-input.tsx +++ b/frontend/src/components/features/settings/git-settings/gitlab-token-input.tsx @@ -29,7 +29,7 @@ export function GitLabTokenInput({ onChange={onChange} label={t(I18nKey.GITLAB$TOKEN_LABEL)} type="password" - className="w-[680px]" + className="w-full max-w-[680px]" placeholder={isGitLabTokenSet ? "" : ""} startContent={ isGitLabTokenSet && ( @@ -47,7 +47,7 @@ export function GitLabTokenInput({ testId="gitlab-host-input" label={t(I18nKey.GITLAB$HOST_LABEL)} type="text" - className="w-[680px]" + className="w-full max-w-[680px]" placeholder="gitlab.com" defaultValue={gitlabHostSet || undefined} startContent={ diff --git a/frontend/src/components/features/settings/secrets-settings/secret-form.tsx b/frontend/src/components/features/settings/secrets-settings/secret-form.tsx index 7ad39e3853d8..984fb0941026 100644 --- a/frontend/src/components/features/settings/secrets-settings/secret-form.tsx +++ b/frontend/src/components/features/settings/secrets-settings/secret-form.tsx @@ -141,7 +141,7 @@ export function SecretForm({ name="secret-name" type="text" label="Name" - className="w-[350px]" + className="w-full max-w-[350px]" required defaultValue={mode === "edit" && selectedSecret ? selectedSecret : ""} placeholder="e.g. OpenAI_API_Key" @@ -150,14 +150,14 @@ export function SecretForm({ {error &&

{error}

} {mode === "add" && ( -