fix: detect total RAM on Windows via GlobalMemoryStatusEx

`_total_ram_gb()` had branches for Darwin (sysctl) and Linux
(/proc/meminfo) but no Windows path, so `jarvis init` reported
"0.0 GB RAM" on every Windows host. The downstream
`recommend_model()` then fell back to VRAM-only sizing, often
selecting a smaller tier than the system can actually run.

Add a Windows branch that calls `GlobalMemoryStatusEx` via
ctypes — no new dependency. Add a platform-skip-aware test for
each OS branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
IsaacH
2026-05-20 03:36:55 +00:00
committed by krypticmouse
co-authored by Claude Opus 4.7
parent 8b5a304222
commit 31efd9e672
2 changed files with 51 additions and 1 deletions
+22 -1
View File
@@ -188,13 +188,34 @@ def _total_ram_gb() -> float:
if platform.system() == "Darwin":
raw = _run_cmd(["sysctl", "-n", "hw.memsize"])
return round(int(raw) / (1024**3), 1) if raw else 0.0
if platform.system() == "Windows":
import ctypes
class _MemoryStatusEx(ctypes.Structure):
_fields_ = [
("dwLength", ctypes.c_ulong),
("dwMemoryLoad", ctypes.c_ulong),
("ullTotalPhys", ctypes.c_ulonglong),
("ullAvailPhys", ctypes.c_ulonglong),
("ullTotalPageFile", ctypes.c_ulonglong),
("ullAvailPageFile", ctypes.c_ulonglong),
("ullTotalVirtual", ctypes.c_ulonglong),
("ullAvailVirtual", ctypes.c_ulonglong),
("sullAvailExtendedVirtual", ctypes.c_ulonglong),
]
stat = _MemoryStatusEx()
stat.dwLength = ctypes.sizeof(_MemoryStatusEx)
if ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)):
return round(stat.ullTotalPhys / (1024**3), 1)
return 0.0
meminfo = Path("/proc/meminfo")
if meminfo.exists():
for line in meminfo.read_text().splitlines():
if line.startswith("MemTotal"):
kb = int(line.split()[1])
return round(kb / (1024**2), 1)
except (OSError, ValueError):
except (OSError, ValueError, AttributeError):
pass
return 0.0
+29
View File
@@ -3,13 +3,17 @@ and engine recommendation."""
from __future__ import annotations
import sys
from unittest.mock import patch
import pytest
from openjarvis.core.config import (
GpuInfo,
_detect_amd_gpu,
_detect_apple_gpu,
_detect_nvidia_gpu,
_total_ram_gb,
recommend_engine,
)
@@ -75,6 +79,31 @@ class TestDetectHardware:
assert _detect_apple_gpu() is None
# ---------------------------------------------------------------------------
# RAM detection
# ---------------------------------------------------------------------------
class TestTotalRamGb:
"""Tests for _total_ram_gb() across platforms."""
@pytest.mark.skipif(sys.platform != "win32", reason="Requires Windows")
def test_total_ram_gb_windows(self):
"""On Windows, GlobalMemoryStatusEx must return a positive RAM value."""
ram = _total_ram_gb()
assert ram > 0, f"Expected > 0 GB on Windows, got {ram}"
@pytest.mark.skipif(sys.platform != "darwin", reason="Requires macOS")
def test_total_ram_gb_darwin(self):
ram = _total_ram_gb()
assert ram > 0, f"Expected > 0 GB on macOS, got {ram}"
@pytest.mark.skipif(not sys.platform.startswith("linux"), reason="Requires Linux")
def test_total_ram_gb_linux(self):
ram = _total_ram_gb()
assert ram > 0, f"Expected > 0 GB on Linux, got {ram}"
# ---------------------------------------------------------------------------
# Engine recommendation
# ---------------------------------------------------------------------------