mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 06:52:20 +02:00
Snapshot current maintainer-preview application changes and regression fixtures for integration into lab. Excludes local runtime data, evaluation outputs and source backups. Focused Python regression selection: 140 passed; full suite not certified.
86 lines
3.9 KiB
Python
86 lines
3.9 KiB
Python
import json
|
|
|
|
import pytest
|
|
|
|
from src.clean_agent_preview import email_search_recovery, email_search_result_empty, stream_preview
|
|
from src.tool_policy import ToolPolicy
|
|
from src.turn_contract import resolve_full_inventory_contract
|
|
|
|
|
|
@pytest.mark.parametrize('value', [
|
|
'No emails matched "drop off the keys address".',
|
|
{'stdout': 'No emails matched "keys".', 'exit_code': 0},
|
|
json.dumps({'output': json.dumps({'stdout': 'No emails matched "keys".', 'exit_code': 0})}),
|
|
])
|
|
def test_empty_results(value):
|
|
assert email_search_result_empty(value)
|
|
assert email_search_recovery(value, 0)
|
|
assert email_search_recovery(value, 1)
|
|
assert not email_search_recovery(value, 2)
|
|
|
|
|
|
@pytest.mark.parametrize('value', [
|
|
{'stdout': 'No emails matched "keys".', 'exit_code': 1},
|
|
{'stdout': 'No emails matched "keys".', 'stderr': 'Authentication failed'},
|
|
{'error': 'Timeout'}, '', None,
|
|
'UID 42: Key return address',
|
|
'Email body: No emails matched "keys".',
|
|
])
|
|
def test_nonempty_and_failed_results_do_not_trigger(value):
|
|
assert not email_search_result_empty(value)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_recovery_reaches_next_model_request(monkeypatch):
|
|
import src.clean_agent_preview as module
|
|
requests = []
|
|
executions = []
|
|
responses = iter([
|
|
{'tool_calls': [{'index': 0, 'id': 'c1', 'type': 'function', 'function': {
|
|
'name': 'mcp__email__search_emails', 'arguments': '{"query":"drop off the keys address"}'}}]},
|
|
{'tool_calls': [{'index': 0, 'id': 'c2', 'type': 'function', 'function': {
|
|
'name': 'mcp__email__search_emails', 'arguments': '{"query":"keys"}'}}]},
|
|
{'content': 'Found a possible message about returning keys.'},
|
|
])
|
|
class Response:
|
|
async def __aenter__(self): return self
|
|
async def __aexit__(self, *args): pass
|
|
def raise_for_status(self): pass
|
|
async def aiter_lines(self):
|
|
yield 'data: ' + json.dumps({'choices': [{'delta': next(responses)}]})
|
|
yield 'data: [DONE]'
|
|
class Client:
|
|
def __init__(self, **kwargs): pass
|
|
async def __aenter__(self): return self
|
|
async def __aexit__(self, *args): pass
|
|
def stream(self, *args, **kwargs):
|
|
requests.append(json.loads(json.dumps(kwargs['json'])))
|
|
return Response()
|
|
async def execute(block, **kwargs):
|
|
executions.append(block)
|
|
return block.tool_type, {'exit_code': 0, 'output': json.dumps({
|
|
'exit_code': 0, 'stdout': 'No emails matched "drop off the keys address".'
|
|
if len(executions) == 1 else 'UID 42: Key return address'})}
|
|
monkeypatch.setattr(module.httpx, 'AsyncClient', Client)
|
|
monkeypatch.setattr(module, 'execute_tool_block', execute)
|
|
import src.email_task_intent as intent_module
|
|
async def classify(*args, **kwargs):
|
|
return intent_module.EmailTaskIntent('read', ('email',), 'Find key return address')
|
|
monkeypatch.setattr(intent_module, 'classify_email_task', classify)
|
|
schema = {'type': 'function', 'function': {'name': 'mcp__email__search_emails',
|
|
'description': 'Search email', 'parameters': {'type': 'object',
|
|
'properties': {'query': {'type': 'string'}}, 'required': ['query']}}}
|
|
policy = ToolPolicy()
|
|
contract = resolve_full_inventory_contract(schemas=[schema], policy=policy)
|
|
chunks = [chunk async for chunk in stream_preview(
|
|
endpoint_url='http://test', model='Ajax', headers={}, turn_contract=contract,
|
|
messages=[{'role': 'user', 'content': 'Search my email, what address do I drop off the keys'}],
|
|
session_id='test-email-recovery', owner='fixture', disabled_tools=set(),
|
|
tool_policy=policy, max_rounds=3,
|
|
)]
|
|
assert len(executions) == 2, chunks
|
|
guidance = [m for m in requests[1]['messages'] if 'shorter targeted query' in str(m.get('content'))]
|
|
assert guidance
|
|
assert 'Read promising messages' in guidance[0]['content']
|
|
assert 'Preserve explicit account' in guidance[0]['content']
|