Add RecallActions and observations for retrieval of prompt extensions (#6909)

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Calvin Smith <email@cjsmith.io>
This commit is contained in:
Engel Nyst
2025-03-15 21:48:37 +01:00
committed by GitHub
parent e34a771e66
commit cc45f5d9c3
38 changed files with 2317 additions and 735 deletions

View File

@@ -6,9 +6,11 @@ from openhands.controller.agent import Agent
from openhands.controller.agent_controller import AgentController
from openhands.controller.state.state import State
from openhands.core.config import AppConfig, LLMConfig
from openhands.core.config.agent_config import AgentConfig
from openhands.events import EventStream, EventStreamSubscriber
from openhands.llm import LLM
from openhands.llm.metrics import Metrics
from openhands.memory.memory import Memory
from openhands.runtime.base import Runtime
from openhands.server.session.agent_session import AgentSession
from openhands.storage.memory import InMemoryFileStore
@@ -22,18 +24,24 @@ def mock_agent():
llm = MagicMock(spec=LLM)
metrics = MagicMock(spec=Metrics)
llm_config = MagicMock(spec=LLMConfig)
agent_config = MagicMock(spec=AgentConfig)
# Configure the LLM config
llm_config.model = 'test-model'
llm_config.base_url = 'http://test'
llm_config.max_message_chars = 1000
# Configure the agent config
agent_config.disabled_microagents = []
# Set up the chain of mocks
llm.metrics = metrics
llm.config = llm_config
agent.llm = llm
agent.name = 'test-agent'
agent.sandbox_plugins = []
agent.config = agent_config
agent.prompt_manager = MagicMock()
return agent
@@ -78,7 +86,11 @@ async def test_agent_session_start_with_no_state(mock_agent):
self.test_initial_state = state
super().set_initial_state(*args, state=state, **kwargs)
# Patch AgentController and State.restore_from_session to fail
# Create a real Memory instance with the mock event stream
memory = Memory(event_stream=mock_event_stream, sid='test-session')
memory.microagents_dir = 'test-dir'
# Patch AgentController and State.restore_from_session to fail; patch Memory in AgentSession
with patch(
'openhands.server.session.agent_session.AgentController', SpyAgentController
), patch(
@@ -87,7 +99,7 @@ async def test_agent_session_start_with_no_state(mock_agent):
), patch(
'openhands.controller.state.state.State.restore_from_session',
side_effect=Exception('No state found'),
):
), patch('openhands.server.session.agent_session.Memory', return_value=memory):
await session.start(
runtime_name='test-runtime',
config=AppConfig(),
@@ -96,12 +108,18 @@ async def test_agent_session_start_with_no_state(mock_agent):
)
# Verify EventStream.subscribe was called with correct parameters
mock_event_stream.subscribe.assert_called_with(
mock_event_stream.subscribe.assert_any_call(
EventStreamSubscriber.AGENT_CONTROLLER,
session.controller.on_event,
session.controller.id,
)
mock_event_stream.subscribe.assert_any_call(
EventStreamSubscriber.MEMORY,
session.memory.on_event,
session.controller.id,
)
# Verify set_initial_state was called once with None as state
assert session.controller.set_initial_state_call_count == 1
assert session.controller.test_initial_state is None
@@ -159,7 +177,10 @@ async def test_agent_session_start_with_restored_state(mock_agent):
self.test_initial_state = state
super().set_initial_state(*args, state=state, **kwargs)
# Patch AgentController and State.restore_from_session to succeed
# create a mock Memory
mock_memory = MagicMock(spec=Memory)
# Patch AgentController and State.restore_from_session to succeed, patch Memory in AgentSession
with patch(
'openhands.server.session.agent_session.AgentController', SpyAgentController
), patch(
@@ -168,7 +189,7 @@ async def test_agent_session_start_with_restored_state(mock_agent):
), patch(
'openhands.controller.state.state.State.restore_from_session',
return_value=mock_restored_state,
):
), patch('openhands.server.session.agent_session.Memory', mock_memory):
await session.start(
runtime_name='test-runtime',
config=AppConfig(),