ollie/tools/memory_remember

82 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
# ollie:prompt
# ## memory_remember
#
# Persist a fact that would otherwise be lost when the session ends.
#
# **Trigger condition**: the user states a preference, constraint, or decision affecting future work; you discover a non-obvious fact about the codebase, system, or environment; a debugging session surfaces a root cause worth keeping; the user explicitly asks you to remember something. Autonomously remember architectural patterns, service relationships, API behaviors, configuration quirks, and other structural knowledge as you encounter it.
#
# **Calling convention**:
# ```
# call_tool: calls=[{tool: "memory_remember", args: ["<title>", "<tags_csv>", "<body>"]}]
# ```
# - `title`: short noun phrase
# - `tags_csv`: comma-separated tags; pick specific and reusable terms
# - `body`: the fact, written so it stands alone without session context
#
# **Returns**: confirmation.
#
# **Constraints**:
# - One memory per distinct fact.
# - Before writing, recall on the same topic to avoid duplicates.
# - Do not store stale facts. If a previously stored fact is wrong, update it with `file_edit`.
# - Never delete a memory without explicit user instruction.
# - **Act autonomously.** Do not ask the user whether to remember something.
# ollie:end
import sys
import os
import re
from datetime import datetime
if len(sys.argv) < 4:
print('{"schema": {"type": "array", "items": [{"name": "title", "type": "string", "description": "Short noun phrase", "required": true}, {"name": "tags_csv", "type": "string", "description": "Comma-separated tags", "required": true}, {"name": "body", "type": "string", "description": "The fact to remember", "required": true}], "examples": [["API endpoint", "api,backend", "The /users endpoint returns..."]]}}')
sys.exit(1)
title = sys.argv[1]
tags_csv = sys.argv[2]
body = sys.argv[3]
mem_dir = os.environ.get("OLLIE_MEMORY_PATH", os.path.expanduser("~/.config/ollie/memory"))
if not os.path.isdir(mem_dir):
os.makedirs(mem_dir, exist_ok=True)
now = datetime.now()
ident = now.strftime("%Y%m%dT%H%M%S")
date = now.strftime("%Y-%m-%d %a %H:%M")
tags = [t.strip() for t in tags_csv.split(",") if t.strip()]
def slugify(s):
s = s.lower()
s = re.sub(r"[^a-z0-9]+", "-", s)
return s.strip("-")
slug = slugify(title)
tag_slug = "-".join(slugify(t) for t in tags)
filename = f"{ident}__{slug}--{tag_slug}.md" if tag_slug else f"{ident}__{slug}.md"
path = os.path.join(mem_dir, filename)
tags_yaml = "[" + ", ".join(f'"{t}"' for t in tags) + "]"
content = f"""---
title: {title}
date: {date}
tags: {tags_yaml}
identifier: {ident}
signature:
---
{body}
"""
try:
with open(path, "w") as f:
f.write(content)
except OSError as e:
print(f"error: failed to write {path}: {e}")
sys.exit(1)
print(f"saved: {filename}")