v0.2.7
Release Notes for v0.2.7
This release adds first-class TypeScript SDK integrations for the Vercel AI SDK, Mastra, and OpenAI; closes another set of security gaps (agent lifecycle management auth, recall filter injection, unique on-prem upload staging paths); fixes event-loop-blocking bugs in on-prem restart and session end; and hardens memory-update/export edge cases uncovered in on-prem data migration.
New Features
- TypeScript SDK framework integrations (
sdks/typescript/src/integrations/)- New
ai-sdk.ts: Vercel AI SDK integration exposing Memanto memories as
AI SDK-compatible tools/context. - New
mastra.ts: Mastra framework integration. - New
openai.ts: OpenAI SDK integration for wiring Memanto recall/remember
into OpenAI-based agents. - Shared
memory-types.tsmodule for consistent memory typing across
integrations; new peer dependencies (ai,zod,@ai-sdk/openai,
@mastra/core,openai); Node engine bumped to>=20. - Full test coverage:
test/integrations/{ai-sdk,mastra,openai}.test.ts. - README updated with on-prem (no-API-key) usage instructions.
- New
Security
-
Management auth required for agent lifecycle endpoints (
memanto/app/routes/auth_deps.py)- Agent create/list/delete/activate and
/api/v2/statuspreviously only
checked that the server had a configuredMOORCHEH_API_KEY, not that the
caller was authorized — with the defaultHOST=0.0.0.0bind, any network
peer could create agents, activate sessions, and obtain session tokens.
These endpoints now require either a matching management credential
(Authorization: Bearer/X-Api-Key) or a loopback client origin.
- Agent create/list/delete/activate and
-
Recall filter-token injection guard (
memanto/app/services/memory_read_service.py)memory_type,tag,status, and metadata key/value filters passed to
Moorcheh's keyword query syntax are now validated against a strict
[A-Za-z0-9_.-]+token pattern before being interpolated, preventing
query-syntax injection via crafted filter values.
-
Unique on-prem upload staging paths (
memanto/app/clients/onprem.py)- Uploaded files are now staged under a UUID-suffixed filename
({stem}-{uuid4}{suffix}) instead of the original name, preventing
same-named concurrent uploads from colliding/overwriting each other's
staged file.
- Uploaded files are now staged under a UUID-suffixed filename
Improvements
-
Event-loop blocking fixes (
memanto/app/ui/routes/ui_router.py,
memanto/app/services/session_service.py)restart_onprem_backendpreviously ran two blockingsubprocess.run()
calls (up to 360s combined) plus synchronoushttpx.get()/time.sleep()
directly inside anasync def, freezing the entire FastAPI event loop for
the whole restart window. Now wrapped inasyncio.to_thread/
httpx.AsyncClient/await asyncio.sleep.- The restart lock is now cancellation-safe: the actual restart runs as an
independent task guarded byasyncio.shield(), so a cancelled HTTP handler
(e.g. client timeout) can no longer release the lock whilemoorcheh down/upis still running, which previously let concurrent restarts
interleave subprocess calls against the same stack. end_sessionalways returnedmemories_created=0due to an unresolved
TODO; it now snapshots the live Moorcheh namespace document count
before/after ending the session and reports the delta (best-effort — falls
back to 0 if Moorcheh is unreachable).
-
Batch upload status normalization (
memanto/app/services/memory_write_service.py)- Batch memory writes now count
"ok"(in addition to"queued"/"success")
as a successful per-item status, and count"failed"case-insensitively —
on-prem batch uploads were previously miscounted as failed despite
succeeding.
- Batch memory writes now count
-
On-prem answer model omission (
memanto/app/services/conversation_memory_extraction_service.py)- Conversation extraction now omits
ai_modelwhen no on-prem LLM is
configured (falls back toget_active_llm_model), letting the server pick
its own default instead of erroring, matching the existinganswer
endpoint behavior.
- Conversation extraction now omits
-
memanto exportrefuses to overwrite a good cache on backend outage
(memanto/cli/client/{direct_client,sdk_client}.py)export_memory_mdpreviously swallowed every per-type recall failure into
an empty list and wrote it unconditionally — during a full backend outage
this silently wiped the cached export (and, viasync_memory_to_project,
the project'sMEMORY.md) even though nothing was actually forgotten. Now
raisesConnectionErrorwhen every memory type fails to recall (a
genuine "no memories of this type" still exports fine);sync_memory_to_project
falls back to the previous export ("stale-cache") when a refresh fails
and a prior export exists.
-
Memory-update metadata handling (
memanto/app/services/memory_write_service.py)update_memorynow preserves extra metadata fields from the existing
record (e.g. on-premoriginal_id) that aren't part of theMemoryRecord
schema — but explicitly excludes the trust fields removed on 2026-06-29
(superseded_by,supersedes,validated_at,validation_count,
contradiction_detected) so old on-prem records don't resurrect dead
schema on update.
-
OpenAPI/CI sync (
scripts/generate_openapi.py,.github/workflows/sdk-typescript.yml)generate_openapi.pynow pins a fallback version before importing the app
so the spec doesn't drift on every commit from the hatch-vcs-derived
version; CI updated to catch TypeScriptopenapi.jsondrift.
Tests
- New
tests/test_memory_read_filter_sanitization.py,tests/test_export_resilience.py,
and expandedtests/test_backend.py/tests/test_unit.py/tests/test_api.py
covering the filter-injection guard, stale-cache export fallback, batch
upload status normalization, and trust-field exclusion on update. - New
sdks/typescript/test/integrations/*.test.tsfor the three new SDK
integrations.
Full Changelog
Full Changelog: v0.2.6...v0.2.7