You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(server): don't disable/degrade embeddings when macOS misreports 0 MB available (#13)
The pre-model-load RAM gate read sysinfo's available_memory(), which returns 0
on some macOS versions (reclaimable memory parked in inactive/speculative/
purgeable pages isn't counted as free), so embedding-dependent tools were
silently disabled on healthy Macs.
- evaluate_memory_gate(): a 0 reading is a detection failure -> proceed with the
load; a genuine low-but-nonzero reading still falls back to graph-only.
- Applied consistently across all three sites: per-workspace MemoryManager gate,
socket-engine shared-model gate, and embed-loop RAM backpressure (0 no longer
triggers false pressure).
- CODEGRAPH_SKIP_MEMORY_CHECK=1 escape hatch (MCP + --run-tool); documented in
both READMEs.
- Unit tests cover load/skip/zero-proceed/bypass/boundary.
Closes#13.
Copy file name to clipboardExpand all lines: README.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -100,6 +100,21 @@ with no setup. For the CLI/MCP server it needs a local model directory
100
100
- Distill one from any sentence-transformer (Apache-2.0 Jina-Code by default) in
101
101
~30 s on CPU: `python scripts/distill_static_model.py`.
102
102
103
+
#### `CODEGRAPH_SKIP_MEMORY_CHECK` — force the embedding model past the RAM gate
104
+
105
+
Before loading the ONNX model, the server checks available memory and, if under
106
+
~1.5 GB, skips the model to avoid an OOM-kill (running graph-only instead).
107
+
Set `CODEGRAPH_SKIP_MEMORY_CHECK=1` (also accepts `true`/`yes`) to bypass that
108
+
check and always load the model.
109
+
110
+
Use it if embeddings are disabled even though the machine has plenty of free
111
+
RAM.
112
+
A reading of `0 MB available` is treated as a detection failure and the model
113
+
loads anyway (macOS parks reclaimable memory in inactive/speculative pages that
114
+
some memory readers do not count as free), so this override is mainly for other
115
+
cases where the reported figure is low but wrong.
116
+
It works in both MCP and one-shot `--run-tool` modes.
117
+
103
118
#### `--profile` — narrow the MCP tool surface
104
119
105
120
The full 32-tool surface is convenient but inflates the agent's prompt-context cost. A profile exposes only the slice you need (also settable via the `CODEGRAPH_TOOL_PROFILE` env var):
"Engine: only {} MB available — skipping shared embedding model to avoid OOM; running graph-only. Set CODEGRAPH_SKIP_MEMORY_CHECK=1 to override.",
231
+
avail / 1_000_000
232
+
);
224
233
None
225
234
}else{
235
+
if gate == crate::memory::MemoryGate::ProceedDetectionFailed{
236
+
tracing::warn!(
237
+
"Engine: available memory read as 0 MB — treating as a detection failure (common on macOS, where reclaimable memory is not counted as free) and proceeding with the shared model load. Set CODEGRAPH_SKIP_MEMORY_CHECK=1 to always bypass this check."
"[MemoryManager::initialize] only {} MB available — skipping embedding model to avoid OOM; semantic search disabled (graph-only). Set CODEGRAPH_SKIP_MEMORY_CHECK=1 to override.",
355
+
avail / 1_000_000
356
+
);
357
+
returnErr(MemoryError::Other(format!(
358
+
"insufficient memory ({} MB available) to load embedding model; running graph-only (set CODEGRAPH_SKIP_MEMORY_CHECK=1 to override)",
359
+
avail / 1_000_000
360
+
)));
361
+
}
362
+
MemoryGate::ProceedDetectionFailed => {
363
+
// 0 MB is a detection failure (see MemoryGate) — don't
364
+
// disable embeddings on a Mac that actually has RAM.
365
+
tracing::warn!(
366
+
"[MemoryManager::initialize] available memory read as 0 MB — treating as a detection failure (common on macOS, where reclaimable memory is not counted as free) and proceeding with the embedding model load. Set CODEGRAPH_SKIP_MEMORY_CHECK=1 to always bypass this check."
367
+
);
368
+
}
369
+
MemoryGate::Load => {}
302
370
}
303
371
}
304
372
@@ -612,6 +680,51 @@ pub use codegraph_memory::{
612
680
mod tests {
613
681
usesuper::*;
614
682
683
+
constMIN:u64 = MODEL_MIN_FREE_BYTES;
684
+
685
+
#[test]
686
+
fngate_loads_when_ample_memory(){
687
+
assert_eq!(
688
+
evaluate_memory_gate(8_000_000_000,MIN,false),
689
+
MemoryGate::Load
690
+
);
691
+
}
692
+
693
+
#[test]
694
+
fngate_loads_exactly_at_threshold(){
695
+
// `< min` is the skip condition, so exactly `min` must load.
Copy file name to clipboardExpand all lines: mcp-package/README.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,6 +54,11 @@ Pass flags after `--`:
54
54
|`--graph-only`| off | Skip embeddings — graph + structural tools only. No ONNX model load, 10-50× faster indexing. For CI / one-shot graph queries. |
55
55
|`--run-tool <name>`| — | One-shot: index, run a single tool, print result, exit. No MCP handshake. Pair with `--tool-args '<json>'`. |
56
56
57
+
Before loading the ONNX embedding model, the server checks available memory and runs graph-only if under ~1.5 GB.
58
+
If embeddings are disabled even though the machine has plenty of free RAM, set `CODEGRAPH_SKIP_MEMORY_CHECK=1` (also accepts `true`/`yes`) to bypass the check.
59
+
A reading of `0 MB available` is treated as a detection failure and the model loads anyway (common on macOS).
60
+
Works in both MCP and one-shot `--run-tool` modes.
61
+
57
62
### Agent rules (recommended)
58
63
59
64
Pre-configured rule files that teach your AI agent to use CodeGraph tools before falling back to grep / multi-file reads:
0 commit comments