Feat/ai4sci tool protocol #1
@@ -288,7 +288,9 @@ class EvoScientistConfig:
|
||||
# a deploy-style langgraph server instead of the in-terminal CLI/TUI.
|
||||
ui_backend: Literal["cli", "tui", "webui"] = "tui"
|
||||
log_level: str = "warning"
|
||||
reasoning_effort: str = "high"
|
||||
# Empty means use the provider/model default. A non-empty value is an
|
||||
# explicit user override exported as EVOSCIENTIST_REASONING_EFFORT.
|
||||
reasoning_effort: str = ""
|
||||
# Anthropic prompt caching for OpenRouter anthropic/* models. Opt out if
|
||||
# cache-write costs outweigh the benefit for a workflow.
|
||||
openrouter_anthropic_prompt_cache: bool = True
|
||||
|
||||
@@ -42,6 +42,12 @@ _DEEPSEEK_BASE_URL = "https://api.deepseek.com"
|
||||
_MOONSHOT_BASE_URL = "https://api.moonshot.cn/v1"
|
||||
_KIMI_CODING_BASE_URL = "https://api.kimi.com/coding/"
|
||||
|
||||
|
||||
def _resolve_reasoning_effort(default: str) -> str:
|
||||
"""Return the configured reasoning effort or a provider-specific default."""
|
||||
return os.environ.get("EVOSCIENTIST_REASONING_EFFORT", "").strip() or default
|
||||
|
||||
|
||||
# Providers routed through the OpenAI provider with a custom base_url.
|
||||
# Maps provider name → (base_url or None, env var for API key).
|
||||
_OPENAI_ROUTED_PROVIDERS: dict[str, tuple[str | None, str]] = {
|
||||
@@ -359,11 +365,17 @@ def _apply_auto_config(
|
||||
# ccproxy uses Chat Completions which doesn't support reasoning.
|
||||
pass
|
||||
else:
|
||||
_eff = (
|
||||
_default_effort = (
|
||||
"xhigh"
|
||||
if ("5.4" in model_id or "5.5" in model_id or "codex" in model_id)
|
||||
if (
|
||||
"5.4" in model_id
|
||||
or "5.5" in model_id
|
||||
or "5.6" in model_id
|
||||
or "codex" in model_id
|
||||
)
|
||||
else "high"
|
||||
)
|
||||
_eff = _resolve_reasoning_effort(_default_effort)
|
||||
kwargs["reasoning"] = {"effort": _eff, "summary": "auto"}
|
||||
|
||||
# Google GenAI: surface thinking traces
|
||||
@@ -508,7 +520,7 @@ def get_chat_model(
|
||||
# passback (OpenRouter's `/responses` beta is stateless, store=false —
|
||||
# "Item with id 'rs_...' not found"); the patch strips them on passback,
|
||||
# so enabling `summary` is safe. See langchain-ai/langchain#37777.
|
||||
effort = os.environ.get("EVOSCIENTIST_REASONING_EFFORT", "").strip() or "high"
|
||||
effort = _resolve_reasoning_effort("high")
|
||||
kwargs.setdefault("reasoning", {"effort": effort, "summary": "auto"})
|
||||
# App attribution (issue #339): identify EvoScientist to OpenRouter so
|
||||
# usage is credited to the project (app rankings, model app tabs,
|
||||
|
||||
@@ -130,7 +130,7 @@ class TestEvoScientistConfig:
|
||||
assert config.show_thinking is True
|
||||
assert config.ui_backend == "tui"
|
||||
assert config.log_level == "warning"
|
||||
assert config.reasoning_effort == "high"
|
||||
assert config.reasoning_effort == ""
|
||||
assert config.openrouter_anthropic_prompt_cache is True
|
||||
assert config.openrouter_http_referer == (
|
||||
"https://github.com/EvoScientist/EvoScientist"
|
||||
|
||||
@@ -2432,6 +2432,11 @@ class TestPatchOpenrouterStripResponsesReasoning:
|
||||
|
||||
|
||||
class TestAutoConfig:
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clear_reasoning_effort_env(self, monkeypatch):
|
||||
"""Keep auto-config tests independent of the developer environment."""
|
||||
monkeypatch.delenv("EVOSCIENTIST_REASONING_EFFORT", raising=False)
|
||||
|
||||
@patch("EvoScientist.llm.models.init_chat_model")
|
||||
def test_anthropic_4_5_thinking(self, mock_init, monkeypatch):
|
||||
"""Anthropic 4-5 models get enabled thinking with budget."""
|
||||
@@ -2521,6 +2526,7 @@ class TestAutoConfig:
|
||||
"""gpt-5.4+ and codex models get xhigh reasoning."""
|
||||
mock_init.return_value = "mock_model"
|
||||
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
|
||||
monkeypatch.delenv("EVOSCIENTIST_REASONING_EFFORT", raising=False)
|
||||
|
||||
get_chat_model("gpt-5.4", provider="openai")
|
||||
assert mock_init.call_args[1]["reasoning"] == {
|
||||
@@ -2540,6 +2546,26 @@ class TestAutoConfig:
|
||||
"summary": "auto",
|
||||
}
|
||||
|
||||
get_chat_model("gpt-5.6-sol", provider="openai")
|
||||
assert mock_init.call_args[1]["reasoning"] == {
|
||||
"effort": "xhigh",
|
||||
"summary": "auto",
|
||||
}
|
||||
|
||||
@patch("EvoScientist.llm.models.init_chat_model")
|
||||
def test_openai_reasoning_effort_from_env(self, mock_init, monkeypatch):
|
||||
"""Native OpenAI reasoning effort should be configurable via env var."""
|
||||
mock_init.return_value = "mock_model"
|
||||
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
|
||||
monkeypatch.setenv("EVOSCIENTIST_REASONING_EFFORT", "high")
|
||||
|
||||
get_chat_model("gpt-5.5", provider="openai")
|
||||
|
||||
assert mock_init.call_args[1]["reasoning"] == {
|
||||
"effort": "high",
|
||||
"summary": "auto",
|
||||
}
|
||||
|
||||
@patch("EvoScientist.llm.models.init_chat_model")
|
||||
def test_openai_reasoning_high_fallback(self, mock_init, monkeypatch):
|
||||
"""Other OpenAI models get high reasoning effort."""
|
||||
|
||||
Reference in New Issue
Block a user