mirror of
https://github.com/usestrix/strix.git
synced 2026-08-17 17:30:27 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d98fb167eb |
@@ -36,6 +36,10 @@ class LlmSettings(BaseSettings):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
reasoning_effort: ReasoningEffort = Field(default="high", alias="STRIX_REASONING_EFFORT")
|
reasoning_effort: ReasoningEffort = Field(default="high", alias="STRIX_REASONING_EFFORT")
|
||||||
|
force_required_tool_choice: bool = Field(
|
||||||
|
default=False,
|
||||||
|
alias="STRIX_FORCE_REQUIRED_TOOL_CHOICE",
|
||||||
|
)
|
||||||
timeout: int = Field(default=300, alias="LLM_TIMEOUT")
|
timeout: int = Field(default=300, alias="LLM_TIMEOUT")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -8,7 +8,11 @@ from typing import TYPE_CHECKING, Any
|
|||||||
from agents.model_settings import ModelSettings
|
from agents.model_settings import ModelSettings
|
||||||
from openai.types.shared import Reasoning
|
from openai.types.shared import Reasoning
|
||||||
|
|
||||||
from strix.config.models import DEFAULT_MODEL_RETRY, model_supports_reasoning
|
from strix.config.models import (
|
||||||
|
DEFAULT_MODEL_RETRY,
|
||||||
|
is_known_openai_bare_model,
|
||||||
|
model_supports_reasoning,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -18,6 +22,11 @@ if TYPE_CHECKING:
|
|||||||
DEFAULT_MAX_TURNS = 500
|
DEFAULT_MAX_TURNS = 500
|
||||||
|
|
||||||
|
|
||||||
|
def _accepts_required_tool_choice(model_name: str | None) -> bool:
|
||||||
|
name = (model_name or "").strip().lower()
|
||||||
|
return name.startswith("openai/") or is_known_openai_bare_model(name)
|
||||||
|
|
||||||
|
|
||||||
def build_root_task(scan_config: dict[str, Any]) -> str:
|
def build_root_task(scan_config: dict[str, Any]) -> str:
|
||||||
targets = scan_config.get("targets", []) or []
|
targets = scan_config.get("targets", []) or []
|
||||||
diff_scope = scan_config.get("diff_scope") or {}
|
diff_scope = scan_config.get("diff_scope") or {}
|
||||||
@@ -111,6 +120,7 @@ def make_model_settings(
|
|||||||
reasoning_effort: ReasoningEffort | None,
|
reasoning_effort: ReasoningEffort | None,
|
||||||
*,
|
*,
|
||||||
model_name: str,
|
model_name: str,
|
||||||
|
force_required_tool_choice: bool = False,
|
||||||
) -> ModelSettings:
|
) -> ModelSettings:
|
||||||
model_settings = ModelSettings(
|
model_settings = ModelSettings(
|
||||||
parallel_tool_calls=False,
|
parallel_tool_calls=False,
|
||||||
@@ -125,6 +135,8 @@ def make_model_settings(
|
|||||||
model_settings = model_settings.resolve(
|
model_settings = model_settings.resolve(
|
||||||
ModelSettings(reasoning=Reasoning(effort=reasoning_effort)),
|
ModelSettings(reasoning=Reasoning(effort=reasoning_effort)),
|
||||||
)
|
)
|
||||||
|
if force_required_tool_choice and _accepts_required_tool_choice(model_name):
|
||||||
|
model_settings = model_settings.resolve(ModelSettings(tool_choice="required"))
|
||||||
return model_settings
|
return model_settings
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ async def run_strix_scan(
|
|||||||
model_settings = make_model_settings(
|
model_settings = make_model_settings(
|
||||||
settings.llm.reasoning_effort,
|
settings.llm.reasoning_effort,
|
||||||
model_name=resolved_model,
|
model_name=resolved_model,
|
||||||
|
force_required_tool_choice=settings.llm.force_required_tool_choice,
|
||||||
)
|
)
|
||||||
run_config = RunConfig(
|
run_config = RunConfig(
|
||||||
model=resolved_model,
|
model=resolved_model,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ _LLM_ENV_KEYS = [
|
|||||||
"LITELLM_BASE_URL",
|
"LITELLM_BASE_URL",
|
||||||
"OLLAMA_API_BASE",
|
"OLLAMA_API_BASE",
|
||||||
"STRIX_REASONING_EFFORT",
|
"STRIX_REASONING_EFFORT",
|
||||||
|
"STRIX_FORCE_REQUIRED_TOOL_CHOICE",
|
||||||
"LLM_TIMEOUT",
|
"LLM_TIMEOUT",
|
||||||
"PERPLEXITY_API_KEY",
|
"PERPLEXITY_API_KEY",
|
||||||
# RuntimeSettings
|
# RuntimeSettings
|
||||||
|
|||||||
+24
-1
@@ -7,7 +7,7 @@ from typing import Any
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from strix.core.inputs import build_root_task, child_initial_input
|
from strix.core.inputs import build_root_task, child_initial_input, make_model_settings
|
||||||
|
|
||||||
|
|
||||||
def _child_kwargs(parent_history: list[Any]) -> dict[str, Any]:
|
def _child_kwargs(parent_history: list[Any]) -> dict[str, Any]:
|
||||||
@@ -112,3 +112,26 @@ def test_build_root_task_diff_scope() -> None:
|
|||||||
assert "Scope Constraints:" in task
|
assert "Scope Constraints:" in task
|
||||||
assert "3 changed file(s)" in task
|
assert "3 changed file(s)" in task
|
||||||
assert "2 deleted file(s)" in task
|
assert "2 deleted file(s)" in task
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("model_name", ["openai/o3", "gpt-4o"])
|
||||||
|
def test_make_model_settings_forces_required_tool_choice_for_openai_models(
|
||||||
|
model_name: str,
|
||||||
|
) -> None:
|
||||||
|
settings = make_model_settings(
|
||||||
|
"none",
|
||||||
|
model_name=model_name,
|
||||||
|
force_required_tool_choice=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert settings.tool_choice == "required"
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_model_settings_skips_required_tool_choice_for_non_openai_models() -> None:
|
||||||
|
settings = make_model_settings(
|
||||||
|
"none",
|
||||||
|
model_name="anthropic/claude-3-7-sonnet-latest",
|
||||||
|
force_required_tool_choice=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert settings.tool_choice is None
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ async def test_persistent_rate_limit_stops_gracefully(
|
|||||||
monkeypatch.setattr(runner, "set_scan_id", lambda _scan_id: None)
|
monkeypatch.setattr(runner, "set_scan_id", lambda _scan_id: None)
|
||||||
|
|
||||||
settings = types.SimpleNamespace(
|
settings = types.SimpleNamespace(
|
||||||
llm=types.SimpleNamespace(model="openai/gpt-4o", reasoning_effort="high")
|
llm=types.SimpleNamespace(
|
||||||
|
model="openai/gpt-4o",
|
||||||
|
reasoning_effort="high",
|
||||||
|
force_required_tool_choice=False,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
monkeypatch.setattr(runner, "load_settings", lambda: settings)
|
monkeypatch.setattr(runner, "load_settings", lambda: settings)
|
||||||
monkeypatch.setattr(runner, "configure_sdk_model_defaults", lambda _settings: None)
|
monkeypatch.setattr(runner, "configure_sdk_model_defaults", lambda _settings: None)
|
||||||
|
|||||||
Reference in New Issue
Block a user