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
Introduce provider, model, and invocation contracts with encrypted configuration persistence. Add web runtime fencing, route fallback, recovery middleware, workspace scoping, and comprehensive tests.
147 lines
5.0 KiB
Python
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
|