Files
odysseus/tests/test_session_mutation_lookup.py
T
pewdiepie-archdaemon 2e8413a54a Preserve preview harness, editor, email and task improvements
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.
2026-10-01 01:34:26 +00:00

94 lines
4.5 KiB
Python

from types import SimpleNamespace
import pytest
from src.clean_agent_preview import dependent_write_prerequisite_error, required_read_tool_choice
from src.turn_contract import selected_tools_for_request
@pytest.mark.parametrize('prompt', [
'delete my last chat', 'remove my previous conversation',
'archive my last session', 'rename my last chat',
])
def test_session_mutations_include_lookup(prompt):
assert selected_tools_for_request(prompt) == {'list_sessions', 'manage_session'}
def contract():
return SimpleNamespace(required={'list_sessions', 'manage_session'},
required_read_operation=None, permits=lambda name: True)
def test_lookup_precedes_mutation_and_clarification_remains_possible():
tools = [{'function': {'name': name}} for name in ('manage_session', 'list_sessions')]
assert required_read_tool_choice(contract(), tools) == {
'type': 'function', 'function': {'name': 'list_sessions'}}
assert required_read_tool_choice(contract(), tools, calls=1,
attempted_required_tools={'list_sessions'}) is None
def test_failed_or_missing_lookup_cannot_unlock_mutation():
assert dependent_write_prerequisite_error(contract(), 'manage_session', set())
assert dependent_write_prerequisite_error(contract(), 'manage_session', {'web_search'})
assert dependent_write_prerequisite_error(contract(), 'manage_session', {'list_sessions'}) is None
def test_unavailable_lookup_does_not_force_delete():
assert required_read_tool_choice(contract(), [{'function': {'name': 'manage_session'}}]) is None
assert dependent_write_prerequisite_error(contract(), 'manage_session', set())
@pytest.mark.asyncio
async def test_stream_orders_lookup_before_mutation_without_touching_real_chats(monkeypatch):
import json
from dataclasses import replace
import src.clean_agent_preview as module
from src.tool_policy import ToolPolicy
from src.tool_schemas import FUNCTION_TOOL_SCHEMAS
from src.turn_contract import resolve_full_inventory_contract
calls, requests = [], []
def tool(name, args):
return {'tool_calls': [{'index': 0, 'id': name, 'type': 'function',
'function': {'name': name, 'arguments': json.dumps(args)}}]}
responses = iter([tool('list_sessions', {}),
tool('manage_session', {'action': 'delete', 'session_id': 'fixture-previous'}),
{'content': 'Deleted the previous fixture chat.'}])
class Response:
def __init__(self, delta): self.delta = delta
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': self.delta}]})
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(kwargs['json'])
return Response(next(responses))
async def execute(block, **kwargs):
calls.append(block.tool_type)
result = ('fixture-current: current chat; fixture-previous: previous chat'
if block.tool_type == 'list_sessions' else 'Deleted fixture-previous')
return block.tool_type, {'results': result, 'exit_code': 0}
monkeypatch.setattr(module.httpx, 'AsyncClient', Client)
monkeypatch.setattr(module, 'execute_tool_block', execute)
policy = ToolPolicy()
schemas = [s for s in FUNCTION_TOOL_SCHEMAS
if s['function']['name'] in {'list_sessions', 'manage_session'}]
scoped = replace(resolve_full_inventory_contract(schemas=schemas, policy=policy),
required=frozenset({'list_sessions', 'manage_session'}),
active_capabilities=frozenset({'sessions'}),
capabilities=frozenset({'sessions'}))
chunks = [chunk async for chunk in module.stream_preview(
endpoint_url='http://fixture', model='test', headers={}, turn_contract=scoped,
messages=[{'role': 'user', 'content': 'delete my last chat'}],
session_id='fixture-current', owner='test', disabled_tools=set(), tool_policy=policy)]
assert calls == ['list_sessions', 'manage_session'], '\n'.join(chunks)
assert requests[0]['tool_choice']['function']['name'] == 'list_sessions'
assert requests[1].get('tool_choice') is None
assert any('[DONE]' in chunk for chunk in chunks)