diff --git a/agent-memory/agent.py b/agent-memory/agent.py index 33e7afc..197b4ac 100644 --- a/agent-memory/agent.py +++ b/agent-memory/agent.py @@ -615,8 +615,8 @@ def agent_loop( "take, only ask when it is strictly necessary to proceed.\n\n" "- Long-term memory (read_memory / append_memory): at the start of a session, read " - "both personal and user memory. Personal memory is for durable lessons, environment " - "facts, and conventions; user memory is for stable preferences and expectations. " + "both project and user memory. Project memory is for durable lessons, environment " + "facts, and conventions; user memory is for stable preferences and expectations. " "Append only concise, useful facts that are likely to hold in future sessions. Never " "store secrets, credentials, or transient task details.\n" "- Past sessions (list_sessions / search_sessions / read_session): use these to find " @@ -938,7 +938,7 @@ if __name__ == "__main__": parser.add_argument( "--memory-dir", default="~/.agent-harness/memory", - help="Directory for durable personal/user memory and saved sessions.", + help="Directory for durable project/user memory and saved sessions.", ) parser.add_argument( "--list-sessions", diff --git a/agent-memory/memory.py b/agent-memory/memory.py index ae1e56b..ded2277 100644 --- a/agent-memory/memory.py +++ b/agent-memory/memory.py @@ -18,6 +18,7 @@ class MemoryStore: self.sessions_dir = self.root / "sessions" self.root.mkdir(parents=True, exist_ok=True) self.sessions_dir.mkdir(exist_ok=True) + self._migrate_personal_notes() def read_notes(self, scope: str) -> str: path = self._notes_path(scope) @@ -100,10 +101,17 @@ class MemoryStore: return matches def _notes_path(self, scope: str) -> Path: - if scope not in {"personal", "user"}: - raise ValueError("scope must be 'personal' or 'user'") + if scope not in {"project", "user"}: + raise ValueError("scope must be 'project' or 'user'") return self.root / f"{scope}.md" + def _migrate_personal_notes(self) -> None: + """Rename the old personal scope without discarding existing notes.""" + old_path = self.root / "personal.md" + project_path = self.root / "project.md" + if old_path.exists() and not project_path.exists(): + os.replace(old_path, project_path) + def _session_path(self, session_id: str) -> Path: if not re.fullmatch(r"[A-Za-z0-9_-]+", session_id): raise ValueError("session id contains invalid characters") diff --git a/agent-memory/test_memory.py b/agent-memory/test_memory.py index 2e412b1..70223e6 100644 --- a/agent-memory/test_memory.py +++ b/agent-memory/test_memory.py @@ -12,13 +12,21 @@ class MemoryStoreTests(unittest.TestCase): self.root = Path(tempfile.mkdtemp()) self.store = MemoryStore(self.root) - def test_persists_personal_and_user_notes(self): - self.store.append_notes("personal", "Use uv for Python commands.") + def test_persists_project_and_user_notes(self): + self.store.append_notes("project", "Use uv for Python commands.") self.store.append_notes("user", "Prefers concise answers.") - self.assertIn("Use uv", self.store.read_notes("personal")) + self.assertIn("Use uv", self.store.read_notes("project")) self.assertIn("concise", self.store.read_notes("user")) + def test_migrates_existing_personal_notes_to_project(self): + (self.root / "personal.md").write_text("Use uv for Python commands.\n") + + migrated = MemoryStore(self.root) + + self.assertFalse((self.root / "personal.md").exists()) + self.assertIn("Use uv", migrated.read_notes("project")) + def test_lists_and_searches_saved_sessions(self): self.store.create_session("session-one", [ {"role": "system", "content": "system"}, diff --git a/agent-memory/tools/registry.py b/agent-memory/tools/registry.py index c97af58..c7216e7 100644 --- a/agent-memory/tools/registry.py +++ b/agent-memory/tools/registry.py @@ -273,16 +273,16 @@ def get_tool_schemas(): "type": "function", "function": { "name": "read_memory", - "description": "Read durable notes. scope 'personal' contains the agent's lessons and environment facts; scope 'user' contains user preferences.", - "parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["personal", "user"]}}, "required": ["scope"]}, + "description": "Read durable notes. scope 'project' contains project facts and conventions; scope 'user' contains user preferences.", + "parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["project", "user"]}}, "required": ["scope"]}, }, }, { "type": "function", "function": { "name": "append_memory", - "description": "Append a concise, durable fact to personal or user memory. Only save stable facts useful in future sessions; never save secrets.", - "parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["personal", "user"]}, "content": {"type": "string"}}, "required": ["scope", "content"]}, + "description": "Append a concise, durable fact to project or user memory. Only save stable facts useful in future sessions; never save secrets.", + "parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["project", "user"]}, "content": {"type": "string"}}, "required": ["scope", "content"]}, }, }, {