Add number of connections to Conversation Info (#8456)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
tofarr 2025-05-12 13:57:52 -06:00 committed by GitHub
parent 5a927c8651
commit f75fa50b80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 21 additions and 33 deletions

View File

@ -18,4 +18,5 @@ class ConversationInfo:
status: ConversationStatus = ConversationStatus.STOPPED
selected_repository: str | None = None
trigger: ConversationTrigger | None = None
num_connections: int = 0
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

View File

@ -308,38 +308,9 @@ async def get_cwd(
workspace_mount_path_in_sandbox: str,
) -> str:
metadata = await conversation_store.get_metadata(conversation_id)
is_running = await conversation_manager.is_agent_loop_running(conversation_id)
conversation_info = await _get_conversation_info(metadata, is_running)
cwd = workspace_mount_path_in_sandbox
if conversation_info and conversation_info.selected_repository:
repo_dir = conversation_info.selected_repository.split('/')[-1]
if metadata and metadata.selected_repository:
repo_dir = metadata.selected_repository.split('/')[-1]
cwd = os.path.join(cwd, repo_dir)
return cwd
async def _get_conversation_info(
conversation: ConversationMetadata,
is_running: bool,
) -> ConversationInfo | None:
try:
title = conversation.title
if not title:
title = f'Conversation {conversation.conversation_id[:5]}'
return ConversationInfo(
conversation_id=conversation.conversation_id,
title=title,
last_updated_at=conversation.last_updated_at,
created_at=conversation.created_at,
selected_repository=conversation.selected_repository,
status=ConversationStatus.RUNNING
if is_running
else ConversationStatus.STOPPED,
)
except Exception as e:
logger.error(
f'Error loading conversation {conversation.conversation_id}: {str(e)}',
extra={'session_id': conversation.conversation_id},
)
return None

View File

@ -267,13 +267,18 @@ async def search_conversations(
conversation.conversation_id for conversation in filtered_results
)
running_conversations = await conversation_manager.get_running_agent_loops(
user_id, set(conversation_ids)
user_id, conversation_ids
)
connection_ids_to_conversation_ids = await conversation_manager.get_connections(filter_to_sids=conversation_ids)
result = ConversationInfoResultSet(
results=await wait_all(
_get_conversation_info(
conversation=conversation,
is_running=conversation.conversation_id in running_conversations,
num_connections=sum(
1 for conversation_id in connection_ids_to_conversation_ids.values()
if conversation_id == conversation.conversation_id
)
)
for conversation in filtered_results
),
@ -290,7 +295,8 @@ async def get_conversation(
try:
metadata = await conversation_store.get_metadata(conversation_id)
is_running = await conversation_manager.is_agent_loop_running(conversation_id)
conversation_info = await _get_conversation_info(metadata, is_running)
num_connections = len(await conversation_manager.get_connections(filter_to_sids={conversation_id}))
conversation_info = await _get_conversation_info(metadata, is_running, num_connections)
return conversation_info
except FileNotFoundError:
return None
@ -318,6 +324,7 @@ async def delete_conversation(
async def _get_conversation_info(
conversation: ConversationMetadata,
is_running: bool,
num_connections: int
) -> ConversationInfo | None:
try:
title = conversation.title
@ -333,6 +340,7 @@ async def _get_conversation_info(
status=(
ConversationStatus.RUNNING if is_running else ConversationStatus.STOPPED
),
num_connections=num_connections
)
except Exception as e:
logger.error(

View File

@ -110,7 +110,11 @@ async def test_search_conversations():
async def mock_get_running_agent_loops(*args, **kwargs):
return set()
async def mock_get_connections(*args, **kwargs):
return {}
mock_manager.get_running_agent_loops = mock_get_running_agent_loops
mock_manager.get_connections = mock_get_connections
with patch(
'openhands.server.routes.manage_conversations.datetime'
) as mock_datetime:
@ -162,6 +166,7 @@ async def test_search_conversations():
),
status=ConversationStatus.STOPPED,
selected_repository='foobar',
num_connections=0,
)
]
)
@ -190,6 +195,7 @@ async def test_get_conversation():
'openhands.server.routes.manage_conversations.conversation_manager'
) as mock_manager:
mock_manager.is_agent_loop_running = AsyncMock(return_value=False)
mock_manager.get_connections = AsyncMock(return_value={})
conversation = await get_conversation(
'some_conversation_id', conversation_store=mock_store
@ -202,6 +208,7 @@ async def test_get_conversation():
last_updated_at=datetime.fromisoformat('2025-01-01T00:01:00+00:00'),
status=ConversationStatus.STOPPED,
selected_repository='foobar',
num_connections=0,
)
assert conversation == expected
@ -420,6 +427,7 @@ async def test_delete_conversation():
'openhands.server.routes.manage_conversations.conversation_manager'
) as mock_manager:
mock_manager.is_agent_loop_running = AsyncMock(return_value=False)
mock_manager.get_connections = AsyncMock(return_value={})
# Mock the runtime class
with patch(