mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-14 02:16:21 +00:00
Minor renaming and docs extension
This commit is contained in:
1 parent
2b71875b3c
commit
f7ab5b2c85
6 files changed
+50
-46
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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: []
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user