rename agent project memory
This commit is contained in:
@@ -615,8 +615,8 @@ def agent_loop(
|
|||||||
"take, only ask when it is strictly necessary to proceed.\n\n"
|
"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 "
|
"- 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 "
|
"both project and user memory. Project memory is for durable lessons, environment "
|
||||||
"facts, and conventions; user memory is for stable preferences and expectations. "
|
"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 "
|
"Append only concise, useful facts that are likely to hold in future sessions. Never "
|
||||||
"store secrets, credentials, or transient task details.\n"
|
"store secrets, credentials, or transient task details.\n"
|
||||||
"- Past sessions (list_sessions / search_sessions / read_session): use these to find "
|
"- Past sessions (list_sessions / search_sessions / read_session): use these to find "
|
||||||
@@ -938,7 +938,7 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--memory-dir",
|
"--memory-dir",
|
||||||
default="~/.agent-harness/memory",
|
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(
|
parser.add_argument(
|
||||||
"--list-sessions",
|
"--list-sessions",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class MemoryStore:
|
|||||||
self.sessions_dir = self.root / "sessions"
|
self.sessions_dir = self.root / "sessions"
|
||||||
self.root.mkdir(parents=True, exist_ok=True)
|
self.root.mkdir(parents=True, exist_ok=True)
|
||||||
self.sessions_dir.mkdir(exist_ok=True)
|
self.sessions_dir.mkdir(exist_ok=True)
|
||||||
|
self._migrate_personal_notes()
|
||||||
|
|
||||||
def read_notes(self, scope: str) -> str:
|
def read_notes(self, scope: str) -> str:
|
||||||
path = self._notes_path(scope)
|
path = self._notes_path(scope)
|
||||||
@@ -100,10 +101,17 @@ class MemoryStore:
|
|||||||
return matches
|
return matches
|
||||||
|
|
||||||
def _notes_path(self, scope: str) -> Path:
|
def _notes_path(self, scope: str) -> Path:
|
||||||
if scope not in {"personal", "user"}:
|
if scope not in {"project", "user"}:
|
||||||
raise ValueError("scope must be 'personal' or 'user'")
|
raise ValueError("scope must be 'project' or 'user'")
|
||||||
return self.root / f"{scope}.md"
|
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:
|
def _session_path(self, session_id: str) -> Path:
|
||||||
if not re.fullmatch(r"[A-Za-z0-9_-]+", session_id):
|
if not re.fullmatch(r"[A-Za-z0-9_-]+", session_id):
|
||||||
raise ValueError("session id contains invalid characters")
|
raise ValueError("session id contains invalid characters")
|
||||||
|
|||||||
@@ -12,13 +12,21 @@ class MemoryStoreTests(unittest.TestCase):
|
|||||||
self.root = Path(tempfile.mkdtemp())
|
self.root = Path(tempfile.mkdtemp())
|
||||||
self.store = MemoryStore(self.root)
|
self.store = MemoryStore(self.root)
|
||||||
|
|
||||||
def test_persists_personal_and_user_notes(self):
|
def test_persists_project_and_user_notes(self):
|
||||||
self.store.append_notes("personal", "Use uv for Python commands.")
|
self.store.append_notes("project", "Use uv for Python commands.")
|
||||||
self.store.append_notes("user", "Prefers concise answers.")
|
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"))
|
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):
|
def test_lists_and_searches_saved_sessions(self):
|
||||||
self.store.create_session("session-one", [
|
self.store.create_session("session-one", [
|
||||||
{"role": "system", "content": "system"},
|
{"role": "system", "content": "system"},
|
||||||
|
|||||||
@@ -273,16 +273,16 @@ def get_tool_schemas():
|
|||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "read_memory",
|
"name": "read_memory",
|
||||||
"description": "Read durable notes. scope 'personal' contains the agent's lessons and environment facts; scope 'user' contains user preferences.",
|
"description": "Read durable notes. scope 'project' contains project facts and conventions; scope 'user' contains user preferences.",
|
||||||
"parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["personal", "user"]}}, "required": ["scope"]},
|
"parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["project", "user"]}}, "required": ["scope"]},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "append_memory",
|
"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.",
|
"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": ["personal", "user"]}, "content": {"type": "string"}}, "required": ["scope", "content"]},
|
"parameters": {"type": "object", "properties": {"scope": {"type": "string", "enum": ["project", "user"]}, "content": {"type": "string"}}, "required": ["scope", "content"]},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user