@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,89 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
import json
|
|
5
|
+
from typing import Dict, Any
|
|
6
|
+
|
|
7
|
+
from brain.runtime.instrumentation import emit_event
|
|
8
|
+
from brain.runtime import state_store
|
|
9
|
+
from brain.runtime.memory import provenance, store
|
|
10
|
+
from brain.runtime.security import redaction
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
LOGFILE = state_store.reports_dir() / "brain_memory.log.jsonl"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_candidate(
|
|
17
|
+
source_event_id: int,
|
|
18
|
+
distilled_summary: str,
|
|
19
|
+
verification_points: list[str],
|
|
20
|
+
confidence_score: float,
|
|
21
|
+
metadata: Dict[str, Any] | None = None,
|
|
22
|
+
) -> Dict[str, Any]:
|
|
23
|
+
summary, redacted = redaction.redact_text(distilled_summary)
|
|
24
|
+
verification_lines = []
|
|
25
|
+
for point in verification_points:
|
|
26
|
+
clean, _ = redaction.redact_text(str(point))
|
|
27
|
+
verification_lines.append(clean)
|
|
28
|
+
|
|
29
|
+
normalized_metadata = provenance.normalize_metadata(metadata, source="candidate")
|
|
30
|
+
|
|
31
|
+
conn = store.connect()
|
|
32
|
+
row = conn.execute(
|
|
33
|
+
"SELECT candidate_id FROM candidates WHERE source_event_id=? AND distilled_summary=?",
|
|
34
|
+
(source_event_id, summary),
|
|
35
|
+
).fetchone()
|
|
36
|
+
if row:
|
|
37
|
+
conn.close()
|
|
38
|
+
emit_event(LOGFILE, "brain_memory_candidate_duplicate", status="ok", source_event_id=source_event_id)
|
|
39
|
+
return {"candidate_id": row[0], "duplicate": True}
|
|
40
|
+
|
|
41
|
+
candidate_id = str(uuid.uuid4())
|
|
42
|
+
verification_status = "verified" if verification_lines else "unverified"
|
|
43
|
+
conn.execute(
|
|
44
|
+
"""
|
|
45
|
+
INSERT INTO candidates (
|
|
46
|
+
candidate_id, source_event_id, distilled_summary, verification_points,
|
|
47
|
+
confidence_score, status, verification_status, metadata_json, schema_version
|
|
48
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
49
|
+
""",
|
|
50
|
+
(
|
|
51
|
+
candidate_id,
|
|
52
|
+
source_event_id,
|
|
53
|
+
summary,
|
|
54
|
+
"\n".join(verification_lines),
|
|
55
|
+
confidence_score,
|
|
56
|
+
"pending",
|
|
57
|
+
verification_status,
|
|
58
|
+
json.dumps(normalized_metadata, ensure_ascii=False),
|
|
59
|
+
store.SCHEMA_VERSION,
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
conn.execute(
|
|
63
|
+
"INSERT INTO memory_events (event_type, source, details_json, schema_version) VALUES (?, ?, ?, ?)",
|
|
64
|
+
(
|
|
65
|
+
"candidate_created",
|
|
66
|
+
str(source_event_id),
|
|
67
|
+
json.dumps({"candidate_id": candidate_id, "redacted": redacted, "verification_status": verification_status}),
|
|
68
|
+
store.SCHEMA_VERSION,
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
conn.commit()
|
|
72
|
+
conn.close()
|
|
73
|
+
emit_event(LOGFILE, "brain_memory_candidate_created", status="ok", source_event_id=source_event_id, redacted=redacted)
|
|
74
|
+
return {"candidate_id": candidate_id, "duplicate": False}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_candidate(candidate_id: str) -> Dict[str, Any] | None:
|
|
78
|
+
conn = store.connect()
|
|
79
|
+
row = conn.execute(
|
|
80
|
+
"""
|
|
81
|
+
SELECT candidate_id, source_event_id, distilled_summary, verification_points,
|
|
82
|
+
confidence_score, status, verification_status, metadata_json
|
|
83
|
+
FROM candidates
|
|
84
|
+
WHERE candidate_id=?
|
|
85
|
+
""",
|
|
86
|
+
(candidate_id,),
|
|
87
|
+
).fetchone()
|
|
88
|
+
conn.close()
|
|
89
|
+
return dict(row) if row else None
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Iterable, List
|
|
4
|
+
|
|
5
|
+
from brain.runtime.instrumentation import emit_event
|
|
6
|
+
from brain.runtime import state_store
|
|
7
|
+
from brain.runtime.memory import retrieval
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def build_context(
|
|
11
|
+
prompt: str,
|
|
12
|
+
max_context_blocks: int = 5,
|
|
13
|
+
*,
|
|
14
|
+
memory_queries: Iterable[str] | None = None,
|
|
15
|
+
memory_priorities: Iterable[str] | None = None,
|
|
16
|
+
role_id: str | None = None,
|
|
17
|
+
) -> Dict[str, List[str]]:
|
|
18
|
+
emit_event(state_store.reports_dir() / "brain_memory.log.jsonl", "brain_memory_context_build_start", status="ok")
|
|
19
|
+
queries = [query for query in (memory_queries or ()) if isinstance(query, str) and query.strip()]
|
|
20
|
+
categories = [category for category in (memory_priorities or ()) if isinstance(category, str) and category.strip()]
|
|
21
|
+
role_priorities: List[str] = []
|
|
22
|
+
if role_id:
|
|
23
|
+
try:
|
|
24
|
+
from brain.runtime.roles import role_registry
|
|
25
|
+
role = role_registry.get_role(role_id)
|
|
26
|
+
role_priorities = list(role.memory_priority) if role else []
|
|
27
|
+
except Exception:
|
|
28
|
+
role_priorities = []
|
|
29
|
+
combined_priorities = [*categories, *role_priorities]
|
|
30
|
+
if queries:
|
|
31
|
+
mem = retrieval.retrieve_for_queries(queries, categories=combined_priorities or None)
|
|
32
|
+
else:
|
|
33
|
+
mem = retrieval.retrieve(prompt, categories=combined_priorities or None)
|
|
34
|
+
|
|
35
|
+
ranked_blocks: List[Dict[str, str | float]] = []
|
|
36
|
+
for item in mem.get("knowledge", []):
|
|
37
|
+
ranked_blocks.append(
|
|
38
|
+
{
|
|
39
|
+
"content": item.get("content"),
|
|
40
|
+
"source": "knowledge",
|
|
41
|
+
"score": float(item.get("score") or item.get("confidence") or 0.0),
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
for item in mem.get("tasks", []):
|
|
45
|
+
ranked_blocks.append(
|
|
46
|
+
{
|
|
47
|
+
"content": item.get("content"),
|
|
48
|
+
"source": "tasks",
|
|
49
|
+
"score": float(item.get("score") or item.get("confidence") or 0.0),
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
if role_priorities:
|
|
53
|
+
for item in ranked_blocks:
|
|
54
|
+
if item.get("source") in role_priorities:
|
|
55
|
+
item["score"] = float(item.get("score", 0.0)) + 0.2
|
|
56
|
+
emit_event(
|
|
57
|
+
state_store.reports_dir() / "brain_memory.log.jsonl",
|
|
58
|
+
"brain_role_context_weighted",
|
|
59
|
+
status="ok",
|
|
60
|
+
role_id=role_id,
|
|
61
|
+
priorities=len(role_priorities),
|
|
62
|
+
)
|
|
63
|
+
ranked_blocks.sort(key=lambda item: item.get("score", 0.0), reverse=True)
|
|
64
|
+
if len(ranked_blocks) > max_context_blocks:
|
|
65
|
+
ranked_blocks = ranked_blocks[:max_context_blocks]
|
|
66
|
+
emit_event(state_store.reports_dir() / "brain_memory.log.jsonl", "brain_memory_context_trim", status="ok")
|
|
67
|
+
|
|
68
|
+
context_blocks = [item["content"] for item in ranked_blocks if item.get("content")]
|
|
69
|
+
context_scores = [item.get("score", 0.0) for item in ranked_blocks]
|
|
70
|
+
synthesis = mem.get("synthesis", []) if isinstance(mem, dict) else []
|
|
71
|
+
for item in synthesis[:2]:
|
|
72
|
+
summary = item.get("summary") if isinstance(item, dict) else None
|
|
73
|
+
if summary:
|
|
74
|
+
context_blocks.append(str(summary))
|
|
75
|
+
|
|
76
|
+
context = {
|
|
77
|
+
"context_blocks": context_blocks,
|
|
78
|
+
"context_scores": context_scores,
|
|
79
|
+
"ranked_blocks": ranked_blocks,
|
|
80
|
+
"knowledge": mem.get("knowledge", []),
|
|
81
|
+
"tasks": mem.get("tasks", []),
|
|
82
|
+
"directives": [item["content"] if isinstance(item, dict) else item for item in mem.get("directives", [])],
|
|
83
|
+
"reflections": [item["content"] if isinstance(item, dict) else item for item in mem.get("reflections", [])],
|
|
84
|
+
"used_queries": queries,
|
|
85
|
+
}
|
|
86
|
+
emit_event(state_store.reports_dir() / "brain_memory.log.jsonl", "brain_memory_context_build_complete", status="ok")
|
|
87
|
+
return context
|