Spaces:
Build error
Build error
from fastapi import APIRouter, Depends, HTTPException, Request, status | |
from fastapi.responses import JSONResponse | |
from openhands.core.logger import openhands_logger as logger | |
from openhands.events.event_filter import EventFilter | |
from openhands.events.serialization.event import event_to_dict | |
from openhands.runtime.base import Runtime | |
from openhands.server.dependencies import get_dependencies | |
from openhands.server.session.conversation import ServerConversation | |
from openhands.server.shared import conversation_manager | |
from openhands.server.utils import get_conversation | |
app = APIRouter(prefix='/api/conversations/{conversation_id}', dependencies=get_dependencies()) | |
async def get_remote_runtime_config(conversation: ServerConversation = Depends(get_conversation)) -> JSONResponse: | |
"""Retrieve the runtime configuration. | |
Currently, this is the session ID and runtime ID (if available). | |
""" | |
runtime = conversation.runtime | |
runtime_id = runtime.runtime_id if hasattr(runtime, 'runtime_id') else None | |
session_id = runtime.sid if hasattr(runtime, 'sid') else None | |
return JSONResponse( | |
content={ | |
'runtime_id': runtime_id, | |
'session_id': session_id, | |
} | |
) | |
async def get_vscode_url(conversation: ServerConversation = Depends(get_conversation)) -> JSONResponse: | |
"""Get the VSCode URL. | |
This endpoint allows getting the VSCode URL. | |
Args: | |
request (Request): The incoming FastAPI request object. | |
Returns: | |
JSONResponse: A JSON response indicating the success of the operation. | |
""" | |
try: | |
runtime: Runtime = conversation.runtime | |
logger.debug(f'Runtime type: {type(runtime)}') | |
logger.debug(f'Runtime VSCode URL: {runtime.vscode_url}') | |
return JSONResponse( | |
status_code=status.HTTP_200_OK, content={'vscode_url': runtime.vscode_url} | |
) | |
except Exception as e: | |
logger.error(f'Error getting VSCode URL: {e}') | |
return JSONResponse( | |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
content={ | |
'vscode_url': None, | |
'error': f'Error getting VSCode URL: {e}', | |
}, | |
) | |
async def get_hosts(conversation: ServerConversation = Depends(get_conversation)) -> JSONResponse: | |
"""Get the hosts used by the runtime. | |
This endpoint allows getting the hosts used by the runtime. | |
Args: | |
request (Request): The incoming FastAPI request object. | |
Returns: | |
JSONResponse: A JSON response indicating the success of the operation. | |
""" | |
try: | |
runtime: Runtime = conversation.runtime | |
logger.debug(f'Runtime type: {type(runtime)}') | |
logger.debug(f'Runtime hosts: {runtime.web_hosts}') | |
return JSONResponse(status_code=200, content={'hosts': runtime.web_hosts}) | |
except Exception as e: | |
logger.error(f'Error getting runtime hosts: {e}') | |
return JSONResponse( | |
status_code=500, | |
content={ | |
'hosts': None, | |
'error': f'Error getting runtime hosts: {e}', | |
}, | |
) | |
async def search_events( | |
start_id: int = 0, | |
end_id: int | None = None, | |
reverse: bool = False, | |
filter: EventFilter | None = None, | |
limit: int = 20, | |
conversation: ServerConversation = Depends(get_conversation), | |
): | |
"""Search through the event stream with filtering and pagination. | |
Args: | |
request: The incoming request object | |
start_id: Starting ID in the event stream. Defaults to 0 | |
end_id: Ending ID in the event stream | |
reverse: Whether to retrieve events in reverse order. Defaults to False. | |
filter: Filter for events | |
limit: Maximum number of events to return. Must be between 1 and 100. Defaults to 20 | |
Returns: | |
dict: Dictionary containing: | |
- events: List of matching events | |
- has_more: Whether there are more matching events after this batch | |
Raises: | |
HTTPException: If conversation is not found | |
ValueError: If limit is less than 1 or greater than 100 | |
""" | |
if limit < 0 or limit > 100: | |
raise HTTPException( | |
status_code=status.HTTP_400_BAD_REQUEST, detail='Invalid limit' | |
) | |
# Get matching events from the stream | |
event_stream = conversation.event_stream | |
events = list( | |
event_stream.search_events( | |
start_id=start_id, | |
end_id=end_id, | |
reverse=reverse, | |
filter=filter, | |
limit=limit + 1, | |
) | |
) | |
# Check if there are more events | |
has_more = len(events) > limit | |
if has_more: | |
events = events[:limit] # Remove the extra event | |
events_json = [event_to_dict(event) for event in events] | |
return { | |
'events': events_json, | |
'has_more': has_more, | |
} | |
async def add_event(request: Request, conversation: ServerConversation = Depends(get_conversation)): | |
data = request.json() | |
await conversation_manager.send_to_event_stream(conversation.sid, data) | |
return JSONResponse({'success': True}) | |