mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 14:16:21 +00:00
Ensure consistent mode configuration for project
Enabled modes must not depend on project activation order. Always apply, in order: SerenaConfig, ProjectConfig, current CLI overrides
This commit is contained in:
1 parent
5b103ee281
commit
40a3075cc0
1 file changed
+22
-23
+22
-23
@@ -331,26 +331,20 @@ class SerenaAgent:
|
|||||||
self.prompt_factory = SerenaPromptFactory()
|
self.prompt_factory = SerenaPromptFactory()
|
||||||
self._project_activation_callback = project_activation_callback
|
self._project_activation_callback = project_activation_callback
|
||||||
|
|
||||||
# initialize active modes based on the global configuration
|
# initialize members for modes and tools
|
||||||
|
self._mode_overrides = modes
|
||||||
self._active_modes = ActiveModes()
|
self._active_modes = ActiveModes()
|
||||||
self._active_modes.apply(self.serena_config)
|
self._active_tools: AvailableTools = self._exposed_tools
|
||||||
|
|
||||||
# activate a project configuration (if provided or if there is only a single project available)
|
# activate a project configuration (if provided or if there is only a single project available)
|
||||||
if project is not None:
|
if project is not None:
|
||||||
try:
|
try:
|
||||||
# Note: This will apply the project's mode selections (if any).
|
self.activate_project_from_path_or_name(project, update_modes_and_tools=False)
|
||||||
# We do not yet update the tool set, as we need to apply mode overrides first (see below).
|
|
||||||
self.activate_project_from_path_or_name(project, update_tools=False)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"Error activating project '{project}' at startup: {e}", exc_info=e)
|
log.error(f"Error activating project '{project}' at startup: {e}", exc_info=e)
|
||||||
|
|
||||||
# apply modes from the provided mode selection overrides (precedence over project configuration)
|
# update active modes and active tools (considering the active project, if any)
|
||||||
if modes is not None:
|
self._update_active_modes_and_tools()
|
||||||
self._active_modes.apply(modes)
|
|
||||||
|
|
||||||
# determine the subset of active tools (depending on active modes and the active project)
|
|
||||||
self._active_tools: AvailableTools = self._exposed_tools
|
|
||||||
self._update_active_tools()
|
|
||||||
|
|
||||||
# start the dashboard (web frontend), registering its log handler
|
# start the dashboard (web frontend), registering its log handler
|
||||||
# should be the last thing to happen in the initialization since the dashboard
|
# should be the last thing to happen in the initialization since the dashboard
|
||||||
@@ -529,7 +523,7 @@ class SerenaAgent:
|
|||||||
:param mode_names: List of mode names or paths to use
|
:param mode_names: List of mode names or paths to use
|
||||||
"""
|
"""
|
||||||
self._active_modes.apply(ModeSelectionDefinition(default_modes=mode_names))
|
self._active_modes.apply(ModeSelectionDefinition(default_modes=mode_names))
|
||||||
self._update_active_tools()
|
self._update_active_modes_and_tools()
|
||||||
|
|
||||||
log.info(f"Set modes to {[mode.name for mode in self.get_active_modes()]}")
|
log.info(f"Set modes to {[mode.name for mode in self.get_active_modes()]}")
|
||||||
|
|
||||||
@@ -561,12 +555,20 @@ class SerenaAgent:
|
|||||||
log.info("System prompt:\n%s", system_prompt)
|
log.info("System prompt:\n%s", system_prompt)
|
||||||
return system_prompt
|
return system_prompt
|
||||||
|
|
||||||
def _update_active_tools(self) -> None:
|
def _update_active_modes_and_tools(self) -> None:
|
||||||
"""
|
"""
|
||||||
Update the active tools based on enabled modes and the active project.
|
Updates the active modes and, subsequently, the active tools based on the modes and the active project.
|
||||||
The base tool set already takes the Serena configuration and the context into account
|
The base tool set already takes the Serena configuration and the context into account
|
||||||
(as well as any internal modes that are not handled dynamically, such as JetBrains mode).
|
(as well as any internal modes that are not handled dynamically, such as JetBrains mode).
|
||||||
"""
|
"""
|
||||||
|
# determine active modes from serena config, active project, and mode overrides
|
||||||
|
self._active_modes = ActiveModes()
|
||||||
|
self._active_modes.apply(self.serena_config)
|
||||||
|
if self._active_project:
|
||||||
|
self._active_modes.apply(self._active_project.project_config)
|
||||||
|
if self._mode_overrides:
|
||||||
|
self._active_modes.apply(self._mode_overrides)
|
||||||
|
|
||||||
# apply modes
|
# apply modes
|
||||||
tool_set = self._base_tool_set.apply(*self._active_modes.get_modes())
|
tool_set = self._base_tool_set.apply(*self._active_modes.get_modes())
|
||||||
|
|
||||||
@@ -615,15 +617,12 @@ class SerenaAgent:
|
|||||||
"""
|
"""
|
||||||
return self.serena_config.language_backend == LanguageBackend.LSP
|
return self.serena_config.language_backend == LanguageBackend.LSP
|
||||||
|
|
||||||
def _activate_project(self, project: Project, update_tools: bool = True) -> None:
|
def _activate_project(self, project: Project, update_modes_and_tools: bool = True) -> None:
|
||||||
log.info(f"Activating {project.project_name} at {project.project_root}")
|
log.info(f"Activating {project.project_name} at {project.project_root}")
|
||||||
self._active_project = project
|
self._active_project = project
|
||||||
|
|
||||||
# update the active modes based on the project configuration
|
if update_modes_and_tools:
|
||||||
self._active_modes.apply(project.project_config)
|
self._update_active_modes_and_tools()
|
||||||
|
|
||||||
if update_tools:
|
|
||||||
self._update_active_tools()
|
|
||||||
|
|
||||||
def init_language_server_manager() -> None:
|
def init_language_server_manager() -> None:
|
||||||
# start the language server
|
# start the language server
|
||||||
@@ -654,7 +653,7 @@ class SerenaAgent:
|
|||||||
log.info(f"Added new project {project_instance.project_name} for path {project_instance.project_root}")
|
log.info(f"Added new project {project_instance.project_name} for path {project_instance.project_root}")
|
||||||
return project_instance
|
return project_instance
|
||||||
|
|
||||||
def activate_project_from_path_or_name(self, project_root_or_name: str, update_tools: bool = True) -> Project:
|
def activate_project_from_path_or_name(self, project_root_or_name: str, update_modes_and_tools: bool = True) -> Project:
|
||||||
"""
|
"""
|
||||||
Activate a project from a path or a name.
|
Activate a project from a path or a name.
|
||||||
If the project was already registered, it will just be activated.
|
If the project was already registered, it will just be activated.
|
||||||
@@ -670,7 +669,7 @@ class SerenaAgent:
|
|||||||
f"Project '{project_root_or_name}' not found: Not a valid project name or directory. "
|
f"Project '{project_root_or_name}' not found: Not a valid project name or directory. "
|
||||||
f"Existing project names: {self.serena_config.project_names}"
|
f"Existing project names: {self.serena_config.project_names}"
|
||||||
)
|
)
|
||||||
self._activate_project(project_instance, update_tools=update_tools)
|
self._activate_project(project_instance, update_modes_and_tools=update_modes_and_tools)
|
||||||
return project_instance
|
return project_instance
|
||||||
|
|
||||||
def get_active_tool_names(self) -> list[str]:
|
def get_active_tool_names(self) -> list[str]:
|
||||||
|
|||||||
Reference in new issue
Block a user