Merge branch 'main' into openhands/fix-saas-page-title

This commit is contained in:
Graham Neubig
2025-12-30 15:07:45 -05:00
committed by GitHub
152 changed files with 1462 additions and 124 deletions

View File

@@ -43,7 +43,7 @@ jobs:
⚠️ This PR contains **migrations**
- name: Comment warning on PR
uses: peter-evans/create-or-update-comment@v4
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}

View File

@@ -64,7 +64,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.6.0
uses: docker/setup-qemu-action@v3.7.0
with:
image: tonistiigi/binfmt:latest
- name: Login to GHCR
@@ -102,7 +102,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.6.0
uses: docker/setup-qemu-action@v3.7.0
with:
image: tonistiigi/binfmt:latest
- name: Login to GHCR

View File

@@ -118,7 +118,7 @@ jobs:
contains(github.event.review.body, '@openhands-agent-exp')
)
)
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ env.pythonLocation }}/lib/python3.12/site-packages/*
key: ${{ runner.os }}-pip-openhands-resolver-${{ hashFiles('/tmp/requirements.txt') }}

View File

@@ -161,7 +161,7 @@ poetry run pytest ./tests/unit/test_*.py
To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker
container image by setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/openhands/runtime:1.0-nikolaik`
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/openhands/runtime:1.1-nikolaik`
## Develop inside Docker container

View File

@@ -12,7 +12,7 @@ services:
- SANDBOX_API_HOSTNAME=host.docker.internal
- DOCKER_HOST_ADDR=host.docker.internal
#
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/openhands/runtime:1.0-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/openhands/runtime:1.1-nikolaik}
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:

View File

@@ -7,7 +7,7 @@ services:
image: openhands:latest
container_name: openhands-app-${DATE:-}
environment:
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.openhands.dev/openhands/runtime:1.0-nikolaik}
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.openhands.dev/openhands/runtime:1.1-nikolaik}
#- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} # enable this only if you want a specific non-root sandbox user but you will have to manually adjust permissions of ~/.openhands for this user
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
ports:

View File

@@ -50,7 +50,7 @@ First run this to retrieve Github App secrets
```
gcloud auth application-default login
gcloud config set project global-432717
local/decrypt_env.sh
enterprise_local/decrypt_env.sh /path/to/root/of/deploy/repo
```
Now run this to generate a `.env` file, which will used to run SAAS locally

4
enterprise/enterprise_local/decrypt_env.sh Normal file → Executable file
View File

@@ -4,12 +4,12 @@ set -euo pipefail
# Check if DEPLOY_DIR argument was provided
if [ $# -lt 1 ]; then
echo "Usage: $0 <DEPLOY_DIR>"
echo "Example: $0 /path/to/deploy"
echo "Example: $0 /path/to/root/of/deploy/repo"
exit 1
fi
# Normalize path (remove trailing slash)
DEPLOY_DIR="${DEPLOY_DIR%/}"
DEPLOY_DIR="${1%/}"
# Function to decrypt and rename
decrypt_and_move() {

View File

@@ -6,7 +6,7 @@ from datetime import datetime
from enum import Enum
from typing import Any
from github import Github, GithubIntegration
from github import Auth, Github, GithubIntegration
from integrations.github.github_view import (
GithubIssue,
)
@@ -84,7 +84,7 @@ class GitHubDataCollector:
# self.full_saved_pr_path = 'github_data/prs/{}-{}/data.json'
self.full_saved_pr_path = 'prs/github/{}-{}/data.json'
self.github_integration = GithubIntegration(
GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY
auth=Auth.AppAuth(GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY)
)
self.conversation_id = None

View File

@@ -1,6 +1,6 @@
from types import MappingProxyType
from github import Github, GithubIntegration
from github import Auth, Github, GithubIntegration
from integrations.github.data_collector import GitHubDataCollector
from integrations.github.github_solvability import summarize_issue_solvability
from integrations.github.github_view import (
@@ -43,7 +43,7 @@ class GithubManager(Manager):
self.token_manager = token_manager
self.data_collector = data_collector
self.github_integration = GithubIntegration(
GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY
auth=Auth.AppAuth(GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY)
)
self.jinja_env = Environment(

View File

@@ -1,7 +1,7 @@
from dataclasses import dataclass
from uuid import UUID, uuid4
from github import Github, GithubIntegration
from github import Auth, Github, GithubIntegration
from github.Issue import Issue
from integrations.github.github_types import (
WorkflowRun,
@@ -729,7 +729,7 @@ class GithubFactory:
def _interact_with_github() -> Issue | None:
with GithubIntegration(
GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY
auth=Auth.AppAuth(GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY)
) as integration:
access_token = integration.get_access_token(
payload['installation']['id']
@@ -867,7 +867,7 @@ class GithubFactory:
access_token = ''
with GithubIntegration(
GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY
auth=Auth.AppAuth(GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY)
) as integration:
access_token = integration.get_access_token(installation_id).token

26
enterprise/poetry.lock generated
View File

@@ -5836,14 +5836,14 @@ llama = ["llama-index (>=0.12.29,<0.13.0)", "llama-index-core (>=0.12.29,<0.13.0
[[package]]
name = "openhands-agent-server"
version = "1.7.1"
version = "1.7.3"
description = "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent"
optional = false
python-versions = ">=3.12"
groups = ["main"]
files = [
{file = "openhands_agent_server-1.7.1-py3-none-any.whl", hash = "sha256:e5c57f1b73293d00a68b77f9d290f59d9e2217d9df844fb01c7d2f929c3417f4"},
{file = "openhands_agent_server-1.7.1.tar.gz", hash = "sha256:c82e1e6748ea3b4278ef2ee72f091dc37da6667c854b3aa3c0bc616086a82310"},
{file = "openhands_agent_server-1.7.3-py3-none-any.whl", hash = "sha256:456e7162cefec8ed7fda61433180b3f867265e15c7151b3a2e3e02546c9d9b6d"},
{file = "openhands_agent_server-1.7.3.tar.gz", hash = "sha256:2c06dc497c38050d445559da2825d4d69fe84af90289c82a95317e45359cc547"},
]
[package.dependencies]
@@ -5860,7 +5860,7 @@ wsproto = ">=1.2.0"
[[package]]
name = "openhands-ai"
version = "0.0.0-post.5742+ee50f333b"
version = "0.0.0-post.5769+b5758b160"
description = "OpenHands: Code Less, Make More"
optional = false
python-versions = "^3.12,<3.14"
@@ -5902,9 +5902,9 @@ memory-profiler = "^0.61.0"
numpy = "*"
openai = "2.8.0"
openhands-aci = "0.3.2"
openhands-agent-server = "1.7.1"
openhands-sdk = "1.7.1"
openhands-tools = "1.7.1"
openhands-agent-server = "1.7.3"
openhands-sdk = "1.7.3"
openhands-tools = "1.7.3"
opentelemetry-api = "^1.33.1"
opentelemetry-exporter-otlp-proto-grpc = "^1.33.1"
pathspec = "^0.12.1"
@@ -5960,14 +5960,14 @@ url = ".."
[[package]]
name = "openhands-sdk"
version = "1.7.1"
version = "1.7.3"
description = "OpenHands SDK - Core functionality for building AI agents"
optional = false
python-versions = ">=3.12"
groups = ["main"]
files = [
{file = "openhands_sdk-1.7.1-py3-none-any.whl", hash = "sha256:e097e34dfbd45f38225ae2ff4830702424bcf742bc197b5a811540a75265b135"},
{file = "openhands_sdk-1.7.1.tar.gz", hash = "sha256:e13d1fe8bf14dffd91e9080608072a989132c981cf9bfcd124fa4f7a68a13691"},
{file = "openhands_sdk-1.7.3-py3-none-any.whl", hash = "sha256:afbce9c9e7d1167d9b9610673657fbbcd454b04f0151d943418d897de790aeed"},
{file = "openhands_sdk-1.7.3.tar.gz", hash = "sha256:7fa0cde9148ab905e24346b50f2d7267fb6dde32ec8dcbc1c7d35ced6e0233aa"},
]
[package.dependencies]
@@ -5987,14 +5987,14 @@ boto3 = ["boto3 (>=1.35.0)"]
[[package]]
name = "openhands-tools"
version = "1.7.1"
version = "1.7.3"
description = "OpenHands Tools - Runtime tools for AI agents"
optional = false
python-versions = ">=3.12"
groups = ["main"]
files = [
{file = "openhands_tools-1.7.1-py3-none-any.whl", hash = "sha256:e25815f24925e94fbd4d8c3fd9b2147a0556fde595bf4f80a7dbba1014ea3c86"},
{file = "openhands_tools-1.7.1.tar.gz", hash = "sha256:f3823f7bd302c78969c454730cf793eb63109ce2d986e78585989c53986cc966"},
{file = "openhands_tools-1.7.3-py3-none-any.whl", hash = "sha256:e823f5a47936dd23221cb4eb846d62b59dce5be69210330095fc242772e71d27"},
{file = "openhands_tools-1.7.3.tar.gz", hash = "sha256:f2779cc5ca3b78b9afebb7617006da8069c12b41e6d67cbf0cc8de5d819005f8"},
]
[package.dependencies]

View File

@@ -38,6 +38,8 @@ LITE_LLM_API_URL = os.environ.get(
)
LITE_LLM_TEAM_ID = os.environ.get('LITE_LLM_TEAM_ID', None)
LITE_LLM_API_KEY = os.environ.get('LITE_LLM_API_KEY', None)
# Timeout in seconds for BYOR key verification requests to LiteLLM
BYOR_KEY_VERIFICATION_TIMEOUT = 5.0
SUBSCRIPTION_PRICE_DATA = {
'MONTHLY_SUBSCRIPTION': {
'unit_amount': 2000,

View File

@@ -4,7 +4,11 @@ import httpx
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, field_validator
from server.config import get_config
from server.constants import LITE_LLM_API_KEY, LITE_LLM_API_URL
from server.constants import (
BYOR_KEY_VERIFICATION_TIMEOUT,
LITE_LLM_API_KEY,
LITE_LLM_API_URL,
)
from storage.api_key_store import ApiKeyStore
from storage.database import session_maker
from storage.saas_settings_store import SaasSettingsStore
@@ -112,6 +116,70 @@ async def generate_byor_key(user_id: str) -> str | None:
return None
async def verify_byor_key_in_litellm(byor_key: str, user_id: str) -> bool:
"""Verify that a BYOR key is valid in LiteLLM by making a lightweight API call.
Args:
byor_key: The BYOR key to verify
user_id: The user ID for logging purposes
Returns:
True if the key is verified as valid, False if verification fails or key is invalid.
Returns False on network errors/timeouts to ensure we don't return potentially invalid keys.
"""
if not (LITE_LLM_API_URL and byor_key):
return False
try:
async with httpx.AsyncClient(
verify=httpx_verify_option(),
timeout=BYOR_KEY_VERIFICATION_TIMEOUT,
) as client:
# Make a lightweight request to verify the key
# Using /v1/models endpoint as it's lightweight and requires authentication
response = await client.get(
f'{LITE_LLM_API_URL}/v1/models',
headers={
'Authorization': f'Bearer {byor_key}',
},
)
# Only 200 status code indicates valid key
if response.status_code == 200:
logger.debug(
'BYOR key verification successful',
extra={'user_id': user_id},
)
return True
# All other status codes (401, 403, 500, etc.) are treated as invalid
# This includes authentication errors and server errors
logger.warning(
'BYOR key verification failed - treating as invalid',
extra={
'user_id': user_id,
'status_code': response.status_code,
'key_prefix': byor_key[:10] + '...'
if len(byor_key) > 10
else byor_key,
},
)
return False
except (httpx.TimeoutException, Exception) as e:
# Any exception (timeout, network error, etc.) means we can't verify
# Return False to trigger regeneration rather than returning potentially invalid key
logger.warning(
'BYOR key verification error - treating as invalid to ensure key validity',
extra={
'user_id': user_id,
'error': str(e),
'error_type': type(e).__name__,
},
)
return False
async def delete_byor_key_from_litellm(user_id: str, byor_key: str) -> bool:
"""Delete the BYOR key from LiteLLM using the key directly."""
if not (LITE_LLM_API_KEY and LITE_LLM_API_URL):
@@ -278,18 +346,44 @@ async def delete_api_key(key_id: int, user_id: str = Depends(get_user_id)):
@api_router.get('/llm/byor', response_model=LlmApiKeyResponse)
async def get_llm_api_key_for_byor(user_id: str = Depends(get_user_id)):
"""Get the LLM API key for BYOR (Bring Your Own Runtime) for the authenticated user."""
"""Get the LLM API key for BYOR (Bring Your Own Runtime) for the authenticated user.
This endpoint validates that the key exists in LiteLLM before returning it.
If validation fails, it automatically generates a new key to ensure users
always receive a working key.
"""
try:
# Check if the BYOR key exists in the database
byor_key = await get_byor_key_from_db(user_id)
if byor_key:
return {'key': byor_key}
# Validate that the key is actually registered in LiteLLM
is_valid = await verify_byor_key_in_litellm(byor_key, user_id)
if is_valid:
return {'key': byor_key}
else:
# Key exists in DB but is invalid in LiteLLM - regenerate it
logger.warning(
'BYOR key found in database but invalid in LiteLLM - regenerating',
extra={
'user_id': user_id,
'key_prefix': byor_key[:10] + '...'
if len(byor_key) > 10
else byor_key,
},
)
# Delete the invalid key from LiteLLM (best effort, don't fail if it doesn't exist)
await delete_byor_key_from_litellm(user_id, byor_key)
# Fall through to generate a new key
# If not, generate a new key for BYOR
# Generate a new key for BYOR (either no key exists or validation failed)
key = await generate_byor_key(user_id)
if key:
# Store the key in the database
await store_byor_key_in_db(user_id, key)
logger.info(
'Successfully generated and stored new BYOR key',
extra={'user_id': user_id},
)
return {'key': key}
else:
logger.error(
@@ -301,6 +395,9 @@ async def get_llm_api_key_for_byor(user_id: str = Depends(get_user_id)):
detail='Failed to generate new BYOR LLM API key',
)
except HTTPException:
# Re-raise HTTP exceptions as-is
raise
except Exception as e:
logger.exception('Error retrieving BYOR LLM API key', extra={'error': str(e)})
raise HTTPException(

View File

@@ -111,10 +111,24 @@ def calculate_credits(user_info: LiteLlmUserInfo) -> float:
async def get_credits(user_id: str = Depends(get_user_id)) -> GetCreditsResponse:
if not stripe_service.STRIPE_API_KEY:
return GetCreditsResponse()
async with httpx.AsyncClient(verify=httpx_verify_option()) as client:
user_json = await _get_litellm_user(client, user_id)
credits = calculate_credits(user_json['user_info'])
return GetCreditsResponse(credits=Decimal('{:.2f}'.format(credits)))
try:
async with httpx.AsyncClient(verify=httpx_verify_option()) as client:
user_json = await _get_litellm_user(client, user_id)
credits = calculate_credits(user_json['user_info'])
return GetCreditsResponse(credits=Decimal('{:.2f}'.format(credits)))
except httpx.HTTPStatusError as e:
logger.error(
f'litellm_get_user_failed: {type(e).__name__}: {e}',
extra={
'user_id': user_id,
'status_code': e.response.status_code,
},
exc_info=True,
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail='Failed to retrieve credit balance from billing service',
)
# Endpoint to retrieve user's current subscription access

View File

@@ -134,12 +134,12 @@ async def _process_batch_operations_background(
)
except Exception as e:
logger.error(
'error_processing_batch_operation',
f'error_processing_batch_operation: {type(e).__name__}: {e}',
extra={
'path': batch_op.path,
'method': str(batch_op.method),
'error': str(e),
},
exc_info=True,
)

View File

@@ -0,0 +1,330 @@
"""Unit tests for API keys routes, focusing on BYOR key validation and retrieval."""
from unittest.mock import AsyncMock, MagicMock, patch
import httpx
import pytest
from fastapi import HTTPException
from server.routes.api_keys import (
get_llm_api_key_for_byor,
verify_byor_key_in_litellm,
)
class TestVerifyByorKeyInLitellm:
"""Test the verify_byor_key_in_litellm function."""
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_valid_key_returns_true(self, mock_client_class):
"""Test that a valid key (200 response) returns True."""
# Arrange
byor_key = 'sk-valid-key-123'
user_id = 'user-123'
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.is_success = True
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.return_value = mock_response
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is True
mock_client.get.assert_called_once_with(
'https://litellm.example.com/v1/models',
headers={'Authorization': f'Bearer {byor_key}'},
)
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_invalid_key_401_returns_false(self, mock_client_class):
"""Test that an invalid key (401 response) returns False."""
# Arrange
byor_key = 'sk-invalid-key-123'
user_id = 'user-123'
mock_response = MagicMock()
mock_response.status_code = 401
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.return_value = mock_response
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_invalid_key_403_returns_false(self, mock_client_class):
"""Test that an invalid key (403 response) returns False."""
# Arrange
byor_key = 'sk-forbidden-key-123'
user_id = 'user-123'
mock_response = MagicMock()
mock_response.status_code = 403
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.return_value = mock_response
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_server_error_returns_false(self, mock_client_class):
"""Test that a server error (500) returns False to ensure key validity."""
# Arrange
byor_key = 'sk-key-123'
user_id = 'user-123'
mock_response = MagicMock()
mock_response.status_code = 500
mock_response.is_success = False
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.return_value = mock_response
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_timeout_returns_false(self, mock_client_class):
"""Test that a timeout returns False to ensure key validity."""
# Arrange
byor_key = 'sk-key-123'
user_id = 'user-123'
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.side_effect = httpx.TimeoutException('Request timed out')
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
@patch('server.routes.api_keys.httpx.AsyncClient')
async def test_verify_network_error_returns_false(self, mock_client_class):
"""Test that a network error returns False to ensure key validity."""
# Arrange
byor_key = 'sk-key-123'
user_id = 'user-123'
mock_client = AsyncMock()
mock_client.__aenter__.return_value = mock_client
mock_client.__aexit__.return_value = None
mock_client.get.side_effect = httpx.NetworkError('Network error')
mock_client_class.return_value = mock_client
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', None)
async def test_verify_missing_api_url_returns_false(self):
"""Test that missing LITE_LLM_API_URL returns False."""
# Arrange
byor_key = 'sk-key-123'
user_id = 'user-123'
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
@pytest.mark.asyncio
@patch('server.routes.api_keys.LITE_LLM_API_URL', 'https://litellm.example.com')
async def test_verify_empty_key_returns_false(self):
"""Test that empty key returns False."""
# Arrange
byor_key = ''
user_id = 'user-123'
# Act
result = await verify_byor_key_in_litellm(byor_key, user_id)
# Assert
assert result is False
class TestGetLlmApiKeyForByor:
"""Test the get_llm_api_key_for_byor endpoint."""
@pytest.mark.asyncio
@patch('server.routes.api_keys.store_byor_key_in_db')
@patch('server.routes.api_keys.generate_byor_key')
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_no_key_in_database_generates_new(
self, mock_get_key, mock_generate_key, mock_store_key
):
"""Test that when no key exists in database, a new one is generated."""
# Arrange
user_id = 'user-123'
new_key = 'sk-new-generated-key'
mock_get_key.return_value = None
mock_generate_key.return_value = new_key
mock_store_key.return_value = None
# Act
result = await get_llm_api_key_for_byor(user_id=user_id)
# Assert
assert result == {'key': new_key}
mock_get_key.assert_called_once_with(user_id)
mock_generate_key.assert_called_once_with(user_id)
mock_store_key.assert_called_once_with(user_id, new_key)
@pytest.mark.asyncio
@patch('server.routes.api_keys.verify_byor_key_in_litellm')
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_valid_key_in_database_returns_key(
self, mock_get_key, mock_verify_key
):
"""Test that when a valid key exists in database, it is returned."""
# Arrange
user_id = 'user-123'
existing_key = 'sk-existing-valid-key'
mock_get_key.return_value = existing_key
mock_verify_key.return_value = True
# Act
result = await get_llm_api_key_for_byor(user_id=user_id)
# Assert
assert result == {'key': existing_key}
mock_get_key.assert_called_once_with(user_id)
mock_verify_key.assert_called_once_with(existing_key, user_id)
@pytest.mark.asyncio
@patch('server.routes.api_keys.store_byor_key_in_db')
@patch('server.routes.api_keys.generate_byor_key')
@patch('server.routes.api_keys.delete_byor_key_from_litellm')
@patch('server.routes.api_keys.verify_byor_key_in_litellm')
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_invalid_key_in_database_regenerates(
self,
mock_get_key,
mock_verify_key,
mock_delete_key,
mock_generate_key,
mock_store_key,
):
"""Test that when an invalid key exists in database, it is regenerated."""
# Arrange
user_id = 'user-123'
invalid_key = 'sk-invalid-key'
new_key = 'sk-new-generated-key'
mock_get_key.return_value = invalid_key
mock_verify_key.return_value = False
mock_delete_key.return_value = True
mock_generate_key.return_value = new_key
mock_store_key.return_value = None
# Act
result = await get_llm_api_key_for_byor(user_id=user_id)
# Assert
assert result == {'key': new_key}
mock_get_key.assert_called_once_with(user_id)
mock_verify_key.assert_called_once_with(invalid_key, user_id)
mock_delete_key.assert_called_once_with(user_id, invalid_key)
mock_generate_key.assert_called_once_with(user_id)
mock_store_key.assert_called_once_with(user_id, new_key)
@pytest.mark.asyncio
@patch('server.routes.api_keys.store_byor_key_in_db')
@patch('server.routes.api_keys.generate_byor_key')
@patch('server.routes.api_keys.delete_byor_key_from_litellm')
@patch('server.routes.api_keys.verify_byor_key_in_litellm')
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_invalid_key_deletion_failure_still_regenerates(
self,
mock_get_key,
mock_verify_key,
mock_delete_key,
mock_generate_key,
mock_store_key,
):
"""Test that even if deletion fails, regeneration still proceeds."""
# Arrange
user_id = 'user-123'
invalid_key = 'sk-invalid-key'
new_key = 'sk-new-generated-key'
mock_get_key.return_value = invalid_key
mock_verify_key.return_value = False
mock_delete_key.return_value = False # Deletion fails
mock_generate_key.return_value = new_key
mock_store_key.return_value = None
# Act
result = await get_llm_api_key_for_byor(user_id=user_id)
# Assert
assert result == {'key': new_key}
mock_delete_key.assert_called_once_with(user_id, invalid_key)
mock_generate_key.assert_called_once_with(user_id)
mock_store_key.assert_called_once_with(user_id, new_key)
@pytest.mark.asyncio
@patch('server.routes.api_keys.generate_byor_key')
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_key_generation_failure_raises_exception(
self, mock_get_key, mock_generate_key
):
"""Test that when key generation fails, an HTTPException is raised."""
# Arrange
user_id = 'user-123'
mock_get_key.return_value = None
mock_generate_key.return_value = None
# Act & Assert
with pytest.raises(HTTPException) as exc_info:
await get_llm_api_key_for_byor(user_id=user_id)
assert exc_info.value.status_code == 500
assert 'Failed to generate new BYOR LLM API key' in exc_info.value.detail
@pytest.mark.asyncio
@patch('server.routes.api_keys.get_byor_key_from_db')
async def test_database_error_raises_exception(self, mock_get_key):
"""Test that database errors are properly handled."""
# Arrange
user_id = 'user-123'
mock_get_key.side_effect = Exception('Database connection error')
# Act & Assert
with pytest.raises(HTTPException) as exc_info:
await get_llm_api_key_for_byor(user_id=user_id)
assert exc_info.value.status_code == 500
assert 'Failed to retrieve BYOR LLM API key' in exc_info.value.detail

View File

@@ -699,12 +699,11 @@ class TestProcessBatchOperationsBackground:
# Should not raise exceptions
await _process_batch_operations_background(batch_ops, 'test-api-key')
# Should log the error
mock_logger.error.assert_called_once_with(
'error_processing_batch_operation',
extra={
'path': 'invalid-path',
'method': 'BatchMethod.POST',
'error': mock_logger.error.call_args[1]['extra']['error'],
},
)
# Should log the error with exception type and message in the log message
mock_logger.error.assert_called_once()
call_args = mock_logger.error.call_args
log_message = call_args[0][0]
assert log_message.startswith('error_processing_batch_operation:')
assert call_args[1]['extra']['path'] == 'invalid-path'
assert call_args[1]['extra']['method'] == 'BatchMethod.POST'
assert call_args[1]['exc_info'] is True

View File

@@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
import stripe
from fastapi import HTTPException, Request, status
from httpx import HTTPStatusError, Response
from httpx import Response
from integrations.stripe_service import has_payment_method
from server.routes.billing import (
CreateBillingSessionResponse,
@@ -78,8 +78,6 @@ def mock_subscription_request():
@pytest.mark.asyncio
async def test_get_credits_lite_llm_error():
mock_request = Request(scope={'type': 'http', 'state': {'user_id': 'mock_user'}})
mock_response = Response(
status_code=500, json={'error': 'Internal Server Error'}, request=MagicMock()
)
@@ -88,11 +86,12 @@ async def test_get_credits_lite_llm_error():
with patch('integrations.stripe_service.STRIPE_API_KEY', 'mock_key'):
with patch('httpx.AsyncClient', return_value=mock_client):
with pytest.raises(HTTPStatusError) as exc_info:
await get_credits(mock_request)
with pytest.raises(HTTPException) as exc_info:
await get_credits('mock_user')
assert exc_info.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert (
exc_info.value.response.status_code
== status.HTTP_500_INTERNAL_SERVER_ERROR
exc_info.value.detail
== 'Failed to retrieve credit balance from billing service'
)

View File

@@ -0,0 +1,18 @@
import { test, expect, vi } from "vitest";
import axios from "axios";
import V1GitService from "../../src/api/git-service/v1-git-service.api";
vi.mock("axios");
test("getGitChanges throws when response is not an array (dead runtime returns HTML)", async () => {
const htmlResponse = "<!DOCTYPE html><html>...</html>";
vi.mocked(axios.get).mockResolvedValue({ data: htmlResponse });
await expect(
V1GitService.getGitChanges(
"http://localhost:3000/api/conversations/123",
"test-api-key",
"/workspace",
),
).rejects.toThrow("Invalid response from runtime");
});

View File

@@ -16,6 +16,13 @@ vi.mock("#/hooks/mutation/use-unified-stop-conversation", () => ({
}),
}));
// Mock toast handlers to prevent unhandled rejection errors
vi.mock("#/utils/custom-toast-handlers", () => ({
displaySuccessToast: vi.fn(),
displayErrorToast: vi.fn(),
TOAST_OPTIONS: {},
}));
describe("ConversationPanel", () => {
const onCloseMock = vi.fn();
const RouterStub = createRoutesStub([
@@ -634,12 +641,6 @@ describe("ConversationPanel", () => {
);
updateConversationSpy.mockResolvedValue(true);
// Mock the toast function
const mockToast = vi.fn();
vi.mock("#/utils/custom-toast-handlers", () => ({
displaySuccessToast: mockToast,
}));
renderConversationPanel();
const cards = await screen.findAllByTestId("conversation-card");
@@ -767,10 +768,6 @@ describe("ConversationPanel", () => {
);
updateConversationSpy.mockRejectedValue(new Error("API Error"));
vi.mock("#/utils/custom-toast-handlers", () => ({
displayErrorToast: vi.fn(),
}));
renderConversationPanel();
const cards = await screen.findAllByTestId("conversation-card");

View File

@@ -1,12 +1,12 @@
{
"name": "openhands-frontend",
"version": "1.0.0",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openhands-frontend",
"version": "1.0.0",
"version": "1.1.0",
"dependencies": {
"@heroui/react": "2.8.7",
"@microlink/react-json-view": "^1.26.2",
@@ -14,7 +14,7 @@
"@react-router/node": "^7.11.0",
"@react-router/serve": "^7.11.0",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.14",
"@tanstack/react-query": "^5.90.15",
"@uidotdev/usehooks": "^2.4.1",
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
@@ -30,7 +30,7 @@
"isbot": "^5.1.32",
"lucide-react": "^0.562.0",
"monaco-editor": "^0.55.1",
"posthog-js": "^1.310.1",
"posthog-js": "^1.311.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hot-toast": "^2.6.0",
@@ -5545,20 +5545,20 @@
}
},
"node_modules/@tanstack/query-core": {
"version": "5.90.14",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.14.tgz",
"integrity": "sha512-/6di2yNI+YxpVrH9Ig74Q+puKnkCE+D0LGyagJEGndJHJc6ahkcc/UqirHKy8zCYE/N9KLggxcQvzYCsUBWgdw==",
"version": "5.90.15",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.15.tgz",
"integrity": "sha512-mInIZNUZftbERE+/Hbtswfse49uUQwch46p+27gP9DWJL927UjnaWEF2t3RMOqBcXbfMdcNkPe06VyUIAZTV1g==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "5.90.14",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.14.tgz",
"integrity": "sha512-JAMuULej09hrZ14W9+mxoRZ44rR2BuZfCd6oKTQVNfynQxCN3muH3jh3W46gqZNw5ZqY0ZVaS43Imb3dMr6tgw==",
"version": "5.90.15",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.15.tgz",
"integrity": "sha512-uQvnDDcTOgJouNtAyrgRej+Azf0U5WDov3PXmHFUBc+t1INnAYhIlpZtCGNBLwCN41b43yO7dPNZu8xWkUFBwQ==",
"dependencies": {
"@tanstack/query-core": "5.90.14"
"@tanstack/query-core": "5.90.15"
},
"funding": {
"type": "github",
@@ -13386,9 +13386,9 @@
}
},
"node_modules/posthog-js": {
"version": "1.310.1",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.310.1.tgz",
"integrity": "sha512-UkR6zzlWNtqHDXHJl2Yk062DOmZyVKTPL5mX4j4V+u3RiYbMHJe47+PpMMUsvK1R2e1r/m9uSlHaJMJRzyUjGg==",
"version": "1.311.0",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.311.0.tgz",
"integrity": "sha512-P1dWYNFr1dlfa5sAOFj4uq2jJuGfNce3ctYl565t0Fm/i4ZJZq4D2hmKyTMjKu5f9wyZVlTeRdxdmTIGDjCegw==",
"dependencies": {
"@posthog/core": "1.9.0",
"core-js": "^3.38.1",

View File

@@ -1,6 +1,6 @@
{
"name": "openhands-frontend",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"type": "module",
"engines": {
@@ -13,7 +13,7 @@
"@react-router/node": "^7.11.0",
"@react-router/serve": "^7.11.0",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.14",
"@tanstack/react-query": "^5.90.15",
"@uidotdev/usehooks": "^2.4.1",
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
@@ -29,7 +29,7 @@
"isbot": "^5.1.32",
"lucide-react": "^0.562.0",
"monaco-editor": "^0.55.1",
"posthog-js": "^1.310.1",
"posthog-js": "^1.311.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hot-toast": "^2.6.0",

View File

@@ -53,6 +53,13 @@ class V1GitService {
// V1 API returns V1GitChangeStatus types, we need to map them to V0 format
const { data } = await axios.get<V1GitChange[]>(url, { headers });
// Validate response is an array (could be HTML error page if runtime is dead)
if (!Array.isArray(data)) {
throw new Error(
"Invalid response from runtime - runtime may be unavailable",
);
}
// Map V1 statuses to V0 format for compatibility
return data.map((change) => ({
status: mapV1ToV0Status(change.status),

View File

@@ -89,10 +89,9 @@ export const useTerminal = () => {
scrollback: 10000,
scrollSensitivity: 1,
fastScrollSensitivity: 5,
allowTransparency: true,
disableStdin: true, // Make terminal read-only
theme: {
background: "transparent",
background: "#25272D",
},
});

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import os
from browsergym.core.action.highlevel import HighLevelActionSet

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import ast
import re

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import collections
import re
from warnings import warn

View File

@@ -1,3 +1,11 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# V1 replacement for this module lives in the Software Agent SDK.
import os
import sys
from collections import deque

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""This file contains the function calling implementation for different actions.
This is similar to the functionality of `CodeActResponseParser`.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
from openhands.agenthub.codeact_agent.tools.prompt import refine_prompt

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from browsergym.core.action.highlevel import HighLevelActionSet
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
_CONDENSATION_REQUEST_DESCRIPTION = 'Request a condensation of the conversation history when the context becomes too long or when you need to focus on the most relevant information.'

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
from openhands.llm.tool_names import FINISH_TOOL_NAME

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
from openhands.agenthub.codeact_agent.tools.security_utils import (

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
from openhands.agenthub.codeact_agent.tools.security_utils import (

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import re
import sys

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""Security utility constants for tool risk descriptions.
This file contains standardized risk description text for various tools.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import os
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
from openhands.llm.tool_names import TASK_TRACKER_TOOL_NAME

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
_THINK_DESCRIPTION = """Use the tool to think about something. It will not obtain new information or make any changes to the repository, but just log the thought. Use it when complex reasoning or brainstorming is needed.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from typing import TypedDict
from openhands.controller.agent import Agent

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""This file contains the function calling implementation for different actions.
This is similar to the functionality of `CodeActResponseParser`.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from typing import TYPE_CHECKING
import openhands.agenthub.loc_agent.function_calling as locagent_function_calling

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import (
ChatCompletionToolParam,
ChatCompletionToolParamFunctionChunk,

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import (
ChatCompletionToolParam,
ChatCompletionToolParamFunctionChunk,

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""This file contains the function calling implementation for different actions.
This is similar to the functionality of `CodeActResponseParser`.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""ReadOnlyAgent - A specialized version of CodeActAgent that only uses read-only tools."""
import os

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
_GLOB_DESCRIPTION = """Fast file pattern matching tool.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
_GREP_DESCRIPTION = """Fast content search tool.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from litellm import ChatCompletionToolParam, ChatCompletionToolParamFunctionChunk
_VIEW_DESCRIPTION = """Reads a file or list directories from the local filesystem.

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from browsergym.core.action.highlevel import HighLevelActionSet
from browsergym.utils.obs import flatten_axtree_to_str

View File

@@ -4,7 +4,7 @@ from typing import Any
from uuid import UUID
import httpx
from github import Github, GithubIntegration
from github import Auth, Github, GithubIntegration
from pydantic import Field
from openhands.agent_server.models import AskAgentRequest, AskAgentResponse
@@ -124,8 +124,7 @@ class GithubV1CallbackProcessor(EventCallbackProcessor):
raise ValueError('GitHub App credentials are not configured')
github_integration = GithubIntegration(
github_app_client_id,
github_app_private_key,
auth=Auth.AppAuth(github_app_client_id, github_app_private_key),
)
token_data = github_integration.get_access_token(installation_id)
return token_data.token

View File

@@ -13,7 +13,7 @@ from openhands.sdk.utils.models import DiscriminatedUnionMixin
# The version of the agent server to use for deployments.
# Typically this will be the same as the values from the pyproject.toml
AGENT_SERVER_IMAGE = 'ghcr.io/openhands/agent-server:0b7ccc9-python'
AGENT_SERVER_IMAGE = 'ghcr.io/openhands/agent-server:5cbfbf7-python'
class SandboxSpecService(ABC):

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from abc import ABC, abstractmethod
from typing import Any

View File

@@ -1,3 +1,11 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# V1 replacement for this module lives in the Software Agent SDK.
from __future__ import annotations
from abc import ABC, abstractmethod

View File

@@ -1,3 +1,11 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# V1 replacement for this module lives in the Software Agent SDK.
from __future__ import annotations
import asyncio

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
from openhands.core.logger import openhands_logger as logger

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
from dataclasses import dataclass

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
import base64

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from openhands.controller.state.control_flags import (
BudgetControlFlag,
IterationControlFlag,

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from dataclasses import dataclass
from typing import Optional

View File

@@ -1,10 +1,8 @@
from openhands.core.config.agent_config import AgentConfig
from openhands.core.config.arg_utils import (
get_cli_parser,
get_evaluation_parser,
get_headless_parser,
)
from openhands.core.config.cli_config import CLIConfig
from openhands.core.config.config_utils import (
OH_DEFAULT_AGENT,
OH_MAX_ITERATIONS,
@@ -34,7 +32,6 @@ __all__ = [
'OH_DEFAULT_AGENT',
'OH_MAX_ITERATIONS',
'AgentConfig',
'CLIConfig',
'OpenHandsConfig',
'MCPConfig',
'LLMConfig',
@@ -49,7 +46,6 @@ __all__ = [
'get_agent_config_arg',
'get_llm_config_arg',
'get_field_info',
'get_cli_parser',
'get_headless_parser',
'get_evaluation_parser',
'parse_arguments',

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field, ValidationError

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""Centralized command line argument configuration for OpenHands CLI and headless modes."""
import argparse

View File

@@ -1,9 +0,0 @@
from pydantic import BaseModel, Field
class CLIConfig(BaseModel):
"""Configuration for CLI-specific settings."""
vi_mode: bool = Field(default=False)
model_config = {'extra': 'forbid'}

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
from typing import Literal, cast

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from types import UnionType
from typing import Any, get_args, get_origin

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from typing import Any
from pydantic import RootModel

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from pydantic import BaseModel, ConfigDict, Field, ValidationError

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
import os

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
import os

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from pydantic import BaseModel, ConfigDict, Field, ValidationError
from openhands.core.config.llm_config import LLMConfig

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import os
from typing import Any, ClassVar
@@ -5,7 +12,6 @@ from pydantic import BaseModel, ConfigDict, Field, SecretStr
from openhands.core import logger
from openhands.core.config.agent_config import AgentConfig
from openhands.core.config.cli_config import CLIConfig
from openhands.core.config.config_utils import (
DEFAULT_WORKSPACE_MOUNT_PATH_IN_SANDBOX,
OH_DEFAULT_AGENT,
@@ -119,7 +125,6 @@ class OpenHandsConfig(BaseModel):
mcp_host: str = Field(default=f'localhost:{os.getenv("port", 3000)}')
mcp: MCPConfig = Field(default_factory=MCPConfig)
kubernetes: KubernetesConfig = Field(default_factory=KubernetesConfig)
cli: CLIConfig = Field(default_factory=CLIConfig)
git_user_name: str = Field(
default='openhands', description='Git user name for commits made by the agent'
)

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import os
from pydantic import BaseModel, ConfigDict, Field, ValidationError, model_validator

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from pydantic import BaseModel, ConfigDict, Field, ValidationError

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import argparse
import os
import pathlib

View File

@@ -1 +1,8 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
TROUBLESHOOTING_URL = 'https://docs.all-hands.dev/usage/troubleshooting'

View File

@@ -1,2 +1,9 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# Run this file to trigger a model download
import openhands.agenthub # noqa F401 (we import this to get the agents registered)

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# ============================================
# Agent Exceptions
# ============================================

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import copy
import logging
import os

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import asyncio
from openhands.controller import AgentController

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import asyncio
import json
import os

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from enum import Enum
from typing import Any, Literal

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from openhands.events.event import Event
from openhands.llm.metrics import Metrics, TokenUsage

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from enum import Enum

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from enum import Enum

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from enum import Enum

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from enum import Enum

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import hashlib
import os
import uuid

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import asyncio
from functools import partial
from typing import Any, Callable

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import boto3
from openhands.core.logger import openhands_logger as logger

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from logging import DEBUG
from typing import Any

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
"""Convert function calling messages to non-function calling messages and vice versa.
This will inject prompts so that models that doesn't support function calling

View File

@@ -1,3 +1,11 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
# V1 replacement for this module lives in the Software Agent SDK.
import copy
import os
import time

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import copy
from typing import Any, Callable
from uuid import uuid4

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import copy
from typing import TYPE_CHECKING

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
import copy
import time

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from __future__ import annotations
from dataclasses import dataclass

View File

@@ -1,3 +1,10 @@
# IMPORTANT: LEGACY V0 CODE
# This file is part of the legacy (V0) implementation of OpenHands and will be removed soon as we complete the migration to V1.
# OpenHands V1 uses the Software Agent SDK for the agentic core and runs a new application server. Please refer to:
# - V1 agentic core (SDK): https://github.com/OpenHands/software-agent-sdk
# - V1 application server (in this repo): openhands/app_server/
# Unless you are working on deprecation, please avoid extending this legacy file and consult the V1 codepaths above.
# Tag: Legacy-V0
from typing import Any, Callable
from tenacity import (

Some files were not shown because too many files have changed in this diff Show More