Files
EvoScientist-Multi/tests/test_user_options_runtime.py
T
m4 5a581c78a2
Build / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
feat: add scoped model runtime configuration
Introduce provider, model, and invocation contracts with encrypted configuration persistence. Add web runtime fencing, route fallback, recovery middleware, workspace scoping, and comprehensive tests.
2026-08-14 22:03:04 +08:00

147 lines
5.0 KiB
Python

from __future__ import annotations
from dataclasses import replace
from types import SimpleNamespace
import pytest
from EvoScientist.llm.configuration.provider import ResolvedSecret
from EvoScientist.llm.contracts import (
AgentInputV3,
EvoRuntimeError,
HmacGrantAuthority,
WebHostContext,
)
from EvoScientist.llm.model_config import EvoModelConfig
from EvoScientist.llm.runtime import EvoModelRuntime
from EvoScientist.llm.user_options import model_options_schema_hash
from tests.test_provider_model_config_v3 import v3_payload as provider_v3_payload
from tests.test_web_model_runtime import (
_input,
_preparation,
_runtime,
_Sink,
)
from tests.v3_fixtures import (
IDENTITY_KEY_ID,
RUNTIME_KEY_ID,
RUNTIME_SECRET,
identity_ring,
)
@pytest.mark.asyncio
async def test_prepare_rejects_gateway_catalog_schema_that_became_stale(
monkeypatch, tmp_path
):
runtime, authority = _runtime(tmp_path, monkeypatch)
original = _input()
agent_input = replace(
original,
metadata={
**dict(original.metadata),
"model_options_schema_hash": "sha256:stale",
},
)
host = WebHostContext(
"/tmp", "/tmp", object(), object(), runtime_event_sink=_Sink()
)
with pytest.raises(EvoRuntimeError, match="MODEL_OPTIONS_STALE"):
await runtime.prepare_model_run(
_preparation(authority, agent_input),
agent_input,
host,
)
@pytest.mark.asyncio
async def test_prepare_filters_main_only_options_from_inherited_auxiliary_routes():
payload = provider_v3_payload()
payload["config_identity_key_id"] = IDENTITY_KEY_ID
provider = next(
item for item in payload["providers"] if item["adapter_id"] == "openai"
)
model_payload = provider["models"][0]
model_payload["capabilities"]["thinking"] = True
model_payload["parameters"]["reasoning_policy"] = {
"mode": "effort",
"allowed_efforts": ["low", "medium", "high"],
"default_effort": "high",
}
model_payload["parameters"]["user_options"]["temperature"] = {
"default": 1,
"applies_to": ["main_agent"],
"minimum": 0,
"maximum_exclusive": 2,
}
alias_payload = next(
item for item in payload["aliases"] if item["alias"] == "openai-prod-general"
)
alias_payload["defaults"] = {"temperature": 1}
config = EvoModelConfig.parse(payload, require_evidence=False)
authority = HmacGrantAuthority(RUNTIME_SECRET, RUNTIME_KEY_ID)
def resolve_secret(reference):
return ResolvedSecret(
"test-secret", reference.revision, "1", "test-fingerprint"
)
runtime = EvoModelRuntime(
SimpleNamespace(load=lambda: config),
admission_verifier=authority,
quote_authority=authority,
identity_key_ring=identity_ring(),
secret_resolver=resolve_secret,
)
selector = config.resolve_main_selector("openai-prod-general")
selected_model = config.providers[selector.provider].models[selector.model]
selected_provider = config.providers[selector.provider]
schema_hash = model_options_schema_hash(
model_profile_id="openai-prod-general",
user_options=selected_model.user_options,
supports_reasoning=selected_model.supports_reasoning,
reasoning_mode=selected_model.reasoning_mode,
allowed_reasoning_efforts=selected_model.allowed_reasoning_efforts,
parameter_constraints=selected_model.parameter_constraints,
adapter_id=selected_provider.adapter_id,
adapter_revision=selected_provider.adapter_revision,
)
agent_input = AgentInputV3(
"hello",
"web:user:thread",
metadata={
"source": "web",
"model_options": {"temperature": 0.7},
"model_options_schema_hash": schema_hash,
},
)
grant = authority.sign_preparation(
request_id="11111111-1111-4111-8111-111111111111",
turn_id="22222222-2222-4222-8222-222222222222",
thread_id="thread",
subject_id="user",
requested_model_ref="openai-prod-general",
plan="starter",
roles=("user",),
requires_vision=False,
reasoning_effort="high",
title_policy="best_effort",
gateway_input_digest=authority.agent_input_digest(agent_input.projection()),
checkpoint_thread_id=agent_input.checkpoint_thread_id,
checkpoint_snapshot_id="sha256:checkpoint",
turn_fencing_token=1,
ttl_ms=60_000,
)
await runtime.prepare_model_run(
grant,
agent_input,
WebHostContext("/tmp", "/tmp", object(), object(), runtime_event_sink=_Sink()),
)
snapshot = next(iter(runtime._prepared.values())).snapshot
assert snapshot.purpose_routes["main_agent"][0].params["temperature"] == 0.7
assert "temperature" not in snapshot.purpose_routes["tool_selector"][0].params
assert "temperature" not in snapshot.purpose_routes["deepagents_summarizer"][0].params