Repository navigation
Expand file tree
/
Copy pathmem.py
More file actions
95 lines (79 loc) · 3.1 KB
/
Copy pathmem.py
File metadata and controls
95 lines (79 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import argparse
import os
import re
import sqlite3
import sys
from datetime import datetime, timezone
from pathlib import Path
SCHEMA = "create virtual table if not exists memories using fts5(category, topic, content, importance unindexed, updated_at unindexed)"
def db_path() -> Path:
return Path(os.environ.get("MEMORY_DB", ".claude/memory.db"))
def connect() -> sqlite3.Connection:
path = db_path()
path.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(path)
conn.execute(SCHEMA)
return conn
def now() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%d")
def fts_query(text: str) -> str:
return " OR ".join(f'"{w}"' for w in re.findall(r"\w+", text))
def show(rows) -> None:
for rowid, category, topic, content, importance, updated in rows:
print(f"#{rowid} [{category}/{topic}] (imp {importance}, {updated}) {content}")
if not rows:
print("no results")
def main() -> None:
sys.stdout.reconfigure(encoding="utf-8")
p = argparse.ArgumentParser(prog="mem")
sub = p.add_subparsers(dest="cmd", required=True)
s = sub.add_parser("search")
s.add_argument("query")
s.add_argument("-n", type=int, default=5)
a = sub.add_parser("add")
a.add_argument("category")
a.add_argument("topic")
a.add_argument("content")
a.add_argument("-i", "--importance", type=int, default=3)
u = sub.add_parser("update")
u.add_argument("id", type=int)
u.add_argument("content")
d = sub.add_parser("delete")
d.add_argument("id", type=int)
sub.add_parser("topics")
args = p.parse_args()
conn = connect()
with conn:
if args.cmd == "search":
q = fts_query(args.query)
rows = conn.execute(
"select rowid, category, topic, content, importance, updated_at from memories "
"where memories match ? order by rank - importance * 0.5 limit ?",
(q, args.n),
).fetchall() if q else []
show(rows)
elif args.cmd == "add":
cur = conn.execute(
"insert into memories values (?, ?, ?, ?, ?)",
(args.category, args.topic, args.content, args.importance, now()),
)
print(f"saved #{cur.lastrowid}")
elif args.cmd == "update":
n = conn.execute(
"update memories set content = ?, updated_at = ? where rowid = ?",
(args.content, now(), args.id),
).rowcount
print(f"updated #{args.id}" if n else "not found")
elif args.cmd == "delete":
n = conn.execute("delete from memories where rowid = ?", (args.id,)).rowcount
print(f"deleted #{args.id}" if n else "not found")
elif args.cmd == "topics":
rows = conn.execute(
"select category, topic, count(*) from memories group by category, topic order by category, topic"
).fetchall()
for category, topic, count in rows:
print(f"{category}/{topic}: {count}")
if not rows:
print("empty")
if __name__ == "__main__":
main()