github rohitg00/agentmemory v0.9.12
v0.9.12 — BM25 unicode + vector live-write + viewer hardening + plaintext-bearer guard

4 hours ago

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=1 escalation 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.source declaration (#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:

  1. Removed the <link rel="stylesheet"> to fonts.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.

  2. Wrapped loadDashboard() body in a try/catch that 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/mcp package 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/mcp

Full changelog: v0.9.11...v0.9.12

Don't miss a new agentmemory release

NewReleases is sending notifications on new releases.