mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 23:12:22 +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.
127 lines
6.3 KiB
Python
127 lines
6.3 KiB
Python
import copy
|
|
import json
|
|
import os
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from src.clean_agent_preview import conversation
|
|
from src.tool_policy import ToolPolicy
|
|
from src.tool_routing_experiment import MODEL_CHOICE_MODE, select_experiment_inventory
|
|
from src.tool_schemas import FUNCTION_TOOL_SCHEMAS
|
|
from src.turn_contract import (requested_capabilities, resolve_turn_contract,
|
|
resolve_full_inventory_contract, result_reference_followup)
|
|
|
|
|
|
def search_history(body_size=0):
|
|
return [
|
|
{'role': 'user', 'content': 'Search when the new folding phone is out'},
|
|
{'role': 'assistant', 'content': 'The release date is in these reports.', 'metadata': {
|
|
'tool_events': [{'tool': 'web_search', 'exit_code': 0}],
|
|
'clean_v3_turn': [
|
|
{'role': 'assistant', 'content': None, 'tool_calls': [
|
|
{'id': 'search1', 'type': 'function', 'function': {
|
|
'name': 'web_search', 'arguments': '{"query":"folding phone"}'}}]},
|
|
{'role': 'tool', 'tool_call_id': 'search1', 'content':
|
|
'```sources\n[1] Release guide\n https://example.org/release\n'
|
|
'[2] Details\n https://example.org/details\n```\n' + 'x' * body_size},
|
|
],
|
|
}},
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize('prompt', ['Link more info', 'More information', 'More details about that',
|
|
'Send the links', 'Please show me the source', 'Open that', 'Read the second result'])
|
|
@pytest.mark.parametrize('mode', ['baseline', MODEL_CHOICE_MODE])
|
|
def test_referential_web_inventory_does_not_offer_files(prompt, mode):
|
|
history = search_history()
|
|
capabilities = requested_capabilities(prompt, history)
|
|
assert capabilities == {'search_browser'}
|
|
policy = ToolPolicy(disabled_tools=frozenset({'private_browser'}))
|
|
routed = resolve_turn_contract(capabilities=capabilities, schemas=FUNCTION_TOOL_SCHEMAS, policy=policy)
|
|
inventory = resolve_full_inventory_contract(schemas=FUNCTION_TOOL_SCHEMAS, policy=policy)
|
|
result = select_experiment_inventory(inventory, routed, history, mode, user_text=prompt)
|
|
assert 'web_fetch' in result.offered
|
|
assert not result.offered & {'read_file', 'bash', 'python', 'private_browser'}
|
|
assert not result.required
|
|
|
|
|
|
@pytest.mark.parametrize('prompt', ['Read /workspace/notes.md', 'Search my email',
|
|
'Save that link as a note', 'More details about my calendar',
|
|
'Send the link by email', 'Open that and run a Python script'])
|
|
def test_new_task_is_not_a_source_only_followup(prompt):
|
|
assert not result_reference_followup(prompt)
|
|
|
|
|
|
@pytest.mark.parametrize('body_size', [0, 30000])
|
|
def test_observed_source_references_survive_trimming(body_size):
|
|
history = search_history(body_size)
|
|
original = copy.deepcopy(history)
|
|
result = conversation(SimpleNamespace(history=history), [{'role': 'user', 'content': 'Link more info'}])
|
|
context = result[-2]
|
|
assert context['metadata']['trusted'] is False
|
|
assert context['metadata']['source'] == 'previous turn source references'
|
|
assert '[Source: Release guide](https://example.org/release)' in context['content']
|
|
assert 'https://example.org/details' in context['content']
|
|
assert len(context['content']) < 2000
|
|
assert result[-1]['content'] == 'Link more info'
|
|
assert history == original
|
|
if body_size:
|
|
assert not any(m['role'] == 'tool' for m in result)
|
|
|
|
|
|
def test_old_sources_do_not_cross_an_intervening_topic():
|
|
history = search_history() + [
|
|
{'role': 'user', 'content': 'What is 2+2?'},
|
|
{'role': 'assistant', 'content': '4'},
|
|
]
|
|
result = conversation(SimpleNamespace(history=history), [{'role': 'user', 'content': 'More info'}])
|
|
assert not any(m.get('metadata', {}).get('source') == 'previous turn source references' for m in result)
|
|
|
|
|
|
def test_assistant_prose_is_not_observed_source_evidence():
|
|
history = [{'role': 'user', 'content': 'Search for phones'},
|
|
{'role': 'assistant', 'content': 'https://invented.example/release'}]
|
|
result = conversation(SimpleNamespace(history=history), [{'role': 'user', 'content': 'Link more info'}])
|
|
assert not any(m.get('metadata', {}).get('source') == 'previous turn source references' for m in result)
|
|
|
|
|
|
def test_result_reference_uses_the_actual_domain():
|
|
history = [{'role': 'user', 'content': 'Search my notes'},
|
|
{'role': 'assistant', 'content': 'Found a note', 'metadata': {
|
|
'tool_events': [{'tool': 'manage_notes', 'exit_code': 0}]}}]
|
|
assert requested_capabilities('More info', history) == {'notes'}
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.skipif(not os.getenv('ODYSSEUS_AJAX_TEST_URL'), reason='Opt-in live Ajax replay')
|
|
async def test_live_ajax_links_observed_sources_without_local_files(monkeypatch):
|
|
import src.clean_agent_preview as preview
|
|
calls = []
|
|
|
|
async def execute(block, *args, **kwargs):
|
|
calls.append(block.tool_type)
|
|
return 'fixture', {'exit_code': 0, 'output':
|
|
'[1] Release guide\n https://example.org/release\n'
|
|
'[2] Details\n https://example.org/details'}
|
|
|
|
monkeypatch.setattr(preview, 'execute_tool_block', execute)
|
|
rows = search_history(30000)
|
|
policy = ToolPolicy()
|
|
prompt = 'Link more info'
|
|
routed = resolve_turn_contract(capabilities=requested_capabilities(prompt, rows),
|
|
schemas=FUNCTION_TOOL_SCHEMAS, policy=policy)
|
|
inventory = resolve_full_inventory_contract(schemas=FUNCTION_TOOL_SCHEMAS, policy=policy)
|
|
contract = select_experiment_inventory(inventory, routed, rows, MODEL_CHOICE_MODE, user_text=prompt)
|
|
events = [json.loads(chunk[6:]) async for chunk in preview.stream_preview(
|
|
endpoint_url=os.environ['ODYSSEUS_AJAX_TEST_URL'], model='Ajax', headers={},
|
|
turn_contract=contract, messages=[{'role': 'user', 'content': prompt}],
|
|
history_session=SimpleNamespace(history=rows), session_id='source-reference-test',
|
|
owner='test', disabled_tools=set(), tool_policy=policy, thinking_mode='off',
|
|
) if '[DONE]' not in chunk]
|
|
answer = ''.join(e.get('delta', '') or e.get('content', '') for e in events)
|
|
# The renderer supports both Markdown links and bare HTTP(S) autolinks.
|
|
assert 'https://example.org/release' in answer, json.dumps(events, ensure_ascii=False)
|
|
assert 'https://example.org/details' in answer, answer
|
|
assert not set(calls) & {'read_file', 'bash', 'python'}
|