feat: unify history tools and improve execution reliability

This commit is contained in:
somew1nd committed 2026-09-03 16:05:47 -07:00
1 parent d23a4f6472
commit 2fea9865ee
116 files changed
+8291 -2503

No files matched your search

@@ -12,51 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from artemis.agents.history_analyzer.history_analyzer import HistoryAnalyzer
from artemis.config import parse_llm_config
import pytest
@pytest.mark.asyncio
async def test_exec_get_step_details(artemis_context):
"""Test the exec_get_step_details method with manually configured steps."""
analyzer = HistoryAnalyzer(artemis_context)
analyzer.history_steps = [
{
"step_number": 0,
"relative_time": 0.0,
"summary": "Initial step",
"action_taken": "none",
"operator_raw_thinking": "Starting up",
"last_execution_result": "Success",
},
{
"step_number": 1,
"relative_time": 5.0,
"summary": "Second step",
"action_taken": "click",
"operator_raw_thinking": "Clicking button",
"last_execution_result": "Success",
},
]
first_step_num = 0
result = analyzer.exec_get_step_details(first_step_num, first_step_num)
assert "Error:" not in result
assert "No steps found" not in result
parsed = json.loads(result)
assert isinstance(parsed, list)
assert len(parsed) == 1
assert parsed[0]["step_number"] == first_step_num
assert "summary" in parsed[0]
@pytest.mark.asyncio
async def test_get_step_details_tool_with_fixture(artemis_context):
"""Test _get_step_details_tool against real steps loaded from the inputs/data_engine.db fixture."""
async def test_replay_steps_tool_with_fixture(artemis_context):
"""The analyzer's replay_steps tool against real steps loaded from the
inputs/data_engine.db fixture."""
if not artemis_context.data_engine:
pytest.skip("DataEngine fixture not initialized")
@@ -65,18 +29,21 @@ async def test_get_step_details_tool_with_fixture(artemis_context):
assert len(steps) > 0
analyzer = HistoryAnalyzer(artemis_context)
tool = analyzer._get_step_details_tool(steps)
tools = {t.name: t for t in analyzer._build_tools()}
assert {
"search_history",
"replay_steps",
"get_step_screenshot",
"list_notes",
"read_note",
} <= set(tools)
result = tool.invoke({"start_step": 1, "end_step": 3})
result = tools["replay_steps"].invoke({"start_step": 1, "end_step": 3})
assert isinstance(result, str)
assert "Error:" not in result
assert "No steps found" not in result
parsed = json.loads(result)
assert isinstance(parsed, list)
assert len(parsed) == 3
assert parsed[0]["step_number"] == 1
assert "YouTube" in parsed[0]["summary"]
assert not result.startswith("Error")
assert "- **Step 1 (" in result
assert "- **Step 3 (" in result
assert "YouTube" in result
@pytest.mark.asyncio
+18 -23
View File
@@ -12,36 +12,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from artemis.agents.outputter.tools import (
get_search_history_tool,
get_step_details_tool,
get_step_screenshot_tool,
)
from artemis.context import ArtemisContext
"""The outputter mounts the shared history tools; smoke-test them against the
fixture database."""
import pytest
from artemis.context import ArtemisContext
from artemis.tools.history import get_history_tools
@pytest.fixture
def history_steps(artemis_context: ArtemisContext):
if artemis_context.data_engine:
return artemis_context.data_engine.get_agent_friendly_steps()
return []
def history_tools(artemis_context: ArtemisContext):
search, replay, screenshot = get_history_tools(artemis_context)
return {"search_history": search, "replay_steps": replay, "get_step_screenshot": screenshot}
def test_get_step_details_tool(history_steps):
"""Test get_step_details_tool to ensure it runs without errors."""
tool = get_step_details_tool(history_steps)
result = tool.invoke({"start_step": 1, "end_step": 5})
def test_replay_steps_tool(history_tools):
"""replay_steps runs against the fixture history without errors."""
result = history_tools["replay_steps"].invoke({"start_step": 1, "end_step": 5})
assert isinstance(result, str)
assert len(result) > 0
def test_get_step_screenshot_tool(artemis_context: ArtemisContext, history_steps):
"""Test get_step_screenshot_tool to ensure it handles requests gracefully."""
tool = get_step_screenshot_tool(artemis_context, history_steps)
result = tool.invoke({"step_number": 1})
def test_get_step_screenshot_tool(history_tools):
"""get_step_screenshot returns content blocks with an image, or a plain explanation."""
result = history_tools["get_step_screenshot"].invoke({"step_number": 1})
if isinstance(result, list):
assert len(result) == 2
@@ -52,10 +48,9 @@ def test_get_step_screenshot_tool(artemis_context: ArtemisContext, history_steps
assert len(result) > 0
def test_get_search_history_tool(artemis_context: ArtemisContext):
"""Test get_search_history_tool to ensure it can search through history."""
tool = get_search_history_tool(artemis_context)
result = tool.invoke({"query": "test"})
def test_search_history_tool(history_tools):
"""search_history searches the fixture history and always answers in text."""
result = history_tools["search_history"].invoke({"query": "test"})
assert isinstance(result, str)
assert len(result) > 0