Files
mem0/mem0-plugin/scripts/on_user_prompt.sh
2026-03-25 14:45:59 -07:00

62 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Hook: UserPromptSubmit
#
# Fires on every user message. Searches mem0 for relevant memories
# and injects them into Claude's context before processing.
#
# Input: JSON on stdin with prompt, session_id, cwd, transcript_path
# Output: Matching memories as context text (exit 0)
#
# Skips search for very short prompts (< 20 chars) and when
# MEM0_API_KEY is not set. Uses a 3s timeout to minimize latency.
# Intentionally omit -e so the script always exits 0 even if
# curl or jq fail — must never block the user's prompt.
set -uo pipefail
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null || echo "")
# Skip trivial prompts — not worth a network call
if [ ${#PROMPT} -lt 20 ]; then
exit 0
fi
API_KEY="${MEM0_API_KEY:-}"
if [ -z "$API_KEY" ]; then
exit 0
fi
USER_ID="${MEM0_USER_ID:-${USER:-default}}"
# Build request body safely via jq to avoid injection
BODY=$(jq -n --arg query "$PROMPT" --arg user_id "$USER_ID" \
'{query: $query, filters: {user_id: $user_id}, top_k: 5}')
# Search mem0 for memories relevant to this prompt
RESPONSE=$(curl -s --max-time 3 \
-X POST "https://api.mem0.ai/v2/memories/search/" \
-H "Authorization: Token $API_KEY" \
-H "Content-Type: application/json" \
-d "$BODY" \
2>/dev/null || echo "")
if [ -z "$RESPONSE" ]; then
exit 0
fi
# Extract memories from response (API returns a flat array)
MEMORIES=$(echo "$RESPONSE" | jq -r '
if type == "array" then . else .results // [] end |
if length == 0 then empty else
"## Relevant memories from mem0\n\n" +
(map(select(.memory != null) | "- " + .memory) | join("\n"))
end
' 2>/dev/null || echo "")
if [ -n "$MEMORIES" ]; then
echo "$MEMORIES"
fi
exit 0