@simbimbo/memory-ocmemog 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/LICENSE +21 -0
- package/README.md +223 -0
- package/brain/__init__.py +1 -0
- package/brain/runtime/__init__.py +13 -0
- package/brain/runtime/config.py +21 -0
- package/brain/runtime/inference.py +83 -0
- package/brain/runtime/instrumentation.py +17 -0
- package/brain/runtime/memory/__init__.py +13 -0
- package/brain/runtime/memory/api.py +152 -0
- package/brain/runtime/memory/artifacts.py +33 -0
- package/brain/runtime/memory/candidate.py +89 -0
- package/brain/runtime/memory/context_builder.py +87 -0
- package/brain/runtime/memory/conversation_state.py +1825 -0
- package/brain/runtime/memory/distill.py +198 -0
- package/brain/runtime/memory/embedding_engine.py +94 -0
- package/brain/runtime/memory/freshness.py +91 -0
- package/brain/runtime/memory/health.py +42 -0
- package/brain/runtime/memory/integrity.py +170 -0
- package/brain/runtime/memory/interaction_memory.py +57 -0
- package/brain/runtime/memory/memory_consolidation.py +60 -0
- package/brain/runtime/memory/memory_gate.py +38 -0
- package/brain/runtime/memory/memory_graph.py +54 -0
- package/brain/runtime/memory/memory_links.py +109 -0
- package/brain/runtime/memory/memory_salience.py +235 -0
- package/brain/runtime/memory/memory_synthesis.py +33 -0
- package/brain/runtime/memory/memory_taxonomy.py +35 -0
- package/brain/runtime/memory/person_identity.py +83 -0
- package/brain/runtime/memory/person_memory.py +138 -0
- package/brain/runtime/memory/pondering_engine.py +577 -0
- package/brain/runtime/memory/promote.py +237 -0
- package/brain/runtime/memory/provenance.py +356 -0
- package/brain/runtime/memory/reinforcement.py +73 -0
- package/brain/runtime/memory/retrieval.py +153 -0
- package/brain/runtime/memory/semantic_search.py +66 -0
- package/brain/runtime/memory/sentiment_memory.py +67 -0
- package/brain/runtime/memory/store.py +400 -0
- package/brain/runtime/memory/tool_catalog.py +68 -0
- package/brain/runtime/memory/unresolved_state.py +93 -0
- package/brain/runtime/memory/vector_index.py +270 -0
- package/brain/runtime/model_roles.py +11 -0
- package/brain/runtime/model_router.py +22 -0
- package/brain/runtime/providers.py +59 -0
- package/brain/runtime/security/__init__.py +3 -0
- package/brain/runtime/security/redaction.py +14 -0
- package/brain/runtime/state_store.py +25 -0
- package/brain/runtime/storage_paths.py +41 -0
- package/docs/architecture/memory.md +118 -0
- package/docs/release-checklist.md +34 -0
- package/docs/reports/ocmemog-code-audit-2026-03-14.md +155 -0
- package/docs/usage.md +223 -0
- package/index.ts +726 -0
- package/ocmemog/__init__.py +1 -0
- package/ocmemog/sidecar/__init__.py +1 -0
- package/ocmemog/sidecar/app.py +1068 -0
- package/ocmemog/sidecar/compat.py +74 -0
- package/ocmemog/sidecar/transcript_watcher.py +425 -0
- package/openclaw.plugin.json +18 -0
- package/package.json +60 -0
- package/scripts/install-ocmemog.sh +277 -0
- package/scripts/launchagents/com.openclaw.ocmemog.guard.plist +22 -0
- package/scripts/launchagents/com.openclaw.ocmemog.ponder.plist +22 -0
- package/scripts/launchagents/com.openclaw.ocmemog.sidecar.plist +27 -0
- package/scripts/ocmemog-context.sh +15 -0
- package/scripts/ocmemog-continuity-benchmark.py +178 -0
- package/scripts/ocmemog-demo.py +122 -0
- package/scripts/ocmemog-failover-test.sh +17 -0
- package/scripts/ocmemog-guard.sh +11 -0
- package/scripts/ocmemog-install.sh +93 -0
- package/scripts/ocmemog-load-test.py +106 -0
- package/scripts/ocmemog-ponder.sh +30 -0
- package/scripts/ocmemog-recall-test.py +58 -0
- package/scripts/ocmemog-reindex-vectors.py +14 -0
- package/scripts/ocmemog-reliability-soak.py +177 -0
- package/scripts/ocmemog-sidecar.sh +46 -0
- package/scripts/ocmemog-soak-report.py +58 -0
- package/scripts/ocmemog-soak-test.py +44 -0
- package/scripts/ocmemog-test-rig.py +345 -0
- package/scripts/ocmemog-transcript-append.py +45 -0
- package/scripts/ocmemog-transcript-watcher.py +8 -0
- package/scripts/ocmemog-transcript-watcher.sh +7 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import sqlite3
|
|
5
|
+
import time
|
|
6
|
+
from typing import Dict, List
|
|
7
|
+
|
|
8
|
+
from brain.runtime import state_store
|
|
9
|
+
from brain.runtime.instrumentation import emit_event
|
|
10
|
+
|
|
11
|
+
LOGFILE = state_store.reports_dir() / "brain_memory.log.jsonl"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _connect() -> sqlite3.Connection:
|
|
15
|
+
path = state_store.data_dir() / "person_memory.db"
|
|
16
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
17
|
+
conn = sqlite3.connect(str(path))
|
|
18
|
+
conn.row_factory = sqlite3.Row
|
|
19
|
+
conn.execute(
|
|
20
|
+
"""
|
|
21
|
+
CREATE TABLE IF NOT EXISTS person_memory (
|
|
22
|
+
person_id TEXT PRIMARY KEY,
|
|
23
|
+
display_name TEXT,
|
|
24
|
+
aliases_json TEXT,
|
|
25
|
+
email_addresses_json TEXT,
|
|
26
|
+
phone_numbers_json TEXT,
|
|
27
|
+
interaction_count INTEGER DEFAULT 0,
|
|
28
|
+
trust_score REAL DEFAULT 0.5,
|
|
29
|
+
trust_level TEXT DEFAULT 'operator',
|
|
30
|
+
expertise_tags_json TEXT,
|
|
31
|
+
communication_style_json TEXT,
|
|
32
|
+
last_seen TEXT,
|
|
33
|
+
relationship_type TEXT,
|
|
34
|
+
notes_json TEXT,
|
|
35
|
+
created_at TEXT
|
|
36
|
+
)
|
|
37
|
+
"""
|
|
38
|
+
)
|
|
39
|
+
_ensure_columns(conn)
|
|
40
|
+
return conn
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _ensure_columns(conn: sqlite3.Connection) -> None:
|
|
44
|
+
existing = {row[1] for row in conn.execute("PRAGMA table_info(person_memory)")}
|
|
45
|
+
columns = {
|
|
46
|
+
"trust_level": "ALTER TABLE person_memory ADD COLUMN trust_level TEXT DEFAULT 'operator'",
|
|
47
|
+
"expertise_tags_json": "ALTER TABLE person_memory ADD COLUMN expertise_tags_json TEXT",
|
|
48
|
+
"communication_style_json": "ALTER TABLE person_memory ADD COLUMN communication_style_json TEXT",
|
|
49
|
+
"relationship_type": "ALTER TABLE person_memory ADD COLUMN relationship_type TEXT",
|
|
50
|
+
"notes_json": "ALTER TABLE person_memory ADD COLUMN notes_json TEXT",
|
|
51
|
+
"created_at": "ALTER TABLE person_memory ADD COLUMN created_at TEXT",
|
|
52
|
+
}
|
|
53
|
+
for name, ddl in columns.items():
|
|
54
|
+
if name not in existing:
|
|
55
|
+
conn.execute(ddl)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def create_person(person_id: str, display_name: str = "") -> Dict[str, object]:
|
|
59
|
+
conn = _connect()
|
|
60
|
+
conn.execute(
|
|
61
|
+
"""
|
|
62
|
+
INSERT OR IGNORE INTO person_memory (
|
|
63
|
+
person_id, display_name, aliases_json, email_addresses_json, phone_numbers_json,
|
|
64
|
+
interaction_count, trust_score, trust_level, expertise_tags_json, communication_style_json,
|
|
65
|
+
last_seen, relationship_type, notes_json
|
|
66
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
67
|
+
""",
|
|
68
|
+
(
|
|
69
|
+
person_id,
|
|
70
|
+
display_name,
|
|
71
|
+
json.dumps([]),
|
|
72
|
+
json.dumps([]),
|
|
73
|
+
json.dumps([]),
|
|
74
|
+
0,
|
|
75
|
+
0.5,
|
|
76
|
+
"operator",
|
|
77
|
+
json.dumps([]),
|
|
78
|
+
json.dumps({}),
|
|
79
|
+
time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
80
|
+
"",
|
|
81
|
+
json.dumps([]),
|
|
82
|
+
time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
conn.commit()
|
|
86
|
+
conn.close()
|
|
87
|
+
emit_event(LOGFILE, "brain_person_memory_created", status="ok", person_id=person_id)
|
|
88
|
+
return get_person(person_id) or {}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_person(person_id: str) -> Dict[str, object] | None:
|
|
92
|
+
conn = _connect()
|
|
93
|
+
row = conn.execute("SELECT * FROM person_memory WHERE person_id=?", (person_id,)).fetchone()
|
|
94
|
+
conn.close()
|
|
95
|
+
return dict(row) if row else None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def update_person(person_id: str, updates: Dict[str, object]) -> None:
|
|
99
|
+
conn = _connect()
|
|
100
|
+
fields = []
|
|
101
|
+
values = []
|
|
102
|
+
for key, value in updates.items():
|
|
103
|
+
fields.append(f"{key}=?")
|
|
104
|
+
values.append(value)
|
|
105
|
+
if not fields:
|
|
106
|
+
conn.close()
|
|
107
|
+
return
|
|
108
|
+
values.append(person_id)
|
|
109
|
+
conn.execute(f"UPDATE person_memory SET {', '.join(fields)} WHERE person_id=?", values)
|
|
110
|
+
conn.commit()
|
|
111
|
+
conn.close()
|
|
112
|
+
emit_event(LOGFILE, "brain_person_memory_updated", status="ok", person_id=person_id)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _find_by_json(field: str, value: str) -> Dict[str, object] | None:
|
|
116
|
+
conn = _connect()
|
|
117
|
+
rows = conn.execute("SELECT * FROM person_memory").fetchall()
|
|
118
|
+
conn.close()
|
|
119
|
+
for row in rows:
|
|
120
|
+
payload = json.loads(row[field] or "[]")
|
|
121
|
+
if value in payload:
|
|
122
|
+
return dict(row)
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def find_person_by_email(email: str) -> Dict[str, object] | None:
|
|
127
|
+
return _find_by_json("email_addresses_json", email)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def find_person_by_phone(phone: str) -> Dict[str, object] | None:
|
|
131
|
+
return _find_by_json("phone_numbers_json", phone)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def list_people(limit: int = 50) -> List[Dict[str, object]]:
|
|
135
|
+
conn = _connect()
|
|
136
|
+
rows = conn.execute("SELECT * FROM person_memory ORDER BY last_seen DESC LIMIT ?", (limit,)).fetchall()
|
|
137
|
+
conn.close()
|
|
138
|
+
return [dict(row) for row in rows]
|