Commit Graph

8 Commits

Author SHA1 Message Date
Mgeeeek 8b36f7c50e fix(plugin): expire stale state captures + document plugin-update restart
Memory expiration + recency
  Hook-side captures (session_state in on_pre_compact.py and
  compact_summary in capture_compact_summary.py) now set
  expiration_date = today + 90 days. These types describe a single
  moment of project state and become stale clutter after a quarter.
  Durable types written by the agent (decision, anti_pattern,
  convention, user_preference, task_learning, environmental) stay
  unexpired by design -- a decision from a year ago is still a
  decision.

  Skill updated with two new sections:
    - "Expiration: high-churn vs durable" -- table mapping each
      metadata.type to whether it should carry an expiration_date.
    - "Recency filter on recall" -- agent should layer a
      created_at >= <90 days ago> filter on recall when the user
      asks about *current* state, and skip it when looking for
      durable facts.

Plugin-update / MCP reconnect
  When the plugin updates, the MCP server connection in the running
  client goes stale -- there's no in-process reconnection path from
  inside the plugin. Documenting the workaround is the realistic
  fix: README now has an "Updating the plugin" section explaining
  /restart (Claude Code), quit-and-relaunch (Cursor), restart
  (Codex). The auth header re-reads MEM0_API_KEY from the new
  shell, so users don't have to re-enter the key.
2026-05-08 21:39:28 +05:30
Mgeeeek 2946fc9da5 feat(plugin): coding-focused custom-category setup script
mem0 auto-tags every memory with one or more `categories` from a
project-level list. The default list is consumer-oriented (food,
hobbies, music, ...), which produces meaningless tags for code
workflows.

Per-request `custom_categories` is not supported on the managed API,
so the fix has to be a one-time project-level configuration. New
script `setup_coding_categories.py` does this:

  - Dry-run by default: prints current vs proposed taxonomy, exits.
  - `--apply` flag actually calls `project.update(custom_categories=...)`.
  - Falls back gracefully when mem0ai SDK isn't installed or
    MEM0_API_KEY is missing/invalid (friendly error, no stack trace).

Recommended taxonomy:
  architecture_decisions, anti_patterns, task_learnings,
  tooling_setup, bug_fixes, coding_conventions, user_preferences

Skill clarification: `metadata.type` (agent-applied explicit tag,
used in filters) and `categories` (platform-applied auto-tag, used
in dashboards) are complementary; agent should keep using
`metadata.type` and not try to set `categories` per-request.

README: section under Step 2 explaining how to run the script.
2026-05-08 21:30:42 +05:30
Mgeeeek 0fd7cb9c5a fix(plugin): preserve structure on PreCompact + capture compact summary
Two changes to the compaction flow:

PreCompact: agent stores its summary with infer=False
  on_pre_compact.sh now instructs the agent to call add_memory with
  infer=False. The agent has full conversation context and writes a
  structured summary; without infer=False the platform runs a second
  LLM extraction pass over that summary, losing structure and
  producing fragmented facts. With it, the structured text is
  preserved verbatim. Same guidance added to mem0-mcp/SKILL.md so
  the agent applies it to other already-extracted writes (decisions,
  anti-patterns, conventions).

SessionStart-compact: capture the platform-generated summary
  PreCompact fires BEFORE Claude Code generates its compact summary,
  so the summary is unreachable from that hook. SessionStart-compact
  fires AFTER, so a new background helper (capture_compact_summary.py)
  reads the transcript at that point, finds the isCompactSummary=true
  entry, and stores its content as a separate memory tagged
  metadata.type=compact_summary. The post-compaction bootstrap text
  now tells the agent to layer its recall queries across
  session_state (its own pre-compact summary), compact_summary (the
  platform's condensed view), and topical types like decision /
  anti_pattern.

Net effect: three complementary memory types from one session
boundary, none of which used to be filterable or even captured
correctly.
2026-05-08 21:13:00 +05:30
Mgeeeek ed15fc1386 fix(plugin): deterministic mem0 user_id resolution
Hooks previously fell back to $USER when MEM0_USER_ID wasn't set,
producing a different user_id on every machine for the same person.
Result: a single account with memories scattered across many user
buckets, none of which can see each other.

Resolution priority (same in bash and python):
  1. MEM0_USER_ID env var (explicit override)
  2. ~/.mem0/identity.json cache (pinned to MEM0_API_KEY fingerprint)
  3. Derived: "mem0-" + sha256(MEM0_API_KEY)[:12]
  4. Fallback: $USER, else "default"

Same MEM0_API_KEY across machines now yields the same user_id without
the user having to set MEM0_USER_ID by hand on every laptop.

Resolver shipped as two tiny files instead of a shared module:
  _identity.sh -- sourced by bash hooks, exports MEM0_RESOLVED_USER_ID
  _identity.py -- imported by on_pre_compact.py, exposes resolve_user_id()

Hook integration:
  on_user_prompt.sh -- sources resolver, USER_ID interpolated into rubric
  on_session_start.sh -- emits an "Active user_id: <X>" header before the
    bootstrap text, so the agent's MCP search_memories/add_memory calls
    use the same bucket the hooks write to (closes the agent-side half
    of the symptom)
  on_pre_compact.py -- replaces inline env lookup with resolve_user_id()

Existing memories under previous $USER values are not auto-migrated.
The cache file regenerates on key rotation (fingerprint mismatch).
2026-05-08 21:02:24 +05:30
Mgeeeek 8cb4f09ded fix(plugin): mem0-plugin hook cleanup
Six independent fixes that make hook behaviour deterministic, debuggable,
and free of silent footguns.

Persist session_id in stored memories
  on_pre_compact.py now extracts session_id from the hook input and writes
  it under metadata.session_id, enabling search-by-session.

Skip SessionStart bootstrap when MEM0_API_KEY is missing
  on_session_start.sh exits 0 early instead of emitting bootstrap text that
  instructs the agent to call mem0 MCP tools that would all fail without
  a key.

Tighten block_memory_write.sh regex
  The old `*/memory/*.md` pattern blocked legitimate paths like
  docs/memory/architecture.md. New pattern blocks `*/MEMORY.md` and
  `*/.claude/memory/*` only -- the actual surfaces we want to protect.

Opt-in debug logging via MEM0_DEBUG=1
  Each hook (bash + python) redirects stderr / adds a FileHandler to
  ~/.mem0/hooks.log when MEM0_DEBUG is set. No helper module, no
  rotation -- KISS. Default behaviour is unchanged.

Drop the duplicate PreCompact registration
  hooks.json and cursor-hooks.json had on_pre_compact.sh AND
  on_pre_compact.py registered on PreCompact, producing duplicate
  session-state writes. Drop the python entry. The python script stays
  alive -- on_stop.sh still spawns it as a session-end safety net.

CI nudge
  Adds a single comment line to pyproject.toml because the repo's
  ci.yml path filters exclude mem0-plugin/-only PRs but the
  build_mem0/build_embedchain status checks are required by branch
  protection. Track the proper fix (path-conditional CI) as a
  follow-up.
2026-05-07 21:53:49 +05:30
Gabriel Stein 58304fc939 refactor(plugin): hand mem0 search decisions to the agent (#4992)
Co-authored-by: Mgeeeek <ms8939@bennett.edu.in>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:41:39 +05:30
Gabriel Stein 30ce028a71 feat(mem0-plugin): add Codex lifecycle hooks via opt-in installer (#4917) 2026-04-27 22:59:35 +05:30
Gabriel Stein 3c2683c1b5 feat: add Mem0 plugin for Claude Code and Cursor (#4518) 2026-03-25 14:45:59 -07:00