83 lines
2.7 KiB
Python
Executable File
83 lines
2.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# args_json: {"type":"object","required":["title","tags","body"],"properties":{"title":{"type":"string","description":"Short noun phrase"},"tags":{"type":"string","description":"Comma-separated tags"},"body":{"type":"string","description":"The fact to remember"}}}
|
|
# 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**:
|
|
# ```
|
|
# memory_remember(title="...", tags="...", body="...")
|
|
# ```
|
|
# - `title`: short noun phrase
|
|
# - `tags`: 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
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from _lib.args import parse_args
|
|
|
|
args = parse_args()
|
|
title = args.require("title")
|
|
tags_csv = args.require("tags")
|
|
body = args.require("body")
|
|
|
|
mem_dir = os.path.join(os.environ.get("XDG_CONFIG_HOME", 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}")
|