refactor(mem0-plugin): improve hook scripts, config parsing, and skill definitions

Update git commit capture with better error handling, enhance user prompt hook,
extend config parser capabilities, and refine skill docs for dream, health,
mcp, pin, and stats skills.
This commit is contained in:
kartik-mem0
2026-05-22 14:23:06 +05:30
parent 6ab6ed58a8
commit 71a6696c87
8 changed files with 170 additions and 18 deletions
+2 -2
View File
@@ -75,8 +75,8 @@ For each group, identify the following:
Two memories are near-duplicates when they express the same fact or decision but
phrased differently (e.g., "Use PostgreSQL for auth" and "Auth DB is PostgreSQL").
Heuristics:
- Significant noun/keyword overlap in the memory text.
Heuristics — two memories are near-duplicates if **all** of these hold:
- Similarity threshold: estimated cosine similarity > 0.9 (use noun/keyword overlap as proxy — if >60% of significant nouns overlap, treat as >0.9 similarity).
- Same `metadata.type`.
- Neither memory is pinned (`metadata.pinned != true`).
+31 -1
View File
@@ -79,7 +79,9 @@ If any check fails, add a `## Troubleshooting` section with specific fix steps f
## Extended mode: Memory Quality Analysis
When invoked with `--deep` (e.g., `/mem0:health --deep`), run the standard 5 checks above **plus** a memory quality scan:
When invoked with `--deep` (e.g., `/mem0:health --deep`) or `--fix` (e.g., `/mem0:health --fix`), run the standard 5 checks above **plus** a memory quality scan.
`--fix` implies `--deep` and automatically applies safe fixes after showing the analysis (see bottom of this section).
### Quality Check 1: Duplicates
@@ -101,6 +103,15 @@ Stale candidates: <N>
[mem0:<id>] — session_state, 142d old
```
### Quality Check 2b: Low-confidence memories
Flag memories where `metadata.confidence` < 0.5 (regardless of age). Report separately from stale:
```
Low-confidence memories: <N>
[mem0:<id>] — confidence=0.3, "<content preview>"
```
### Quality Check 3: Contradictions
Within each `metadata.type` group, flag pairs that assert opposing facts about the same topic. Use semantic judgment — look for negation patterns, conflicting tool/framework choices, or reversed decisions.
@@ -131,3 +142,22 @@ Untagged/orphan memories: <N>
```
If all counts are 0: `Memory quality: clean. No duplicates, stale entries, or contradictions found.`
### Auto-fix mode (`--fix`)
When `--fix` is passed, apply these safe fixes automatically after displaying the quality summary:
1. **Orphans:** For each untagged memory, infer a `metadata.type` from content and call `update_memory` to set it. If inference is uncertain, skip.
2. **Stale `session_state`/`compact_summary` > 90d:** Delete them via `delete_memory`. These are ephemeral by design.
3. **Duplicates:** Do NOT auto-merge — print "Run `/mem0:dream` to merge duplicates" instead.
4. **Contradictions:** Do NOT auto-resolve — print "Run `/mem0:dream` to resolve contradictions" instead.
5. **Low-confidence < 0.3 AND > 30d old:** Delete them via `delete_memory`.
Print a summary of actions taken:
```
## Auto-fix Results
Deleted: <N> stale, <N> low-confidence
Retagged: <N> orphans
Skipped: <N> duplicates (use /mem0:dream), <N> contradictions (use /mem0:dream)
```
+19 -2
View File
@@ -272,7 +272,23 @@ add_memory(
)
```
**Filtering note:** The mem0 v2 filter API does not yet support `array-contains` predicates. You cannot filter by `metadata.files` at search time. To work around this, always embed the bare filenames (and important path segments) in the memory content text itself — the vector search will then surface them on a filename query. The `files` array in metadata is still written for future compatibility once array-contains filtering is available.
**Filtering by files:** Use the `contains` operator to filter by `metadata.files` at search time:
```python
search_memories(
query="auth middleware",
filters={
"AND": [
{"user_id": "<id>"},
{"app_id": "<project_id>"},
{"metadata.files": {"contains": "src/middleware/auth.ts"}},
]
},
limit=5,
)
```
Also embed bare filenames in the memory content text as a fallback — the vector search will surface them even if the structured filter misses.
### Access counter: track memory usage
@@ -289,10 +305,11 @@ import datetime
current_meta["access_count"] = current_meta.get("access_count", 0) + 1
current_meta["last_accessed"] = datetime.datetime.now(datetime.timezone.utc).isoformat()
# 3. Update with preserved content
# 3. Update with preserved content and bumped metadata
update_memory(
memory_id=<id>,
data=current_text, # preserve original text — required parameter
metadata=current_meta, # pass updated access_count and last_accessed
)
```
+14 -5
View File
@@ -38,10 +38,15 @@ This is required because `update_memory` replaces the full memory — a metadata
Call `update_memory` with:
- `memory_id=<selected_id>`
- `data=<original_text>` (preserve the existing content)
- `metadata=` merge `original_metadata` with `{"pinned": true}`
The platform will retain the existing metadata and content. Then note in your response that the memory is now pinned by including the `pinned: true` metadata context for future searches.
Example:
```python
updated_meta = {**original_metadata, "pinned": True}
update_memory(memory_id=<selected_id>, data=<original_text>, metadata=updated_meta)
```
**Important:** `update_memory` requires the `data` (text) parameter. Passing only metadata may error or wipe content. Always read first, then update with the full text.
**Important:** `update_memory` requires the `data` (text) parameter. Passing only metadata may error or wipe content. Always read first, then update with the full text and explicit metadata.
### Step 4: Confirm
@@ -53,7 +58,11 @@ Pinned memories surface first when relevant to a search.
### Unpin
If the user says "unpin" or the memory is already pinned:
1. Call `get_memory` to read current content.
2. Call `update_memory` with `data=<original_text>` to preserve content.
If the user says "unpin" or `/mem0:unpin`:
1. Call `get_memory` to read current content and metadata.
2. Set `metadata.pinned = false` explicitly:
```python
updated_meta = {**original_metadata, "pinned": False}
update_memory(memory_id=<id>, data=<original_text>, metadata=updated_meta)
```
3. Print: `Unpinned: "<content>..."`
+14
View File
@@ -63,6 +63,18 @@ Print a compact dashboard with an ASCII histogram for category distribution:
user_preference ██░░░░░░░░░░░░░░ 3
session_state █░░░░░░░░░░░░░░░ 2
By age:
< 7 days ████████████████ 5
7–30 days ██████████░░░░░░ 12
30–90 days ████░░░░░░░░░░░░ 10
> 90 days ██░░░░░░░░░░░░░░ 8
By access count:
Never accessed ████████████████ 18
1–5 accesses ████████░░░░░░░░ 10
6–20 accesses ████░░░░░░░░░░░░ 4
20+ accesses █░░░░░░░░░░░░░░░ 3
Oldest memory: <date>
Newest memory: <date>
@@ -78,5 +90,7 @@ Print a compact dashboard with an ASCII histogram for category distribution:
- Use `█` for filled and `░` for empty. Right-align the count number.
- Sort categories by count descending. Omit categories with 0 memories.
- If only 1-2 categories exist, still show the histogram — it provides visual context.
- **Age buckets:** Compute from `created_at`. Buckets: <7d, 7–30d, 30–90d, >90d.
- **Access count buckets:** Read `metadata.access_count` (default 0 if absent). Buckets: 0, 1–5, 6–20, 20+.
Skip any section with zero data.