mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-13 02:12:21 +02:00
merge: reconcile PR 40 with current lab
Integrate lab fff55a78 into PR #40 (cc25d5ba). Lab's modular email backend/frontend, modular settings, split stylesheets (static/style.css stays deleted), procfs compatibility, and request-scoped TurnContract authority win; PR #40's routing classifiers, editor/email/task features, and style.css changes are ported into lab's module and stylesheet homes. Integration fixes: - settings/api.js imports ui.js under its canonical versioned URL - browser observations keep legacy CAPTCHA/access-block evidence - artifact turns do not re-trigger broad-web research recovery - env reference documents PR test-tool variables; page regenerated PR #40 defects surfaced by lab gates and fixed here: - web_fetch generic schema drops top-level anyOf (OpenAI contract); the compact preview contract still requires url or urls - get_weather registered as a brokered network read - new lazy editor modules precached for offline use - SearXNG pin mirrored into GPU standalone compose files - image model picker again skips offline endpoints Tests updated where PR #40 changed behaviour on purpose, and PR tests moved onto lab's document_source helpers.
This commit is contained in:
@@ -4377,11 +4377,13 @@ def test_v3_schema_uses_configured_versioned_contract_root(tmp_path, monkeypatch
|
||||
monkeypatch.setenv('ODYSSEUS_TOOL_CONTRACT_ROOT', str(contract_root))
|
||||
module.contract_builder.cache_clear()
|
||||
try:
|
||||
notes = next(
|
||||
# Probe a tool whose compact description the harness does not
|
||||
# replace; manage_notes now carries a full harness-owned override.
|
||||
search = next(
|
||||
s for s in FUNCTION_TOOL_SCHEMAS
|
||||
if s['function']['name'] == 'manage_notes'
|
||||
if s['function']['name'] == 'web_search'
|
||||
)
|
||||
compact = module.compact_schemas([notes])[0]
|
||||
compact = module.compact_schemas([search])[0]
|
||||
assert compact['function']['description'].startswith('versioned-contract-loaded')
|
||||
finally:
|
||||
module.contract_builder.cache_clear()
|
||||
@@ -4392,7 +4394,8 @@ def test_v3_document_edit_schema_has_one_unambiguous_structured_form():
|
||||
if s['function']['name'] == 'edit_document')
|
||||
parameters = edit['function']['parameters']
|
||||
assert parameters['required'] == ['edits']
|
||||
assert set(parameters['properties']) == {'edits'}
|
||||
assert set(parameters['properties']) == {'edits', 'more'}
|
||||
assert parameters['properties']['more']['type'] == 'boolean'
|
||||
|
||||
|
||||
def test_v3_ui_schema_advertises_only_policy_executable_client_local_actions():
|
||||
@@ -5650,7 +5653,7 @@ async def test_blocked_search_engine_browser_forces_native_web_search(monkeypatc
|
||||
)
|
||||
raw = [chunk async for chunk in stream_preview(
|
||||
endpoint_url='http://test', model='test',
|
||||
messages=[{'role': 'user', 'content': 'Open browser and find the latest AI news.'}],
|
||||
messages=[{'role': 'user', 'content': 'Open browser and find an AI model release.'}],
|
||||
headers={}, turn_contract=contract, session_id='test', owner='test',
|
||||
disabled_tools=set(), tool_policy=ToolPolicy(), max_rounds=4,
|
||||
)]
|
||||
@@ -5720,7 +5723,9 @@ async def test_native_stream_reserves_remaining_budget_for_required_artifact(mon
|
||||
|
||||
async def execute(block, **kwargs):
|
||||
executed.append(block.tool_type)
|
||||
return block.tool_type, {"output": "ok", "exit_code": 0}
|
||||
return block.tool_type, {"output": "ok", "exit_code": 0,
|
||||
"materialized_artifacts": ["/tmp_workspace/results"]
|
||||
if block.tool_type == "python" and "out.md" in block.content else []}
|
||||
|
||||
monkeypatch.setattr(module.httpx, "AsyncClient", Client)
|
||||
monkeypatch.setattr(module, "execute_tool_block", execute)
|
||||
@@ -5832,7 +5837,9 @@ async def test_native_stream_reserves_wall_time_for_required_artifact(monkeypatc
|
||||
executed.append(block.tool_type)
|
||||
if block.tool_type == "web_search":
|
||||
now[0] = 450.0
|
||||
return block.tool_type, {"output": "ok", "exit_code": 0}
|
||||
return block.tool_type, {"output": "ok", "exit_code": 0,
|
||||
"materialized_artifacts": ["/tmp_workspace/results"]
|
||||
if block.tool_type == "python" and "out.md" in block.content else []}
|
||||
|
||||
monkeypatch.setattr(module.time, "monotonic", lambda: now[0])
|
||||
monkeypatch.setattr(module.httpx, "AsyncClient", Client)
|
||||
@@ -6431,7 +6438,7 @@ async def test_native_stream_terminates_after_calling_a_permanently_suppressed_t
|
||||
{"choices": [{"delta": {"tool_calls": [{"index": 0, "id": f"inspect-{index}", "function": {
|
||||
"name": "inspect_media", "arguments": arguments,
|
||||
}}]}}]}
|
||||
for index in range(1, 5)
|
||||
for index in range(1, 4)
|
||||
] + [{"choices": [{"delta": {"content": "Final answer from existing evidence."}}]}])
|
||||
|
||||
class Response:
|
||||
@@ -6479,9 +6486,9 @@ async def test_native_stream_terminates_after_calling_a_permanently_suppressed_t
|
||||
|
||||
events = [json.loads(chunk[6:]) for chunk in raw if "[DONE]" not in chunk]
|
||||
assert len(executions) == 1
|
||||
assert len(requests) == 5
|
||||
assert 'tools' not in requests[4]
|
||||
assert 'best concise final answer' in requests[4]['messages'][-1]['content'].lower()
|
||||
assert len(requests) == 4
|
||||
assert 'tools' not in requests[3]
|
||||
assert 'best concise final answer' in requests[3]['messages'][-1]['content'].lower()
|
||||
final = [event for event in events if event.get("type") == "final_response"]
|
||||
assert final == []
|
||||
metrics = next(event['data'] for event in events if event.get('type') == 'metrics')
|
||||
|
||||
Reference in New Issue
Block a user