@simbimbo/memory-ocmemog 0.1.11 → 0.1.13

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +83 -18
  3. package/brain/runtime/__init__.py +2 -12
  4. package/brain/runtime/config.py +1 -24
  5. package/brain/runtime/inference.py +1 -151
  6. package/brain/runtime/instrumentation.py +1 -15
  7. package/brain/runtime/memory/__init__.py +3 -13
  8. package/brain/runtime/memory/api.py +1 -1219
  9. package/brain/runtime/memory/candidate.py +1 -185
  10. package/brain/runtime/memory/conversation_state.py +1 -1823
  11. package/brain/runtime/memory/distill.py +1 -344
  12. package/brain/runtime/memory/embedding_engine.py +1 -92
  13. package/brain/runtime/memory/freshness.py +1 -112
  14. package/brain/runtime/memory/health.py +1 -40
  15. package/brain/runtime/memory/integrity.py +1 -186
  16. package/brain/runtime/memory/memory_consolidation.py +1 -58
  17. package/brain/runtime/memory/memory_links.py +1 -107
  18. package/brain/runtime/memory/memory_salience.py +1 -233
  19. package/brain/runtime/memory/memory_synthesis.py +1 -31
  20. package/brain/runtime/memory/memory_taxonomy.py +1 -33
  21. package/brain/runtime/memory/pondering_engine.py +1 -654
  22. package/brain/runtime/memory/promote.py +1 -277
  23. package/brain/runtime/memory/provenance.py +1 -406
  24. package/brain/runtime/memory/reinforcement.py +1 -71
  25. package/brain/runtime/memory/retrieval.py +1 -210
  26. package/brain/runtime/memory/semantic_search.py +1 -64
  27. package/brain/runtime/memory/store.py +1 -429
  28. package/brain/runtime/memory/unresolved_state.py +1 -91
  29. package/brain/runtime/memory/vector_index.py +1 -323
  30. package/brain/runtime/model_roles.py +1 -9
  31. package/brain/runtime/model_router.py +1 -22
  32. package/brain/runtime/providers.py +1 -66
  33. package/brain/runtime/security/redaction.py +1 -12
  34. package/brain/runtime/state_store.py +1 -23
  35. package/brain/runtime/storage_paths.py +1 -39
  36. package/docs/architecture/memory.md +20 -24
  37. package/docs/release-checklist.md +19 -6
  38. package/docs/usage.md +33 -17
  39. package/index.ts +8 -1
  40. package/ocmemog/__init__.py +11 -0
  41. package/ocmemog/doctor.py +1255 -0
  42. package/ocmemog/runtime/__init__.py +18 -0
  43. package/ocmemog/runtime/_compat_bridge.py +28 -0
  44. package/ocmemog/runtime/config.py +34 -0
  45. package/ocmemog/runtime/identity.py +115 -0
  46. package/ocmemog/runtime/inference.py +163 -0
  47. package/ocmemog/runtime/instrumentation.py +20 -0
  48. package/ocmemog/runtime/memory/__init__.py +91 -0
  49. package/ocmemog/runtime/memory/api.py +1594 -0
  50. package/ocmemog/runtime/memory/candidate.py +192 -0
  51. package/ocmemog/runtime/memory/conversation_state.py +1831 -0
  52. package/ocmemog/runtime/memory/distill.py +282 -0
  53. package/ocmemog/runtime/memory/embedding_engine.py +151 -0
  54. package/ocmemog/runtime/memory/freshness.py +114 -0
  55. package/ocmemog/runtime/memory/health.py +93 -0
  56. package/ocmemog/runtime/memory/integrity.py +208 -0
  57. package/ocmemog/runtime/memory/memory_consolidation.py +60 -0
  58. package/ocmemog/runtime/memory/memory_links.py +109 -0
  59. package/ocmemog/runtime/memory/memory_salience.py +235 -0
  60. package/ocmemog/runtime/memory/memory_synthesis.py +33 -0
  61. package/ocmemog/runtime/memory/memory_taxonomy.py +35 -0
  62. package/ocmemog/runtime/memory/pondering_engine.py +681 -0
  63. package/ocmemog/runtime/memory/promote.py +279 -0
  64. package/ocmemog/runtime/memory/provenance.py +408 -0
  65. package/ocmemog/runtime/memory/reinforcement.py +73 -0
  66. package/ocmemog/runtime/memory/retrieval.py +224 -0
  67. package/ocmemog/runtime/memory/semantic_search.py +66 -0
  68. package/ocmemog/runtime/memory/store.py +433 -0
  69. package/ocmemog/runtime/memory/unresolved_state.py +93 -0
  70. package/ocmemog/runtime/memory/vector_index.py +411 -0
  71. package/ocmemog/runtime/model_roles.py +15 -0
  72. package/ocmemog/runtime/model_router.py +28 -0
  73. package/ocmemog/runtime/providers.py +78 -0
  74. package/ocmemog/runtime/roles.py +92 -0
  75. package/ocmemog/runtime/security/__init__.py +8 -0
  76. package/ocmemog/runtime/security/redaction.py +17 -0
  77. package/ocmemog/runtime/state_store.py +32 -0
  78. package/ocmemog/runtime/storage_paths.py +70 -0
  79. package/ocmemog/sidecar/app.py +421 -60
  80. package/ocmemog/sidecar/compat.py +50 -13
  81. package/ocmemog/sidecar/transcript_watcher.py +327 -242
  82. package/openclaw.plugin.json +4 -0
  83. package/package.json +1 -1
  84. package/scripts/ocmemog-backfill-vectors.py +5 -3
  85. package/scripts/ocmemog-continuity-benchmark.py +1 -1
  86. package/scripts/ocmemog-demo.py +1 -1
  87. package/scripts/ocmemog-doctor.py +15 -0
  88. package/scripts/ocmemog-install.sh +29 -7
  89. package/scripts/ocmemog-integrated-proof.py +374 -0
  90. package/scripts/ocmemog-reindex-vectors.py +5 -3
  91. package/scripts/ocmemog-release-check.sh +330 -0
  92. package/scripts/ocmemog-sidecar.sh +4 -2
  93. package/scripts/ocmemog-test-rig.py +5 -3
  94. package/brain/runtime/memory/artifacts.py +0 -33
  95. package/brain/runtime/memory/context_builder.py +0 -112
  96. package/brain/runtime/memory/interaction_memory.py +0 -57
  97. package/brain/runtime/memory/memory_gate.py +0 -38
  98. package/brain/runtime/memory/memory_graph.py +0 -54
  99. package/brain/runtime/memory/person_identity.py +0 -83
  100. package/brain/runtime/memory/person_memory.py +0 -138
  101. package/brain/runtime/memory/sentiment_memory.py +0 -67
  102. package/brain/runtime/memory/tool_catalog.py +0 -68
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.13 — 2026-03-22
4
+
5
+ Final hardening release before a possible 1.0 cut.
6
+
7
+ ### Highlights
8
+ - tested the full shipped surface aggressively: full pytest suite, release gate, live sidecar contract smoke, packaging dry-run, installer surfaces, and governance summary responsiveness checks all passed together
9
+ - fixed a supersession-governance regression that could suppress `supersession_recommendation` generation and break governance queue/review/summary and auto-resolve flows
10
+ - moved dashboard supersession plain-English rewriting out of the render path so live dashboard loads stay fast while recommendations still carry human-readable text
11
+ - added a lightweight cached governance review summary path for the dashboard, reducing review load time from multi-second scans to sub-second first load and near-instant cached refresh
12
+ - simplified Governance Review UI output into more concise, single-row plain-English review items
13
+ - hardened supersession summary generation against polluted transcript/log content with tighter preview normalization, aggressive noise stripping, bounded local-model rewriting, and safe heuristic fallbacks
14
+ - fixed dashboard cursor handling so the dashboard route tolerates minimal/mock DB cursor implementations used by tests
15
+ - hardened the integrated proof token/session identifiers to avoid fresh-state collisions during repeated release validation
16
+
17
+ ## 0.1.12 — 2026-03-21
18
+
19
+ Release hardening, integrated proof validation, and native-ownership cleanup.
20
+
21
+ ### Highlights
22
+ - fixed conversation-state self-healing so polluted continuity cleanup preserves valid checkpoints instead of deleting the entire checkpoint history for a thread/session/conversation
23
+ - aligned FastAPI sidecar version reporting with the package version and added regression coverage for version drift
24
+ - moved runtime defaults toward native `ocmemog` ownership for report-log and SQLite DB naming while preserving legacy `brain_*` file fallback for existing installs
25
+ - made embedding configuration native-first (`OCMEMOG_*`) while keeping `BRAIN_*` aliases for compatibility
26
+ - hardened the integrated memory contract proof and release gate so fresh-state proof, live sidecar smoke, and route/regression validation run together as the canonical pre-release bar
27
+ - fixed release-gate/proof path bugs around HTTP method mismatches, async ingest/postprocess timing assumptions, and proof output capture
28
+ - restored live sidecar request-path verification for `/memory/ingest`, `/memory/search`, `/memory/get`, and `/conversation/hydrate`
29
+ - collapsed the legacy `brain/runtime/*` implementation tree into thin compatibility shims and removed orphan legacy side-modules that were no longer part of the shipped product contract
30
+ - cleaned release docs, compat wording, and helper scripts so new deployments follow native `ocmemog` behavior by default and stale side-DB architecture references are removed
31
+ - removed stray invalid transcript-watcher drift assertions from the test suite
32
+
3
33
  ## 0.1.11 — 2026-03-20
4
34
 
5
35
  Watcher reliability and release-quality follow-up.
package/README.md CHANGED
@@ -12,7 +12,7 @@ It is designed to go beyond simple memory search by providing:
12
12
  Architecture at a glance:
13
13
  - **OpenClaw plugin (`index.ts`)** handles tools and hook integration
14
14
  - **FastAPI sidecar (`ocmemog/sidecar/`)** exposes memory and continuity APIs
15
- - **SQLite-backed runtime (`brain/runtime/memory/`)** powers storage, hydration, checkpoints, salience ranking, and pondering
15
+ - **SQLite-backed runtime (`ocmemog/runtime/memory/`)** powers storage, hydration, checkpoints, salience ranking, and pondering
16
16
 
17
17
  Current local runtime architecture note:
18
18
  - `docs/architecture/local-runtime-2026-03-19.md`
@@ -21,8 +21,9 @@ Current local runtime architecture note:
21
21
 
22
22
  - `openclaw.plugin.json`, `index.ts`, `package.json`: OpenClaw plugin package and manifest.
23
23
  - `ocmemog/sidecar/`: FastAPI sidecar with `/memory/search` and `/memory/get`.
24
- - `brain/runtime/memory/`: copied brAIn memory package.
25
- - `brain/runtime/`: compatibility shims for state store, instrumentation, redaction, storage paths, and a few placeholder runtime modules needed for importability.
24
+ - `ocmemog/runtime/`: native runtime surfaces used by the sidecar and memory engine.
25
+ - `ocmemog/runtime/memory/`: local memory/runtime package used by the sidecar.
26
+ - `brain/`: internal compatibility residue retained for transitional shim paths; not the primary runtime surface.
26
27
  - `scripts/ocmemog-sidecar.sh`: convenience launcher.
27
28
 
28
29
  ## Run the sidecar
@@ -38,11 +39,44 @@ pip install -r requirements.txt
38
39
  # http://127.0.0.1:17891/dashboard
39
40
  ```
40
41
 
42
+ For local development and CI-style test runs, install test dependencies as well:
43
+
44
+ ```bash
45
+ cd /path/to/ocmemog
46
+ python3 -m venv .venv
47
+ . .venv/bin/activate
48
+ python -m pip install -r requirements-test.txt
49
+ ```
50
+
51
+ ### Run the doctor check
52
+
53
+ ```bash
54
+ ./.venv/bin/python3 scripts/ocmemog-doctor.py
55
+ ./.venv/bin/python3 scripts/ocmemog-doctor.py --json
56
+ ./.venv/bin/python3 scripts/ocmemog-doctor.py --fix create-missing-paths --fix repair-queue
57
+ ./.venv/bin/python3 scripts/ocmemog-doctor.py --strict --check runtime/imports --check sqlite/schema-access
58
+ ```
59
+
60
+ The doctor command currently checks:
61
+ - runtime/imports
62
+ - state/path-writable
63
+ - sqlite/schema-access
64
+ - sidecar/http-auth
65
+ - queue/health
66
+ - sidecar/transcript-watcher
67
+ - sidecar/app-import
68
+ - sidecar/transcript-roots
69
+ - sidecar/env-toggles
70
+ - vector/runtime-probe
71
+
41
72
  ## Optional: transcript watcher (auto-ingest)
42
73
 
43
74
  ```bash
44
- # defaults to ~/.openclaw/workspace/memory/transcripts if not set
75
+ # defaults:
76
+ # - transcript mode: ~/.openclaw/workspace/memory/transcripts
77
+ # - session mode: ~/.openclaw/agents/main/sessions (used when OCMEMOG_TRANSCRIPT_DIR is unset)
45
78
  export OCMEMOG_TRANSCRIPT_DIR="$HOME/.openclaw/workspace/memory/transcripts"
79
+ export OCMEMOG_SESSION_DIR="$HOME/.openclaw/agents/main/sessions"
46
80
  ./scripts/ocmemog-transcript-watcher.sh
47
81
  ```
48
82
 
@@ -80,11 +114,26 @@ Optional environment variables:
80
114
  - `OCMEMOG_OPENAI_API_KEY` (required for model-backed distill)
81
115
  - `OCMEMOG_OPENAI_API_BASE` (default: `https://api.openai.com/v1`)
82
116
  - `OCMEMOG_OPENAI_EMBED_MODEL` (default: `text-embedding-3-small`)
83
- - `BRAIN_EMBED_MODEL_LOCAL` (`simple` by default)
84
- - `BRAIN_EMBED_MODEL_PROVIDER` (`local-openai` to use the local llama.cpp embedding endpoint; `openai` remains available for hosted embeddings)
117
+ - `OCMEMOG_EMBED_MODEL_LOCAL` (`simple` by default; legacy alias: `BRAIN_EMBED_MODEL_LOCAL`)
118
+ - `OCMEMOG_EMBED_MODEL_PROVIDER` (`local-openai` to use the local llama.cpp embedding endpoint; `openai` remains available for hosted embeddings; legacy alias: `BRAIN_EMBED_MODEL_PROVIDER`)
85
119
  - `OCMEMOG_TRANSCRIPT_WATCHER` (`true` to auto-start transcript watcher inside the sidecar)
86
120
  - `OCMEMOG_TRANSCRIPT_ROOTS` (comma-separated allowed roots for transcript context retrieval; default: `~/.openclaw/workspace/memory`)
87
- - `OCMEMOG_API_TOKEN` (optional; if set, requests must include `x-ocmemog-token` or `Authorization: Bearer ...`)
121
+ - `OCMEMOG_TRANSCRIPT_DIR` (default: `~/.openclaw/workspace/memory/transcripts`)
122
+ - `OCMEMOG_SESSION_DIR` (default: `~/.openclaw/agents/main/sessions`)
123
+ - `OCMEMOG_TRANSCRIPT_POLL_SECONDS` (poll interval for file/session watcher; default: `30`, or `120` in battery mode)
124
+ - `OCMEMOG_INGEST_BATCH_SECONDS` (max lines per watcher batch; default: `30`, or `120` in battery mode)
125
+ - `OCMEMOG_INGEST_BATCH_MAX` (max watcher batches before yield; default: `25`, or `10` in battery mode)
126
+ - `OCMEMOG_SESSION_GLOB` (default file glob for session sources: `*.jsonl`)
127
+ - `OCMEMOG_TRANSCRIPT_GLOB` (default file glob for transcripts: `*.log`)
128
+ - `OCMEMOG_INGEST_ASYNC_WORKER` (`true` to keep async ingest queue processing enabled; defaults to `true`)
129
+ - `OCMEMOG_INGEST_ASYNC_POLL_SECONDS` (`5` by default)
130
+ - `OCMEMOG_INGEST_ASYNC_BATCH_MAX` (`25` by default)
131
+ - `OCMEMOG_INGEST_ENDPOINT` (default: `http://127.0.0.1:17891/memory/ingest_async`)
132
+ - `OCMEMOG_SHUTDOWN_DRAIN_QUEUE` (`true` to drain remaining queue entries during shutdown; defaults to `false`)
133
+ - `OCMEMOG_WORKER_SHUTDOWN_TIMEOUT_SECONDS` (`0.35` by default)
134
+ - `OCMEMOG_SHUTDOWN_DUMP_THREADS` (`true` to include worker thread dump output during shutdown joins; defaults to `false`)
135
+ - `OCMEMOG_SHUTDOWN_TIMING` (`true` enables shutdown timing logs; defaults to `true`)
136
+ - `OCMEMOG_API_TOKEN` (optional; if set, requests must include `x-ocmemog-token` or `Authorization: Bearer ...`; OpenClaw plugin users should also set the plugin `config.token` field)
88
137
  - `OCMEMOG_AUTO_HYDRATION` (`true` to re-enable prompt-time continuity prepending; defaults to `false` as a safety guard until the host runtime is verified not to persist prepended context into session history)
89
138
  - `OCMEMOG_LAPTOP_MODE` (`auto` by default; on macOS battery power this slows watcher polling, reduces ingest batch size, and disables sentiment reinforcement unless explicitly overridden)
90
139
  - `OCMEMOG_LOCAL_LLM_BASE_URL` (default: `http://127.0.0.1:18080/v1`; local OpenAI-compatible text endpoint, e.g. llama.cpp)
@@ -101,6 +150,8 @@ Optional environment variables:
101
150
  - `OCMEMOG_PONDER_MODEL` (default via launcher: `local-openai:qwen2.5-7b-instruct`; recommended for structured local memory refinement)
102
151
  - `OCMEMOG_LESSON_MINING_ENABLED` (default: `true`)
103
152
 
153
+ Boolean env values are parsed case-insensitively and support `1/0`, `true/false`, `yes/no`, `on/off`, `y/n`, and `t/f`.
154
+
104
155
  ## Security
105
156
 
106
157
  - Sidecar binds to **127.0.0.1** by default. Keep it local unless you add auth + firewall rules.
@@ -162,19 +213,32 @@ launchctl bootstrap gui/$UID scripts/launchagents/com.openclaw.ocmemog.guard.pli
162
213
 
163
214
  ## Recent changes
164
215
 
165
- ### 0.1.11 (current main)
216
+ ### 0.1.12 (current main)
166
217
 
167
- Current main includes the recent memory-quality, governance, and watcher hardening work, including:
168
- - transcript watcher duplicate-ingest prevention
169
- - watcher auth propagation for `OCMEMOG_API_TOKEN`
170
- - persisted queue stats restored on startup
171
- - durable watcher error logging
172
- - multi-part text preservation for session content arrays
173
- - retry-safe session/transcript handling with transcript provenance preserved
174
- - pytest declared as a repo test extra and available in the local project venv
218
+ Current main now includes:
219
+ - integrated release-gate validation with a fresh-state memory contract proof
220
+ - live sidecar smoke checks for `/memory/ingest`, `/memory/search`, `/memory/get`, and `/conversation/hydrate`
221
+ - hardened async ingest/postprocess handling and queue-health validation
222
+ - native-first `ocmemog` config, DB, and report-log naming with legacy fallback support
223
+ - sidecar/package version alignment and regression coverage for checkpoint self-heal behavior
224
+ - major collapse of the legacy `brain/runtime/*` implementation surface into thin compatibility shims
225
+ - removal of orphan legacy memory side-modules and stale architecture references to retired side DBs
175
226
 
176
227
  ## Release prep / publish
177
228
 
229
+ Run the release gate first:
230
+
231
+ ```bash
232
+ ./scripts/ocmemog-release-check.sh
233
+ ```
234
+
235
+ This command is the canonical pre-release and CI validation path. A pass now means:
236
+ - strict doctor checks succeed on a clean temporary state
237
+ - the broad regression subset plus sidecar route tests pass
238
+ - live `/healthz`, `/memory/ingest`, `/memory/search`, `/memory/get`, and `/conversation/hydrate` checks pass on `OCMEMOG_RELEASE_LIVE_ENDPOINT`
239
+ - the integrated memory contract proof runs in fresh state and emits `reports/release-gate-proof.json`
240
+ - syntax checks, integration assertions, and non-blocking packing validation are attempted
241
+
178
242
  Example ClawHub publish command (update version + changelog first; do not reuse stale release text blindly):
179
243
 
180
244
  ```bash
@@ -205,6 +269,8 @@ plugins:
205
269
  config:
206
270
  endpoint: http://127.0.0.1:17891
207
271
  timeoutMs: 30000
272
+ # Optional if the sidecar is protected by OCMEMOG_API_TOKEN
273
+ token: your-ocmemog-token
208
274
  ```
209
275
 
210
276
  Development install:
@@ -229,7 +295,6 @@ What is working now:
229
295
  Current limitations before broader public rollout:
230
296
  - Some advanced inference- and embedding-dependent paths still depend on environment configuration and may degrade to simpler local behavior if provider access is unavailable
231
297
  - Packaging and install UX are aimed primarily at power users and local developers today
232
- - Public release/distribution metadata is still being tightened up
298
+ - Distribution and release metadata are now tracked in `package.json`, `CHANGELOG.md`, and the release check workflow.
233
299
 
234
300
  When a richer path is unavailable, the sidecar is designed to fail soft with explicit warnings rather than crash.
235
- soft with explicit warnings rather than crash.
@@ -1,13 +1,3 @@
1
- """Minimal runtime shims required by the copied brAIn memory package."""
1
+ from __future__ import annotations
2
2
 
3
- from . import config, inference, instrumentation, model_roles, model_router, state_store, storage_paths
4
-
5
- __all__ = [
6
- "config",
7
- "inference",
8
- "instrumentation",
9
- "model_roles",
10
- "model_router",
11
- "state_store",
12
- "storage_paths",
13
- ]
3
+ from ocmemog.runtime import * # noqa: F401,F403
@@ -1,26 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
-
5
- BRAIN_EMBED_MODEL_LOCAL = os.environ.get("BRAIN_EMBED_MODEL_LOCAL", "simple")
6
- BRAIN_EMBED_MODEL_PROVIDER = os.environ.get("BRAIN_EMBED_MODEL_PROVIDER", "")
7
-
8
- OCMEMOG_MEMORY_MODEL = os.environ.get("OCMEMOG_MEMORY_MODEL", "gpt-4o-mini")
9
- OCMEMOG_OPENAI_API_BASE = os.environ.get("OCMEMOG_OPENAI_API_BASE", "https://api.openai.com/v1")
10
- OCMEMOG_OPENAI_EMBED_MODEL = os.environ.get("OCMEMOG_OPENAI_EMBED_MODEL", "text-embedding-3-small")
11
-
12
- OCMEMOG_LOCAL_LLM_BASE_URL = os.environ.get("OCMEMOG_LOCAL_LLM_BASE_URL", "http://127.0.0.1:18080/v1")
13
- OCMEMOG_LOCAL_LLM_MODEL = os.environ.get("OCMEMOG_LOCAL_LLM_MODEL", "qwen2.5-7b-instruct")
14
- OCMEMOG_LOCAL_EMBED_BASE_URL = os.environ.get("OCMEMOG_LOCAL_EMBED_BASE_URL", "http://127.0.0.1:18081/v1")
15
- OCMEMOG_LOCAL_EMBED_MODEL = os.environ.get("OCMEMOG_LOCAL_EMBED_MODEL", "nomic-embed-text-v1.5")
16
-
17
- OCMEMOG_OLLAMA_HOST = os.environ.get("OCMEMOG_OLLAMA_HOST", "http://127.0.0.1:11434")
18
- OCMEMOG_OLLAMA_MODEL = os.environ.get("OCMEMOG_OLLAMA_MODEL", "qwen2.5:7b")
19
- OCMEMOG_OLLAMA_EMBED_MODEL = os.environ.get("OCMEMOG_OLLAMA_EMBED_MODEL", "nomic-embed-text:latest")
20
-
21
- OCMEMOG_PROMOTION_THRESHOLD = float(os.environ.get("OCMEMOG_PROMOTION_THRESHOLD", "0.5"))
22
- OCMEMOG_DEMOTION_THRESHOLD = float(os.environ.get("OCMEMOG_DEMOTION_THRESHOLD", "0.2"))
23
-
24
- OCMEMOG_PONDER_ENABLED = os.environ.get("OCMEMOG_PONDER_ENABLED", "true")
25
- OCMEMOG_PONDER_MODEL = os.environ.get("OCMEMOG_PONDER_MODEL", OCMEMOG_MEMORY_MODEL)
26
- OCMEMOG_LESSON_MINING_ENABLED = os.environ.get("OCMEMOG_LESSON_MINING_ENABLED", "true")
3
+ from ocmemog.runtime.config import * # noqa: F401,F403
@@ -1,153 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
4
- import os
5
- import re
6
- import urllib.request
7
-
8
- from brain.runtime import config, 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 _infer_openai_compatible(prompt: str, *, base_url: str, model: str, api_key: str | None = None, provider_label: str = "openai-compatible") -> dict[str, str]:
15
- url = f"{base_url.rstrip('/')}/chat/completions"
16
- payload = {
17
- "model": model,
18
- "messages": [{"role": "user", "content": prompt}],
19
- "temperature": 0.2,
20
- }
21
- data = json.dumps(payload).encode("utf-8")
22
- req = urllib.request.Request(url, data=data, method="POST")
23
- if api_key:
24
- req.add_header("Authorization", f"Bearer {api_key}")
25
- req.add_header("Content-Type", "application/json")
26
-
27
- try:
28
- with urllib.request.urlopen(req, timeout=30) as resp:
29
- response = json.loads(resp.read().decode("utf-8"))
30
- except Exception as exc:
31
- emit_event(LOGFILE, "brain_infer_error", status="error", provider=provider_label, error=str(exc))
32
- return {"status": "error", "error": f"request_failed:{exc}"}
33
-
34
- try:
35
- output = response["choices"][0]["message"]["content"]
36
- except Exception as exc:
37
- emit_event(LOGFILE, "brain_infer_error", status="error", provider=provider_label, error=str(exc))
38
- return {"status": "error", "error": "invalid_response"}
39
-
40
- return {"status": "ok", "output": str(output).strip()}
41
-
42
-
43
- def _infer_ollama(prompt: str, model: str | None = None) -> dict[str, str]:
44
- payload = {
45
- "model": model or config.OCMEMOG_OLLAMA_MODEL,
46
- "prompt": prompt,
47
- "stream": False,
48
- }
49
- data = json.dumps(payload).encode("utf-8")
50
- req = urllib.request.Request(f"{config.OCMEMOG_OLLAMA_HOST.rstrip('/')}/api/generate", data=data, method="POST")
51
- req.add_header("Content-Type", "application/json")
52
- try:
53
- with urllib.request.urlopen(req, timeout=60) as resp:
54
- response = json.loads(resp.read().decode("utf-8"))
55
- except Exception as exc:
56
- emit_event(LOGFILE, "brain_infer_error", status="error", provider="ollama", error=str(exc))
57
- return {"status": "error", "error": f"ollama_failed:{exc}"}
58
- output = response.get("response")
59
- if not output:
60
- emit_event(LOGFILE, "brain_infer_error", status="error", provider="ollama", error="invalid_response")
61
- return {"status": "error", "error": "invalid_response"}
62
- return {"status": "ok", "output": str(output).strip()}
63
-
64
-
65
- def _looks_like_local_openai_model(name: str) -> bool:
66
- if not name:
67
- return False
68
- lowered = name.strip().lower()
69
- return lowered.startswith("local-openai:") or lowered.startswith("local_openai:") or lowered.startswith("llamacpp:")
70
-
71
-
72
- def _normalize_local_model_name(name: str) -> str:
73
- lowered = (name or "").strip()
74
- for prefix in ("local-openai:", "local_openai:", "llamacpp:"):
75
- if lowered.lower().startswith(prefix):
76
- return lowered[len(prefix):]
77
- return lowered
78
-
79
-
80
- def _looks_like_ollama_model(name: str) -> bool:
81
- if not name:
82
- return False
83
- lowered = name.strip().lower()
84
- if lowered.startswith("ollama:"):
85
- return True
86
- if "/" in lowered:
87
- return False
88
- return ":" in lowered
89
-
90
-
91
- def stats() -> dict[str, object]:
92
- materialized_local = int(_LOCAL_INFER_STATS.get("local_success", 0)) + int(_LOCAL_INFER_STATS.get("cache_hits", 0))
93
- est_prompt_tokens_saved = materialized_local * _AVG_PROMPT_TOKENS_SAVED
94
- est_completion_tokens_saved = materialized_local * _AVG_COMPLETION_TOKENS_SAVED
95
- est_cost_saved = (
96
- (est_prompt_tokens_saved / 1000.0) * _EST_FRONTIER_INPUT_COST_PER_1K
97
- + (est_completion_tokens_saved / 1000.0) * _EST_FRONTIER_OUTPUT_COST_PER_1K
98
- )
99
- return {
100
- "cache_entries": len(_LOCAL_INFER_CACHE),
101
- "warm_models": sorted(_MODEL_WARM_STATE.keys()),
102
- "frontier_calls_avoided_est": materialized_local,
103
- "prompt_tokens_saved_est": est_prompt_tokens_saved,
104
- "completion_tokens_saved_est": est_completion_tokens_saved,
105
- "cost_saved_usd_est": round(est_cost_saved, 4),
106
- **{k: int(v) for k, v in _LOCAL_INFER_STATS.items()},
107
- }
108
-
109
-
110
- def infer(prompt: str, provider_name: str | None = None) -> dict[str, str]:
111
- if not isinstance(prompt, str) or not prompt.strip():
112
- return {"status": "error", "error": "empty_prompt"}
113
-
114
- use_ollama = os.environ.get("OCMEMOG_USE_OLLAMA", "").lower() in {"1", "true", "yes"}
115
- model_override = provider_name or config.OCMEMOG_MEMORY_MODEL
116
- if _looks_like_local_openai_model(model_override):
117
- model = _normalize_local_model_name(model_override) or config.OCMEMOG_LOCAL_LLM_MODEL
118
- return _infer_openai_compatible(
119
- prompt,
120
- base_url=config.OCMEMOG_LOCAL_LLM_BASE_URL,
121
- model=model,
122
- api_key=os.environ.get("OCMEMOG_LOCAL_LLM_API_KEY") or os.environ.get("LOCAL_LLM_API_KEY"),
123
- provider_label="local-openai",
124
- )
125
- if use_ollama or _looks_like_ollama_model(model_override):
126
- model = model_override.split(":", 1)[-1] if model_override.startswith("ollama:") else model_override
127
- return _infer_ollama(prompt, model)
128
-
129
- api_key = os.environ.get("OCMEMOG_OPENAI_API_KEY") or os.environ.get("OPENAI_API_KEY")
130
- if not api_key:
131
- return _infer_openai_compatible(
132
- prompt,
133
- base_url=config.OCMEMOG_LOCAL_LLM_BASE_URL,
134
- model=config.OCMEMOG_LOCAL_LLM_MODEL,
135
- api_key=os.environ.get("OCMEMOG_LOCAL_LLM_API_KEY") or os.environ.get("LOCAL_LLM_API_KEY"),
136
- provider_label="local-openai",
137
- )
138
-
139
- model = model_override
140
- return _infer_openai_compatible(
141
- prompt,
142
- base_url=config.OCMEMOG_OPENAI_API_BASE,
143
- model=model,
144
- api_key=api_key,
145
- provider_label="openai",
146
- )
147
-
148
-
149
- def parse_operator_name(text: str) -> dict[str, str] | None:
150
- match = re.search(r"\bmy name is ([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b", text, flags=re.IGNORECASE)
151
- if not match:
152
- return None
153
- return {"name": match.group(1)}
3
+ from ocmemog.runtime.inference import * # noqa: F401,F403
@@ -1,17 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
4
- from datetime import datetime, timezone
5
- from pathlib import Path
6
- from typing import Any
7
-
8
-
9
- def emit_event(path: Path, event: str, **fields: Any) -> None:
10
- path.parent.mkdir(parents=True, exist_ok=True)
11
- payload = {
12
- "timestamp": datetime.now(timezone.utc).isoformat(),
13
- "event": event,
14
- **fields,
15
- }
16
- with path.open("a", encoding="utf-8") as handle:
17
- handle.write(json.dumps(payload, sort_keys=True) + "\n")
3
+ from ocmemog.runtime.instrumentation import * # noqa: F401,F403
@@ -1,13 +1,3 @@
1
- __all__ = [
2
- "store",
3
- "distill",
4
- "candidate",
5
- "promote",
6
- "retrieval",
7
- "reinforcement",
8
- "integrity",
9
- "vector_index",
10
- "context_builder",
11
- "memory_taxonomy",
12
- "health",
13
- ]
1
+ from __future__ import annotations
2
+
3
+ from ocmemog.runtime.memory import * # noqa: F401,F403