mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-11 12:29:04 +00:00
Merge pull request #1828 from oraios/prompt-tags
This commit is contained in:
3 files changed
+28
-19
No files matched your search
@@ -15,6 +15,8 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
failed `--project-from-cwd` auto-detection (#1773).
|
||||
- ProjectServer: Configure trusted hosts (local hosts only) when listening on localhost
|
||||
- SerenaDashboardTrayManager: Configure trusted hosts (local hosts only)
|
||||
- Enclose sub-prompts in XML-like tags to make scopes explicit
|
||||
- Allow initial project prompts and project-specific newly activated modes to use templating
|
||||
|
||||
* CLI:
|
||||
- Fix: `start-mcp-server` help text for `--project-from-cwd` falsely promised a fallback to the CWD, which was
|
||||
|
||||
+26
-17
@@ -956,14 +956,24 @@ class SerenaAgent:
|
||||
result[tool_class.get_name_from_cls()] = new_tool_class.get_name_from_cls()
|
||||
return result
|
||||
|
||||
def _format_prompt(self, prompt_template: str) -> str:
|
||||
def _format_prompt_tag(self, text: str, tag: str, tag_name_attr: str | None = None) -> str:
|
||||
open_tag = f"<{tag}" + (f' name="{tag_name_attr}"' if tag_name_attr is not None else "") + ">"
|
||||
close_tag = f"</{tag}>"
|
||||
return f"{open_tag}\n{text.strip()}\n{close_tag}"
|
||||
|
||||
def _format_prompt(self, prompt_template: str, tag: str | None = None, tag_name_attr: str | None = None) -> str:
|
||||
template = JinjaTemplate(prompt_template)
|
||||
return template.render(
|
||||
text = template.render(
|
||||
available_tools=self._exposed_tools.tool_names,
|
||||
available_markers=self._exposed_tools.tool_marker_names,
|
||||
tool_names=self._prompt_tool_names_mapping,
|
||||
)
|
||||
|
||||
if tag is not None:
|
||||
text = self._format_prompt_tag(text, tag=tag, tag_name_attr=tag_name_attr)
|
||||
|
||||
return text
|
||||
|
||||
def create_connection_prompt(self) -> str:
|
||||
"""
|
||||
Returns the bootstrap prompt to be sent at MCP connection time.
|
||||
@@ -997,8 +1007,8 @@ class SerenaAgent:
|
||||
self._project_prompt_status.mark_mode_prompts_as_provided(session_id)
|
||||
|
||||
system_prompt = self.prompt_factory.create_system_prompt(
|
||||
context_system_prompt=self._format_prompt(self._context.prompt),
|
||||
mode_system_prompts=[self._format_prompt(mode.prompt) for mode in relevant_modes],
|
||||
context_system_prompt=self._format_prompt(self._context.prompt, tag="context"),
|
||||
mode_system_prompts=[self._format_prompt(mode.prompt, tag="mode", tag_name_attr=mode.name) for mode in relevant_modes],
|
||||
available_tools=available_tools.tool_names,
|
||||
available_markers=available_markers,
|
||||
global_memories_list=global_memories_str,
|
||||
@@ -1007,11 +1017,11 @@ class SerenaAgent:
|
||||
|
||||
# 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(session_id):
|
||||
system_prompt += "\n\n" + self.get_project_activation_message(session_id)
|
||||
system_prompt += "\n\n" + self._format_prompt_tag(self.get_project_activation_message(session_id), tag="active-project")
|
||||
elif self._project_activation_error:
|
||||
system_prompt += f"\n\nNo project is active ({self._project_activation_error})."
|
||||
|
||||
return system_prompt
|
||||
return self._format_prompt_tag(system_prompt, tag="serena")
|
||||
|
||||
def get_project_activation_message(self, session_id: str) -> str:
|
||||
"""
|
||||
@@ -1031,13 +1041,13 @@ class SerenaAgent:
|
||||
|
||||
# provide basic project information (name, location, languages, encoding)
|
||||
if proj.is_newly_created:
|
||||
msg = f"Created and activated a new project with name '{proj.project_name}' at {proj.project_root}. "
|
||||
msg = f"Created and activated a new project with name '{proj.project_name}' at {proj.project_root}.\n"
|
||||
else:
|
||||
msg = f"The project with name '{proj.project_name}' at {proj.project_root} is activated."
|
||||
msg = f"The project with name '{proj.project_name}' at {proj.project_root} is activated.\n"
|
||||
if self._language_backend == LanguageBackend.LSP:
|
||||
languages_str = ", ".join([lang.value for lang in proj.project_config.language_servers])
|
||||
msg += f"\nProgramming languages: {languages_str}."
|
||||
msg += f"File encoding: {proj.project_config.encoding}."
|
||||
language_servers_str = ", ".join([ls.value for ls in proj.project_config.language_servers])
|
||||
msg += f"Active language servers: {language_servers_str}.\n"
|
||||
msg += f"File encoding: {proj.project_config.encoding}.\n"
|
||||
|
||||
# add list of memories (if memories are enabled)
|
||||
include_memories = self._active_tools.contains_tool_class(ReadMemoryTool)
|
||||
@@ -1045,23 +1055,22 @@ class SerenaAgent:
|
||||
project_memories = proj.memory_manager.list_project_memories()
|
||||
if project_memories:
|
||||
msg += (
|
||||
f"\n{json.dumps(project_memories.to_dict())}\n"
|
||||
+ "Use the `read_memory` tool to read these memories later if they are relevant to the task."
|
||||
f"{json.dumps(project_memories.to_dict())}\n"
|
||||
+ f"Use the `{ReadMemoryTool.get_name_from_cls()}` tool to read these memories later if they are relevant to the task.\n"
|
||||
)
|
||||
elif self._active_tools.contains_tool_class(OnboardingTool):
|
||||
msg += "Onboarding has not been performed yet, you should call Serena's `onboarding` tool now to set up project memories."
|
||||
msg += f"Onboarding has not been performed yet. Ask the user whether to perform onboarding via the `{OnboardingTool.get_name_from_cls()}` tool.\n"
|
||||
|
||||
# add prompts for modes that were dynamically activated by the project
|
||||
modes_with_prompts = self._project_prompt_status.get_modes_with_prompts_to_be_provided_for_project_activation(session_id)
|
||||
if modes_with_prompts:
|
||||
msg += "\nNewly applicable mode instructions:"
|
||||
for mode in modes_with_prompts:
|
||||
msg += f"\n{mode.prompt}"
|
||||
msg += self._format_prompt(mode.prompt, tag="mode", tag_name_attr=mode.name) + "\n"
|
||||
self._project_prompt_status.mark_mode_prompts_as_provided(session_id)
|
||||
|
||||
# add project-specific prompt
|
||||
if proj.project_config.initial_prompt:
|
||||
msg += f"\nProject-specific instructions:\n {proj.project_config.initial_prompt}"
|
||||
msg += "\n" + self._format_prompt(proj.project_config.initial_prompt, tag="project-instructions")
|
||||
|
||||
self._project_prompt_status.mark_project_activation_message_as_provided(session_id)
|
||||
|
||||
|
||||
@@ -49,10 +49,8 @@ prompts:
|
||||
The context and modes of operation are described below. These determine how to interact with your user
|
||||
and which kinds of interactions are expected of you.
|
||||
|
||||
Context description:
|
||||
{{ context_system_prompt }}
|
||||
|
||||
Modes descriptions:
|
||||
{% for prompt in mode_system_prompts %}
|
||||
{{ prompt }}
|
||||
{% endfor %}
|
||||
|
||||
Reference in new issue
Block a user