Skip to content

v0.2.21

Latest

Choose a tag to compare

@het0814 het0814 released this 09 Sep 20:06
0c9e816

Release Notes for v0.2.21

This release makes MEMANTO aware of which AI tool is talking to it. A new client-identity layer and append-only activity log record the tool and MEMANTO session behind every remember, recall, and answer, and the Connections page grows a live context mesh and session timeline built on top of them. Alongside it, recall/answer gain a --tool flag so agents can name themselves on reads, the MCP server attributes tool calls to its handshake client, connect templates embed each agent's own slug, and packaging moves to PyPI Trusted Publishing with a trimmed sdist.

New Features

  • Tool identity and activity tracking (memanto/app/utils/client_identity.py, memanto/app/services/activity_service.py)
    • New client_identity module resolves the calling tool from, in order: MEMANTO_CLIENT / X-Memanto-Client, an MCP initialize handshake's clientInfo, or environment markers specific to a single tool (CLAUDECODE, CURSOR_TRACE_ID, CODEX_HOME, WINDSURF_HOME, GEMINI_CLI, GOOSE_PROVIDER, OPENCODE, CLINE_SESSION_ID, CONTINUE_GLOBAL_DIR, PI_AGENT, ANTIGRAVITY_HOME). Detection is conservative — an unidentified caller stays unknown rather than being guessed at.
    • Free-text client names are folded onto registry slugs via an alias table, so a Cursor MCP write and a Cursor CLI write land on the same connection instead of two lookalike rows.
    • New ActivityService writes one O_APPEND JSON line per memory operation (remember, recall, answer) recording tool, agent, MEMANTO session, and count. Logging is best-effort and never raises — a telemetry line is never worth failing a durable write over. Files older than RETENTION_DAYS (30) are pruned once per process.
    • Liveness is derived on read: a tool that touched memory within LIVE_WINDOW_SECONDS (300) counts as connected now.
    • Identity is bound per-request via a ContextVar (not a module global) so concurrent API requests cannot read each other's attribution.
  • Session and liveness API (memanto/app/ui/routes/ui_router.py, memanto/app/main.py)
    • GET /api/ui/sessions returns MEMANTO sessions with the tools that took part, per-tool liveness, and a live_count. Complements /api/ui/connections, which reports where MEMANTO is installed; this reports what has actually been running.
    • GET /api/ui/sessions/{session_id} returns one session's summary plus its full event timeline, 404-ing on an unknown id.
    • Both clamp the days window to ACTIVITY_MAX_DAYS (30), matching the log's own retention.
    • New attribute_calling_tool HTTP middleware binds X-Memanto-Client (and optional X-Memanto-Project) to the request. An anonymous HTTP call is bound to UNKNOWN rather than falling through to environment detection — otherwise an editor that started memanto server would be credited with every request it never made.
    • Both endpoints stay local-only behind _require_local.
  • Live context mesh and session list in the UI (memanto/app/ui/static/index.html)
    • The Connections page now renders a live context mesh: a MEMANTO hub with one node per tool active in the last 7 days, live nodes and edges highlighted, and a live-count readout. The hub animates only when a tool is genuinely live, and respects prefers-reduced-motion.
    • A collapsible Sessions (last 7 days) list shows each MEMANTO session, its status, and the tools that took part, expanding into a per-session event timeline.
    • Live badges decorate the existing connection cards, and the mesh polls on an interval so a stale page stops claiming a tool is connected.
  • --tool flag on recall and answer (memanto/cli/commands/memory.py)
    • Reads carry no --source, so a new hidden --tool option lets an agent name itself exactly instead of relying on environment sniffing — the only way tools that leave no distinctive marker can be attributed at all. Hidden from --help because a human running memanto by hand has nothing to declare.
    • remember --source now defaults to the detected calling tool instead of the hardcoded "user"; an explicit --source always wins, and a bare terminal still records user.
    • Sources that name a person (user, agent, human) fall through to environment detection rather than putting "user" on the connected-tools diagram.

Improvements

  • MCP tool calls are attributed to the handshake client (integrations/mcp/memanto_mcp/tools.py)
    • New _attributed(ctx) context manager binds the MCP clientInfo name for the duration of a tool call. The MCP server runs as its own process, so its environment says nothing about the driving editor — this is the only way a recall through MCP gets credited to Cursor rather than to an anonymous caller.
    • recall, recall_recent, recall_as_of, recall_changed_since, and answer now accept ctx; remember and batch_remember were rewrapped to run their whole body under the attribution scope.
  • Activity logging wired through every read and write path (memanto/app/services/memory_read_service.py, memanto/app/services/memory_write_service.py, memanto/cli/client/direct_client.py, memanto/cli/client/sdk_client.py, memanto/app/routes/auth_deps.py)
    • Semantic recall, --recent, --as-of, --changed-since, answer, single remember, and batch_remember all emit an activity event.
    • get_current_session and the CLI clients' _get_validated_session_for_agent bind the session id, since the memory services below them only ever receive an agent_id.
    • The CLI answer RAG path calls Moorcheh directly rather than through MemoryReadService, so it logs its own event — otherwise answer would be the one memory operation leaving no trace.
    • Generated instructions and SKILL.md now interpolate the connected agent's real slug into --source "<slug>" and --tool "<slug>" examples, instead of a generic <your_agent_name> placeholder. _install_skill passes agent.name through to get_skill_content.
    • Recall/answer examples and the recall trigger matrix were updated to always pass --tool, with a new anti-pattern entry explaining why reads need it.
  • Packaging and publishing (pyproject.toml, .github/workflows/publish.yml)
    • PyPI publishing moved to Trusted Publishing: PYPI_API_TOKEN is gone, id-token: write added, and the workflow's OIDC identity is what PyPI authenticates — the action attaches PEP 740 provenance attestations by default.
    • New [tool.hatch.build.targets.sdist] include list trims the sdist to memanto/, tests/, and build metadata; assets/, examples/, integrations/, docs/, and sdks/ (whose demo GIFs and architecture PNGs dominated the archive) are excluded.
    • Classifier bumped from 3 - Alpha to 5 - Production/Stable, Python 3.13 added, and project URLs repointed to memanto.ai / docs.memanto.ai.

Tests

  • tests/test_tool_sessions.py — new 500-line suite covering environment detection precedence, alias normalization, append-only event writing, failure-swallowing on broken storage, session grouping, liveness expiry, quiet-but-unexpired and zero-activity sessions, dead-session flooding, torn-line recovery, session timelines, HTTP header attribution, anonymous-caller safety, and the --tool flag on recall/answer.
  • tests/test_cli.pyremember attributes the write to the calling tool, and an explicit --source overrides detection.
  • tests/test_connect_engine.py — each connected agent gets its own slug in both its instructions and its installed SKILL.md.
  • tests/test_remaining_ui_auth.py — both new session endpoints are rejected from remote callers.
  • tests/conftest.py — new autouse fixture resets the bound client identity and session between tests, so one test's --tool cannot decide the attribution of every test after it.

Full Changelog

Full Changelog: v0.2.20...v0.2.21