Minor renaming and docs extension

This commit is contained in:
Michael Panchenko committed 2026-02-01 13:19:40 +07:00
1 parent 2b71875b3c
commit f7ab5b2c85
6 files changed
+50 -46

No files matched your search

+12 -12
View File
@@ -171,7 +171,7 @@ class ProjectConfig(ToolInclusionDefinition, ModeSelectionDefinition, ToStringMi
ignore_all_files_in_gitignore: bool = True
initial_prompt: str = ""
encoding: str = DEFAULT_SOURCE_FILE_ENCODING
include_info_hover_budget_seconds: float | None = None
hover_budget: float | None = None
"""
Per-project override for include_info hover budget (seconds).
@@ -329,16 +329,16 @@ class ProjectConfig(ToolInclusionDefinition, ModeSelectionDefinition, ToStringMi
f"Invalid language: {orig_language_str}.\nValid language_strings are: {[l.value for l in Language]}"
) from e
# Validate include_info_hover_budget_seconds
hover_budget_raw = data["include_info_hover_budget_seconds"]
# Validate hover_budget
hover_budget_raw = data["hover_budget"]
hover_budget = hover_budget_raw
if hover_budget is not None:
try:
hover_budget = float(hover_budget_raw)
except (TypeError, ValueError) as e:
raise ValueError(f"include_info_hover_budget_seconds must be a number or null, got: {hover_budget_raw}") from e
raise ValueError(f"hover_budget must be a number or null, got: {hover_budget_raw}") from e
if hover_budget < 0:
raise ValueError(f"include_info_hover_budget_seconds cannot be negative, got: {hover_budget}")
raise ValueError(f"hover_budget cannot be negative, got: {hover_budget}")
return cls(
project_name=data["project_name"],
@@ -353,7 +353,7 @@ class ProjectConfig(ToolInclusionDefinition, ModeSelectionDefinition, ToStringMi
encoding=data["encoding"],
base_modes=data["base_modes"],
default_modes=data["default_modes"],
include_info_hover_budget_seconds=hover_budget,
hover_budget=hover_budget,
)
def _to_yaml_dict(self) -> dict:
@@ -511,7 +511,7 @@ class SerenaConfig(ToolInclusionDefinition, ModeSelectionDefinition, ToStringMix
ls_specific_settings: dict = field(default_factory=dict)
"""Advanced configuration option allowing to configure language server implementation specific options, see SolidLSPSettings for more info."""
include_info_hover_budget_seconds: float = 5.0
hover_budget: float = 5.0
"""
Time budget (seconds) for LSP hover requests when tools request include_info.
@@ -660,15 +660,15 @@ class SerenaConfig(ToolInclusionDefinition, ModeSelectionDefinition, ToStringMix
instance.log_level = loaded_commented_yaml["gui_log_level"]
del loaded_commented_yaml["gui_log_level"]
# Load and validate include_info_hover_budget_seconds
hover_budget_raw = get_value_or_default("include_info_hover_budget_seconds")
# Load and validate hover_budget
hover_budget_raw = get_value_or_default("hover_budget")
try:
hover_budget = float(hover_budget_raw)
except (TypeError, ValueError) as e:
raise ValueError(f"include_info_hover_budget_seconds must be a number, got: {hover_budget_raw}") from e
raise ValueError(f"hover_budget must be a number, got: {hover_budget_raw}") from e
if hover_budget < 0:
raise ValueError(f"include_info_hover_budget_seconds cannot be negative, got: {hover_budget}")
instance.include_info_hover_budget_seconds = hover_budget
raise ValueError(f"hover_budget cannot be negative, got: {hover_budget}")
instance.hover_budget = hover_budget
# re-save the configuration file if any migrations were performed
if num_migrations > 0:
+3 -4
View File
@@ -110,7 +110,6 @@ default_modes:
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""
# Per-project override for include_info hover budget (seconds).
# If null or missing, global config is used.
# 0 disables the budget (no early stopping). Negative values are invalid.
include_info_hover_budget_seconds: null
# Override of the correspounding setting in serena_config.yml, see the documentation there.
# If null or missing, the value from the global config is used.
hover_budget: null
@@ -103,10 +103,14 @@ default_max_tool_answer_chars: 150000
# estimate the token count using the Claude Sonnet 4 tokenizer.
token_count_estimator: CHAR_COUNT
# Time budget (seconds) for LSP hover requests when tools request include_info.
# If budget is exceeded, Serena stops issuing further hover requests and returns partial info results.
# Time budget (seconds) budget for LSP request_hover calls within an MCP tool call (in seconds).
# This is an advanced setting that can help alleviate problems with LSP servers
# that have a slow implementation of request_hover (clangd is one of those)
# or with tool calls that find very many symbols.
# If the configured budget is exceeded, Serena stops issuing further hover requests and returns partial info results.
# 0 disables the budget (no early stopping). Negative values are invalid.
include_info_hover_budget_seconds: 5
# Can be overridden in project.yml.
hover_budget: 10
# the list of registered project paths (updated automatically).
projects: []
+9 -8
View File
@@ -552,17 +552,17 @@ class LanguageServerSymbolRetriever:
return None
return self._request_info(relative_file_path=symbol.relative_path, line=symbol.line, column=symbol.column) # type: ignore[arg-type]
def _get_hover_budget(self, default_budget: float = 5) -> float:
def _get_hover_budget(self, default_budget: float = 10) -> float:
"""Project -> global -> default"""
hover_budget_seconds = default_budget
hover_budget = default_budget
if self.agent is not None:
hover_budget_seconds = self.agent.serena_config.include_info_hover_budget_seconds
hover_budget = self.agent.serena_config.hover_budget
active_project = self.agent.get_active_project()
if active_project is not None:
project_hover_budget = active_project.project_config.include_info_hover_budget_seconds
project_hover_budget = active_project.project_config.hover_budget
if project_hover_budget is not None:
hover_budget_seconds = project_hover_budget
return hover_budget_seconds
hover_budget = project_hover_budget
return hover_budget
def request_info_for_symbol_batch(
self,
@@ -577,7 +577,7 @@ class LanguageServerSymbolRetriever:
Groups symbols by file path to minimize file switching overhead and uses a per-file
cache keyed by (line, col) to avoid duplicate hover lookups.
The hover budget (include_info_hover_budget_seconds) limits total time spent on hover
The hover budget (hover_budget) limits total time spent on hover
requests. If exceeded, remaining symbols get info=None (partial results).
:param symbols: list of symbols to get info for
@@ -617,7 +617,8 @@ class LanguageServerSymbolRetriever:
file_hover_lookups = 0
for sym in file_symbols:
# Check budget before starting new hover request
# Check budget before starting a new hover request
# hover_budget_seconds=0 disables the budget mechanism (the first inequality)
if 0 < hover_budget_seconds <= hover_spent_seconds:
skipped_due_to_budget += 1
info = None
+11 -11
View File
@@ -127,7 +127,7 @@ class TestProjectConfig:
class TestProjectConfigHoverBudget:
"""Test class for include_info_hover_budget_seconds validation in ProjectConfig."""
"""Test class for hover_budget validation in ProjectConfig."""
def _base_project_dict(self, **overrides):
data = {
@@ -140,7 +140,7 @@ class TestProjectConfigHoverBudget:
"ignore_all_files_in_gitignore": True,
"initial_prompt": "",
"encoding": "utf-8",
"include_info_hover_budget_seconds": None,
"hover_budget": None,
}
data.update(overrides)
return data
@@ -149,23 +149,23 @@ class TestProjectConfigHoverBudget:
"""Test that _from_dict accepts null hover budget (for inheritance)."""
data = self._base_project_dict()
config = ProjectConfig._from_dict(data)
assert config.include_info_hover_budget_seconds is None
assert config.hover_budget is None
def test_from_dict_accepts_positive_budget(self):
"""Test that _from_dict accepts positive hover budget."""
data = self._base_project_dict(include_info_hover_budget_seconds=10.5)
data = self._base_project_dict(hover_budget=10.5)
config = ProjectConfig._from_dict(data)
assert config.include_info_hover_budget_seconds == 10.5
assert config.hover_budget == 10.5
def test_from_dict_accepts_zero_budget(self):
"""Test that _from_dict accepts zero hover budget (disabled)."""
data = self._base_project_dict(include_info_hover_budget_seconds=0)
data = self._base_project_dict(hover_budget=0)
config = ProjectConfig._from_dict(data)
assert config.include_info_hover_budget_seconds == 0.0
assert config.hover_budget == 0.0
def test_from_dict_rejects_negative_budget(self):
"""Test that _from_dict raises ValueError for negative hover budget."""
data = self._base_project_dict(include_info_hover_budget_seconds=-1.0)
data = self._base_project_dict(hover_budget=-1.0)
with pytest.raises(ValueError) as exc_info:
ProjectConfig._from_dict(data)
assert "cannot be negative" in str(exc_info.value)
@@ -174,14 +174,14 @@ class TestProjectConfigHoverBudget:
"""Test that _apply_defaults_to_dict preserves None for hover budget."""
data = {"project_name": "test", "languages": ["python"]}
result = ProjectConfig._apply_defaults_to_dict(data)
assert result["include_info_hover_budget_seconds"] is None
assert result["hover_budget"] is None
def test_apply_defaults_preserves_explicit_value(self):
"""Test that _apply_defaults_to_dict preserves explicit hover budget value."""
data = {
"project_name": "test",
"languages": ["python"],
"include_info_hover_budget_seconds": 15.0,
"hover_budget": 15.0,
}
result = ProjectConfig._apply_defaults_to_dict(data)
assert result["include_info_hover_budget_seconds"] == 15.0
assert result["hover_budget"] == 15.0
+8 -8
View File
@@ -256,14 +256,14 @@ def _make_mock_symbols(count: int, *, relative_path: str = "test_repo/services.p
@pytest.mark.python
class TestHoverBudget:
"""Tests for include_info_hover_budget_seconds time budget behavior."""
"""Tests for hover_budget time budget behavior."""
@pytest.mark.parametrize("language_server", [Language.PYTHON], indirect=True)
def test_budget_not_exceeded_all_lookups_performed(self, language_server: SolidLanguageServer, monkeypatch: pytest.MonkeyPatch):
"""With a large budget, all hover lookups are performed."""
# Create symbol retriever with a mock agent that has large budget
mock_agent = MagicMock()
mock_agent.serena_config.include_info_hover_budget_seconds = 10.0
mock_agent.serena_config.hover_budget = 10.0
mock_agent.get_active_project.return_value = None
symbol_retriever = LanguageServerSymbolRetriever(language_server, agent=mock_agent)
@@ -293,7 +293,7 @@ class TestHoverBudget:
"""With a small budget, hover lookups stop and remaining symbols get None info."""
# Create symbol retriever with a mock agent that has small budget (0.1s)
mock_agent = MagicMock()
mock_agent.serena_config.include_info_hover_budget_seconds = 0.1
mock_agent.serena_config.hover_budget = 0.1
mock_agent.get_active_project.return_value = None
symbol_retriever = LanguageServerSymbolRetriever(language_server, agent=mock_agent)
@@ -339,7 +339,7 @@ class TestHoverBudget:
"""With budget=0, all hover lookups proceed (no early stopping)."""
# Create symbol retriever with budget=0 (unlimited)
mock_agent = MagicMock()
mock_agent.serena_config.include_info_hover_budget_seconds = 0.0
mock_agent.serena_config.hover_budget = 0.0
mock_agent.get_active_project.return_value = None
symbol_retriever = LanguageServerSymbolRetriever(language_server, agent=mock_agent)
@@ -368,10 +368,10 @@ class TestHoverBudget:
"""Project-level budget overrides global budget."""
# Create symbol retriever with global budget 10.0 but project budget 0.05
mock_project = MagicMock()
mock_project.project_config.include_info_hover_budget_seconds = 0.05
mock_project.project_config.hover_budget = 0.05
mock_agent = MagicMock()
mock_agent.serena_config.include_info_hover_budget_seconds = 10.0
mock_agent.serena_config.hover_budget = 10.0
mock_agent.get_active_project.return_value = mock_project
symbol_retriever = LanguageServerSymbolRetriever(language_server, agent=mock_agent)
@@ -410,10 +410,10 @@ class TestHoverBudget:
"""When project budget is None, global budget is used."""
# Create symbol retriever with project budget=None (inherit global)
mock_project = MagicMock()
mock_project.project_config.include_info_hover_budget_seconds = None
mock_project.project_config.hover_budget = None
mock_agent = MagicMock()
mock_agent.serena_config.include_info_hover_budget_seconds = 10.0
mock_agent.serena_config.hover_budget = 10.0
mock_agent.get_active_project.return_value = mock_project
symbol_retriever = LanguageServerSymbolRetriever(language_server, agent=mock_agent)