mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 04:15:11 +00:00
Feature: added memory maintenance memory as part of onboarding
Rephrased onboarding prompt to adjust to the recommended memory management
This commit is contained in:
1 parent
18874913da
commit
bc9d4e050c
5 files changed
+134
-51
No files matched your search
@@ -14,39 +14,31 @@ class PromptFactory(PromptFactoryBase):
|
||||
"""
|
||||
|
||||
def get_info_jet_brains_debug_repl_template_string(self) -> str:
|
||||
return self.get_prompt_template_string("info_jet_brains_debug_repl")
|
||||
|
||||
return self.get_prompt_template_string('info_jet_brains_debug_repl')
|
||||
|
||||
def create_info_jet_brains_debug_repl(self) -> str:
|
||||
return self._render_prompt("info_jet_brains_debug_repl", locals())
|
||||
return self._render_prompt('info_jet_brains_debug_repl', locals())
|
||||
|
||||
def get_onboarding_prompt_template_string(self) -> str:
|
||||
return self.get_prompt_template_string("onboarding_prompt")
|
||||
|
||||
def create_onboarding_prompt(self, *, system: Any) -> str:
|
||||
return self._render_prompt("onboarding_prompt", locals())
|
||||
return self.get_prompt_template_string('onboarding_prompt')
|
||||
|
||||
def create_onboarding_prompt(self, *, memory_maintenance_name: Any, system: Any) -> str:
|
||||
return self._render_prompt('onboarding_prompt', locals())
|
||||
|
||||
def get_connection_prompt_template_string(self) -> str:
|
||||
return self.get_prompt_template_string("connection_prompt")
|
||||
|
||||
return self.get_prompt_template_string('connection_prompt')
|
||||
|
||||
def create_connection_prompt(self) -> str:
|
||||
return self._render_prompt("connection_prompt", locals())
|
||||
return self._render_prompt('connection_prompt', locals())
|
||||
|
||||
def get_system_prompt_template_string(self) -> str:
|
||||
return self.get_prompt_template_string("system_prompt")
|
||||
|
||||
def create_system_prompt(
|
||||
self,
|
||||
*,
|
||||
available_markers: Any,
|
||||
available_tools: Any,
|
||||
context_system_prompt: Any,
|
||||
global_memories_list: Any,
|
||||
mode_system_prompts: Any,
|
||||
) -> str:
|
||||
return self._render_prompt("system_prompt", locals())
|
||||
return self.get_prompt_template_string('system_prompt')
|
||||
|
||||
def create_system_prompt(self, *, available_markers: Any, available_tools: Any, context_system_prompt: Any, global_memories_list: Any, mode_system_prompts: Any) -> str:
|
||||
return self._render_prompt('system_prompt', locals())
|
||||
|
||||
def get_cc_system_prompt_override_template_string(self) -> str:
|
||||
return self.get_prompt_template_string("cc_system_prompt_override")
|
||||
|
||||
return self.get_prompt_template_string('cc_system_prompt_override')
|
||||
|
||||
def create_cc_system_prompt_override(self) -> str:
|
||||
return self._render_prompt("cc_system_prompt_override", locals())
|
||||
return self._render_prompt('cc_system_prompt_override', locals())
|
||||
@@ -93,6 +93,43 @@ class MemoriesManager:
|
||||
name = cls._prepare_name(name)
|
||||
return cls._MEMORY_REF_PREFIX + name
|
||||
|
||||
MEMORY_MAINTENANCE_NAME: str = "memory_maintenance"
|
||||
_MEMORY_MAINTENANCE_TEMPLATE_PATH: Path = Path(__file__).parent / "resources" / "memory_maintenance.md"
|
||||
|
||||
def ensure_memory_maintenance_memory(self) -> str:
|
||||
"""
|
||||
Ensures a memory describing how memories should be maintained exists for this project,
|
||||
and returns the name to reference it by.
|
||||
|
||||
Precedence:
|
||||
|
||||
1. If a global copy exists at ``global/memory_maintenance``, return that name; no
|
||||
project copy is created (the global version takes precedence).
|
||||
2. Else if a project copy already exists, return its name unchanged.
|
||||
3. Else seed a project copy from the package-shipped template and return that name.
|
||||
|
||||
Existing memory files are never overwritten; users may have customized them. To
|
||||
refresh from the shipped template, delete the existing memory first.
|
||||
|
||||
:return: the bare name to reference the maintenance memory by (without the ``mem:``
|
||||
prefix); either ``"global/memory_maintenance"`` or ``"memory_maintenance"``.
|
||||
:raises FileNotFoundError: if the shipped template is missing on disk.
|
||||
:raises AssertionError: if this manager has no associated project directory.
|
||||
"""
|
||||
global_name = f"{self.GLOBAL_TOPIC}/{self.MEMORY_MAINTENANCE_NAME}"
|
||||
if self.get_memory_file_path(global_name).exists():
|
||||
return global_name
|
||||
if self.get_memory_file_path(self.MEMORY_MAINTENANCE_NAME).exists():
|
||||
return self.MEMORY_MAINTENANCE_NAME
|
||||
|
||||
# seed a project copy from the shipped template
|
||||
template_path = self._MEMORY_MAINTENANCE_TEMPLATE_PATH
|
||||
if not template_path.exists():
|
||||
raise FileNotFoundError(f"Memory maintenance template not found at {template_path}")
|
||||
content = template_path.read_text(encoding=self._encoding)
|
||||
self.save_memory(self.MEMORY_MAINTENANCE_NAME, content, is_tool_context=False)
|
||||
return self.MEMORY_MAINTENANCE_NAME
|
||||
|
||||
def rename_references_to_memory(self, content: str, old_name: str, new_name: str) -> tuple[str, int]:
|
||||
r"""
|
||||
Replaces all occurrences of a memory reference (e.g. ``mem:foo``) in ``content`` with
|
||||
|
||||
@@ -4,33 +4,44 @@
|
||||
prompts:
|
||||
onboarding_prompt: |
|
||||
You are viewing the project for the first time.
|
||||
Your task is to assemble relevant high-level information about the project which
|
||||
will be saved to memory files in the following steps.
|
||||
The information should be sufficient to understand what the project is about,
|
||||
and the most important commands for developing code.
|
||||
Your task is to assemble durable, non-obvious information about the project and write it
|
||||
to memory files that future agents will consult.
|
||||
The project is being developed on the system: {{ system }}.
|
||||
|
||||
You need to identify at least the following information:
|
||||
* the project's purpose
|
||||
* the tech stack used
|
||||
* the code style and conventions used (including naming, type hints, docstrings, etc.)
|
||||
* which commands to run when a task is completed (linting, formatting, testing, etc.)
|
||||
* the rough structure of the codebase
|
||||
* the commands for testing, formatting, and linting
|
||||
* the commands for running the entrypoints of the project
|
||||
* the util commands for the system, like `git`, `ls`, `cd`, `grep`, `find`, etc. Keep in mind that the system is {{ system }},
|
||||
so the commands might be different than on a regular unix system.
|
||||
* whether there are particular guidelines, styles, design patterns, etc. that one should know about
|
||||
**Before writing anything, read `mem:{{ memory_maintenance_name }}`** using the `read_memory` tool.
|
||||
It defines the style, naming, reference, and add/update threshold conventions that every
|
||||
memory in this project must follow. Do not skip this step.
|
||||
|
||||
This list is not exhaustive, you can add more information if you think it is relevant.
|
||||
Target memory layout — use the `write_memory` tool, one call per memory:
|
||||
|
||||
For doing that, you will need to acquire information about the project with the corresponding tools.
|
||||
Read only the necessary files and directories to avoid loading too much data into memory.
|
||||
If you cannot find everything you need from the project itself, you should ask the user for more information.
|
||||
* `mem:core` — top-level routing/source map: a terse index pointing at the focused memories
|
||||
below, plus only those project-wide invariants that don't belong in a focused memory.
|
||||
* `mem:tech_stack` — language(s), framework(s), build tools, package manager, version
|
||||
pins where they matter.
|
||||
* `mem:suggested_commands` — project commands the user will actually run (dev, test, lint,
|
||||
format, run entrypoints) and any system util commands (`git`, `ls`, `grep`, …) whose
|
||||
form differs on {{ system }} from a standard unix shell. Skip generic commands that
|
||||
behave identically across systems.
|
||||
* `mem:conventions` — code style, naming, type hints, docstring conventions, design
|
||||
patterns specific to this codebase.
|
||||
* `mem:task_completion` — exact commands to run when a coding task is considered done
|
||||
(linter, formatter, test runner, type checker, etc.).
|
||||
|
||||
After collecting all the information, you will use the `write_memory` tool (in multiple calls) to save it to various memory files.
|
||||
A particularly important memory file will be the `suggested_commands.md` file, which should contain
|
||||
a list of commands that the user should know about to develop code in this project.
|
||||
Moreover, you should create memory files for the style and conventions and a dedicated memory file for
|
||||
what should be done when a task is completed.
|
||||
**Important**: after done with the onboarding task, remember to call the `write_memory` to save the collected information!
|
||||
If the project has clearly distinct modules (e.g. frontend/backend), create per-module
|
||||
`mem:<module>/core` memories for module-specific routing instead of pushing everything
|
||||
into `mem:core`.
|
||||
|
||||
Acquire information using the available tools. Read only the files needed; do not load
|
||||
entire directory trees. If essential information is missing, ask the user.
|
||||
|
||||
Memory body style (full rules in `mem:{{ memory_maintenance_name }}`): dense agent notes —
|
||||
terse bullets, invariants, paths, commands. No self-referential cues ("Use when…",
|
||||
"Start here…", "Read before…"); routing belongs in `mem:core` upstream, not inside the
|
||||
body it points to. References to other memories use `` `mem:NAME` `` (backticked, with
|
||||
the `mem:` prefix).
|
||||
|
||||
When all memories are written, sanity-check the references by mentioning that the user can run
|
||||
`serena memories check` from the project root.
|
||||
|
||||
**Important**: the onboarding is only complete once you have actually called `write_memory`
|
||||
for each memory above — do not summarize the content in chat and skip writing.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Memory Maintenance
|
||||
|
||||
## Discovery Model
|
||||
|
||||
- Agents start with the full memory name list and should read `mem:core` first as the routing entry point.
|
||||
- All other memory discovery comes from memory names plus routing already read.
|
||||
- Routing is useful only before the target memory is selected. Once a memory is open, target-selection text inside it can no longer help decide to read it.
|
||||
- Therefore, never put self-referential selection cues in a memory body: no "Start here", "Use when", "Use before", "Use after", or "read this when..." openers.
|
||||
Such self-referential cues are an error mode: they are unreachable for selection, duplicate routing that belongs upstream, and drift independently from the actual routing graph.
|
||||
- Add routing only when names are insufficient, ambiguous, or a non-obvious dependency/order matters. Do not add tautological routing such as "frontend debugging -> frontend/debugging".
|
||||
- Routing can live outside core memories when needed, but core memories own most module-level routing because they are read before focused memories in that subfolder.
|
||||
- Top-level/startup memory is `mem:core`; top-level memory in each memory subfolder is `<folder>/core` (for example `mem:frontend/core`).
|
||||
- Memory references must use a mem: prefix inside backticks, e.g. `mem:frontend/core`.
|
||||
|
||||
## Style
|
||||
|
||||
Dense agent notes, not prose docs. Prefer invariants, paths, commands, terse bullets. Avoid obvious context, rationale, and examples unless they prevent likely mistakes. Keep guidance durable and generalizable, not task-local.
|
||||
|
||||
## Add/update threshold
|
||||
|
||||
Add or update memory only for stable, non-obvious project conventions that avoid complex rediscovery.
|
||||
|
||||
Do not add: quick-read/rg facts; generic language/framework knowledge; one-off task notes; volatile line-level details; behavior likely to change soon.
|
||||
|
||||
Operational constants (commands, paths, version pins): phrase as current behavior; before changing the value, update it in the owning memory and run `serena memories check` to catch references that need updating.
|
||||
|
||||
## Graph Ownership
|
||||
|
||||
- Project-level routing: `mem:core`.
|
||||
- Module-level routing/source maps: module core memories.
|
||||
- Focused memories: topic details only; assume relevant routing was read before selection.
|
||||
|
||||
## Maintenance Actions
|
||||
|
||||
- Renamed/removed/split/merged/superseded memory: update all references. Done automatically if handled via Serena's memory rename tool.
|
||||
- Stale paths/namespaces/commands/behavior: update or remove in owning memory. If working with Serena, call `serena memories check` for a report.
|
||||
- Split catch-all memory when sections are commonly needed independently or agents must read unrelated domains to reach needed topic.
|
||||
- Retire/delete memory when owning module/subsystem is removed or replaced; remove all references.
|
||||
- Added/renamed/split/moved/deleted memory: update affected routing only where names are insufficient.
|
||||
- Before finishing: list memories for old names and key new names to catch stale/missing references.
|
||||
@@ -54,7 +54,10 @@ class OnboardingTool(Tool):
|
||||
if not write_memory_tool_available:
|
||||
return "Memory writing tool not activated, skipping onboarding."
|
||||
system = platform.system()
|
||||
return self.prompt_factory.create_onboarding_prompt(system=system)
|
||||
# seed the project-local memory-maintenance memory (or detect a global override) so
|
||||
# the prompt can point the agent at the conventions before it writes anything
|
||||
memory_maintenance_name = self.memories_manager.ensure_memory_maintenance_memory()
|
||||
return self.prompt_factory.create_onboarding_prompt(system=system, memory_maintenance_name=memory_maintenance_name)
|
||||
|
||||
|
||||
class InitialInstructionsTool(Tool, ToolMarkerDoesNotRequireActiveProject):
|
||||
|
||||
Reference in new issue
Block a user