v0.20.3
Fixed
Two observer crash modes and one upstream-pin bump — all aimed at the supervised observer surviving real-world macOS conditions.
asyncio.get_event_loop()→get_running_loop()in the observer coroutine (memory/observer.py:212). On Python 3.14 the deprecated call has been observed raisingNameError: name 'asyncio' is not definedfrom inside the coroutine launched byasyncio.run(self._run_async()), even thoughasynciois imported at module scope and the same name resolves fine inrun()a few lines up.get_running_loop()is the canonical API inside a running coroutine, dodges the deprecation, and stops the supervisor from chewing throughmax_restarts: 10on every restart.- fastembed cache pinned to
~/.cache/neo/fastembed/(memory/store.py). The default cache lives under$TMPDIR/fastembed_cache/, which on macOS is/var/folders/<...>/T/— periodically swept by the OS. After a sweep the in-cache manifest still points at a (now-deleted)model.onnxandTextEmbedding(...)raisesONNXRuntimeError ... NO_SUCHFILE, leaving FactStore silently running without embeddings until a human noticed. The new path survives reboots and tmp sweeps; onNO_SUCHFILE/ missing-model.onnxthe loader nukes the stale snapshot dir and retries once, so any future eviction self-heals.
Changed
car-runtimepin bumped to>=0.18.0for two upstream supervisor-reliability fixes that directly hitneo memory observer:spawn_supervisionis now teardown-first withkill_on_drop, so astartissued duringBackoffcan no longer leave an orphaned child holding the agent's port; and restart backoff is exponential (base → ×2, capped at 60s) instead of flat, so a crash loop can no longer burn throughmax_restartsin under a minute.last_exit_codeis also now cleared on successful (re)start, soneo memory observer statuswon't show a stale1next to a healthyrunningagent. No neo code changes required — the pin captures the upstream wins for new installs.