mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-12 22:14:54 +00:00
Prevent project activation message from being provided more than once
Fixes #1372
This commit is contained in:
1 parent
9bc815b3e1
commit
269fe26d08
2 files changed
+40
-18
No files matched your search
@@ -9,6 +9,8 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
- Fix: Duplicate comments in re-saved YAML configuration files #1285
|
||||
- Fix: Prompts of dynamically activated modes (upon project activation) were not necessary passed to the LLM (only in the system prompt via
|
||||
`initial_instructions`). Now they are passed directly in the activation message (and excluded from a subsequent `initial_instructions` call).
|
||||
- Fix: Project activation message was provided more than once for case of dynamic project activation followed
|
||||
by `initial_instructions` #1372
|
||||
|
||||
* JetBrains:
|
||||
- `Move` and `SafeDelete` tools: transform empty string to None (counteracts client errors)
|
||||
|
||||
+38
-18
@@ -234,26 +234,29 @@ class ActiveModes:
|
||||
return [self.get_mode_instance(mode_name) for mode_name in self._configured_base_modes or []]
|
||||
|
||||
|
||||
class DynamicModeProvisionStatus:
|
||||
class ProjectPromptProvisionStatus:
|
||||
"""
|
||||
Manages the provision of modes that have been newly activated (by dynamic project activation)
|
||||
Manages the status of the provision of project-specific prompts
|
||||
"""
|
||||
|
||||
def __init__(self, newly_activated_mode_names: set[str]):
|
||||
def __init__(self, newly_activated_mode_names: set[str] | None = None):
|
||||
"""
|
||||
:param newly_activated_mode_names: list of mode names that have been newly activated (by dynamic project activation)
|
||||
and for which prompts must still be provided (either in the system prompt or the activation prompt)
|
||||
and for which prompts must still be provided (either in the system prompt or via the activation message)
|
||||
"""
|
||||
if newly_activated_mode_names is None:
|
||||
newly_activated_mode_names = set()
|
||||
self._newly_activated_mode_names: set[str] = newly_activated_mode_names
|
||||
self._prompts_provided = False
|
||||
self._mode_prompts_provided = False
|
||||
self._project_activation_message_provided = False
|
||||
|
||||
def is_prompt_already_provided(self, mode_name: str) -> bool:
|
||||
def is_mode_prompt_already_provided(self, mode_name: str) -> bool:
|
||||
"""
|
||||
:param mode_name: the mode name
|
||||
:return: whether the mode name was already provided (in a project-specific activation message) and therefore
|
||||
should not be included again
|
||||
should not be included again (in the Serena instructions manual)
|
||||
"""
|
||||
if not self._prompts_provided:
|
||||
if not self._mode_prompts_provided:
|
||||
return False
|
||||
return mode_name in self._newly_activated_mode_names
|
||||
|
||||
@@ -263,7 +266,7 @@ class DynamicModeProvisionStatus:
|
||||
(in dynamic project activation message).
|
||||
"""
|
||||
result = []
|
||||
if not self._prompts_provided:
|
||||
if not self._mode_prompts_provided:
|
||||
for mode_name in self._newly_activated_mode_names:
|
||||
mode = ActiveModes.get_mode_instance(mode_name)
|
||||
if mode.has_prompt():
|
||||
@@ -274,7 +277,19 @@ class DynamicModeProvisionStatus:
|
||||
"""
|
||||
Marks the prompts for all newly activated modes as provided, so that they will not be included in the project activation message.
|
||||
"""
|
||||
self._prompts_provided = True
|
||||
self._mode_prompts_provided = True
|
||||
|
||||
def mark_project_activation_message_as_provided(self) -> None:
|
||||
"""
|
||||
Marks the project activation message as provided, so that it will not be included again in case of multiple activations of the same project.
|
||||
"""
|
||||
self._project_activation_message_provided = True
|
||||
|
||||
def is_project_activation_message_already_provided(self) -> bool:
|
||||
"""
|
||||
:return: whether the project activation message was already provided and therefore should not be included again
|
||||
"""
|
||||
return self._project_activation_message_provided
|
||||
|
||||
|
||||
class SerenaAgent:
|
||||
@@ -302,7 +317,7 @@ class SerenaAgent:
|
||||
self._active_project: Project | None = None
|
||||
self._gui_log_viewer: Optional["GuiLogViewer"] = None
|
||||
self._dashboard_viewer_process: multiprocessing.Process | None = None
|
||||
self._dynamic_mode_provision_status = DynamicModeProvisionStatus(set())
|
||||
self._project_prompt_status = ProjectPromptProvisionStatus()
|
||||
self._mode_overrides = modes
|
||||
self.version = serena_version()
|
||||
|
||||
@@ -735,9 +750,9 @@ class SerenaAgent:
|
||||
relevant_modes = []
|
||||
for mode in self.get_active_modes():
|
||||
if mode.has_prompt():
|
||||
if not self._dynamic_mode_provision_status.is_prompt_already_provided(mode.name):
|
||||
if not self._project_prompt_status.is_mode_prompt_already_provided(mode.name):
|
||||
relevant_modes.append(mode)
|
||||
self._dynamic_mode_provision_status.mark_mode_prompts_as_provided()
|
||||
self._project_prompt_status.mark_mode_prompts_as_provided()
|
||||
|
||||
system_prompt = self.prompt_factory.create_system_prompt(
|
||||
context_system_prompt=self._format_prompt(self._context.prompt),
|
||||
@@ -747,8 +762,8 @@ class SerenaAgent:
|
||||
global_memories_list=global_memories_str,
|
||||
)
|
||||
|
||||
# If a project is active at startup, append its activation message
|
||||
if self._active_project is not None:
|
||||
# provide the project activation message if it hasn't yet been provided
|
||||
if self._active_project is not None and not self._project_prompt_status.is_project_activation_message_already_provided():
|
||||
system_prompt += "\n\n" + self.get_project_activation_message()
|
||||
|
||||
log.info("System prompt:\n%s", system_prompt)
|
||||
@@ -780,16 +795,18 @@ class SerenaAgent:
|
||||
)
|
||||
|
||||
# add prompts for modes that were dynamically activated by the project
|
||||
modes_with_prompts = self._dynamic_mode_provision_status.get_modes_with_prompts_to_be_provided_for_project_activation()
|
||||
modes_with_prompts = self._project_prompt_status.get_modes_with_prompts_to_be_provided_for_project_activation()
|
||||
if modes_with_prompts:
|
||||
msg += "\nNewly applicable mode instructions:"
|
||||
for mode in modes_with_prompts:
|
||||
msg += f"\n{mode.prompt}"
|
||||
self._dynamic_mode_provision_status.mark_mode_prompts_as_provided()
|
||||
self._project_prompt_status.mark_mode_prompts_as_provided()
|
||||
|
||||
if proj.project_config.initial_prompt:
|
||||
msg += f"\nProject-specific instructions:\n {proj.project_config.initial_prompt}"
|
||||
|
||||
self._project_prompt_status.mark_project_activation_message_as_provided()
|
||||
|
||||
return msg
|
||||
|
||||
def _update_active_modes(self, log_message: bool = True) -> None:
|
||||
@@ -900,7 +917,10 @@ class SerenaAgent:
|
||||
active_mode_names_before = set(self._active_modes.get_mode_names())
|
||||
self._update_active_modes()
|
||||
newly_activated_mode_names = set(self._active_modes.get_mode_names()) - active_mode_names_before
|
||||
self._dynamic_mode_provision_status = DynamicModeProvisionStatus(newly_activated_mode_names=newly_activated_mode_names)
|
||||
else:
|
||||
newly_activated_mode_names = None
|
||||
|
||||
self._project_prompt_status = ProjectPromptProvisionStatus(newly_activated_mode_names=newly_activated_mode_names)
|
||||
|
||||
if update_active_tools:
|
||||
self._update_active_tools()
|
||||
|
||||
Reference in new issue
Block a user