Four landed PRs since v0.9.11 — one type-correctness fix, one search-quality fix (BM25 unicode + vector-index live-write), one viewer hardening (CSP-clean fonts + load-error surface), and one integrations security hardening (bearer token over plaintext HTTP).
Contributors
Huge thanks to four external contributors this release:
- @mvanhorn — plaintext-bearer-auth guard across Hermes (Python), OpenClaw (mjs), and pi (TypeScript) plus the
AGENTMEMORY_REQUIRE_HTTPS=1escalation knob (#315) - @nik1t7n — original repro for the BM25 non-ASCII tokenizer bug + vector-index-never-populated trace (#295)
- @hem57 — Windows repro screenshot + browser-console CSP-violation trace that pinned down the viewer "stuck Loading" path (#323)
- @cl0ckt0wer — precise file:line trace for the duplicate
RetentionScore.sourcedeclaration (#277)
Fixed
BM25 tokenizer now indexes non-ASCII; vector index now actually populated at runtime (#327, closes #295)
Two bugs in one PR:
BM25 tokenizer regex stripped every non-ASCII character. src/state/search-index.ts used \w (JS \w is ASCII-only), so non-English search returned empty results across the board — Greek, accented Latin, Hebrew, Arabic, Cyrillic. Regex replaced with /[^\p{L}\p{N}\s/.\\-_]/gu (Unicode letters/numbers, preserves underscore for memory_recall-style identifiers, keeps existing path/separator handling).
VectorIndex.add() had zero callers anywhere in src/. The vector index was loaded from disk at startup and never updated at runtime, so hybrid search returned stale results forever. New vectorIndexAddGuarded() helper in src/functions/search.ts wires vectorIndex.add() into remember.ts, observe.ts synthetic-compression branch, compress.ts post-LLM compression, and the cold-start rebuildIndex() walk — with a per-write dimension guard (symmetric to the persistence-load guard from #248), 16k-char input clipping (so an oversized memory can't 400 the embed call), and consistent stderr logging that no longer swallows embed failures.
migrateVectorIndex() utility re-embeds every memory + per-session observation against a new provider when dimensions change; per-session try/catch isolation so one bad session can't abort the whole migration; structured failedSessions[] result with a "<sessions-list-failed>" sentinel that distinguishes a catastrophic list-failure from per-session failures.
Soft-fail throughout: a downed embedder never breaks an upstream save. Live-tested end-to-end against Greek fixtures (thanks @nik1t7n for the original repro).
CJK caveat preserved: this fix recovers Greek, Cyrillic, accented Latin, Hebrew, Arabic, and other space-delimited scripts. CJK languages without spaces between characters still tokenize as a single sentence-long token — separate concern, needs a segmenter (PR #224 area).
Integrations now warn when sending the bearer token over plaintext HTTP (#315, closes #275)
Symmetric guard across all three plugin runtimes (Python / mjs / TypeScript): a request that would attach Authorization: Bearer <secret> to a http://<non-loopback>:port URL now logs a one-time stderr warning telling the operator the token is observable on the wire.
Loopback hosts (localhost, 127.0.0.1, ::1) and https:// URLs are exempt.
New env knob AGENTMEMORY_REQUIRE_HTTPS=1 escalates the warning to a hard refusal — the plugin throws before any request is sent, so a misconfigured deployment can fail loudly instead of leaking the bearer once.
Edge cases verified by 13 tests: IPv6 [::1] loopback (loopback), RFC1918 LAN IPs (192.168.x.x / 10.x.x.x warn — NOT loopback by design), lookalike hostnames (localhost.evil.com warns), no-secret short-circuit (guard never fires when no bearer would be sent), https-with-secret silent. Thanks @mvanhorn.
Viewer dashboard no longer sticks on "Loading dashboard…" (#335, closes #323)
Two narrow fixes from @hem57's Windows repro:
-
Removed the
<link rel="stylesheet">tofonts.googleapis.com. The viewer's strict CSP (default-src 'none',style-src 'unsafe-inline',font-src 'self') blocks external stylesheet origins by design, so every page load logged a CSP violation for the font CSS and another for each blocked font file. System-font fallbacks were already declared on every--font-*CSS variable so dropping the external<link>is a clean swap. -
Wrapped
loadDashboard()body in atry/catchthat renders the error inline ("Dashboard failed to load: <reason>") instead of leaving the placeholder text up forever. Future "stuck Loading" reports now come with concrete error messages instead of just a screenshot of the placeholder.
RetentionScore type no longer declares source twice (#326, closes #277)
src/types.ts:835 and :842 both declared source?: "episodic" | "semantic" on RetentionScore. TypeScript silently accepts duplicate property declarations when the types are identical, so the build never errored — but the documented JSDoc on the first declaration (the #124 back-compat note explaining undefined should probe both scopes) was effectively shadowed by the duplicate. Removed the second declaration; grep confirmed no caller writes source twice on the same row, so the cleanup is a pure type-correctness fix with no runtime change. Thanks @cl0ckt0wer.
Changed
@agentmemory/mcppackage version bumped 0.9.11 → 0.9.12 to lockstep with the main package.
Install / upgrade
npm i -g @agentmemory/agentmemory@0.9.12
# or
npx @agentmemory/agentmemory
# MCP standalone shim
npx -y @agentmemory/mcpFull changelog: v0.9.11...v0.9.12