@hir4ta/mneme 0.24.2 → 0.24.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mneme",
3
3
  "description": "A plugin that provides long-term memory for Claude Code. It automatically saves context lost during auto-compact, offering features for session restoration, recording technical decisions, and learning developer patterns.",
4
- "version": "0.24.2",
4
+ "version": "0.24.3",
5
5
  "author": {
6
6
  "name": "hir4ta"
7
7
  },
package/README.ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mneme
2
2
 
3
- ![Version](https://img.shields.io/badge/version-0.24.2-blue)
3
+ ![Version](https://img.shields.io/badge/version-0.24.3-blue)
4
4
  ![Node.js](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40hir4ta%2Fmneme)](https://www.npmjs.com/package/@hir4ta/mneme)
6
6
  [![MIT License](https://img.shields.io/npm/l/%40hir4ta%2Fmneme)](https://github.com/hir4ta/mneme/blob/main/LICENSE)
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mneme
2
2
 
3
- ![Version](https://img.shields.io/badge/version-0.24.2-blue)
3
+ ![Version](https://img.shields.io/badge/version-0.24.3-blue)
4
4
  ![Node.js](https://img.shields.io/badge/node-%3E%3D22.5.0-brightgreen)
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40hir4ta%2Fmneme)](https://www.npmjs.com/package/@hir4ta/mneme)
6
6
  [![MIT License](https://img.shields.io/npm/l/%40hir4ta%2Fmneme)](https://github.com/hir4ta/mneme/blob/main/LICENSE)
package/dist/server.js CHANGED
@@ -4493,7 +4493,7 @@ misc.get("/project", (c) => {
4493
4493
  }
4494
4494
  } catch {
4495
4495
  }
4496
- const version = "0.24.2";
4496
+ const version = "0.24.3";
4497
4497
  return c.json({
4498
4498
  name: projectName,
4499
4499
  path: projectRoot,
@@ -4,8 +4,9 @@
4
4
  #
5
5
  # Purpose: Search mneme for relevant context and approved rules,
6
6
  # inject as additionalContext using shared search-core logic.
7
+ # Also injects Claude Session ID (workaround for anthropics/claude-code#16538).
7
8
  #
8
- # Input (stdin): JSON with prompt, cwd
9
+ # Input (stdin): JSON with prompt, session_id, cwd
9
10
  # Output (stdout): JSON with hookSpecificOutput.additionalContext (if matches found)
10
11
  #
11
12
 
@@ -23,13 +24,16 @@ fi
23
24
 
24
25
  prompt=$(echo "$input_json" | jq -r ".prompt // empty" 2>/dev/null || echo "")
25
26
  cwd=$(echo "$input_json" | jq -r ".cwd // empty" 2>/dev/null || echo "")
27
+ session_id=$(echo "$input_json" | jq -r ".session_id // empty" 2>/dev/null || echo "")
26
28
 
29
+ # Determine if search should run (session ID is always injected regardless)
30
+ run_search=true
27
31
  if [ -z "$prompt" ] || [ ${#prompt} -lt 10 ]; then
28
- exit 0
32
+ run_search=false
29
33
  fi
30
34
 
31
35
  if [[ "$prompt" == /mneme* ]]; then
32
- exit 0
36
+ run_search=false
33
37
  fi
34
38
 
35
39
  if [ -z "$cwd" ]; then
@@ -37,104 +41,114 @@ if [ -z "$cwd" ]; then
37
41
  fi
38
42
  cwd=$(cd "$cwd" 2>/dev/null && pwd || echo "$cwd")
39
43
 
40
- # Cap very large prompts to avoid overly expensive search
41
- if [ ${#prompt} -gt 4000 ]; then
42
- prompt="${prompt:0:4000}"
43
- fi
44
-
45
44
  if ! validate_mneme "$cwd"; then
46
45
  exit 0
47
46
  fi
48
47
 
49
- PLUGIN_ROOT="$(get_plugin_root)"
50
-
51
- search_script=$(find_script "$PLUGIN_ROOT" "prompt-search")
52
- if [ -z "$search_script" ]; then
53
- exit 0
54
- fi
55
-
56
- # Detect changed files for file-based session recommendation
57
- changed_files=""
58
- if command -v git >/dev/null 2>&1 && git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
59
- changed_files=$(cd "$cwd" && {
60
- git diff --name-only HEAD 2>/dev/null
61
- git diff --name-only --cached 2>/dev/null
62
- } | sort -u | head -20 | paste -sd "," - 2>/dev/null || echo "")
63
- fi
64
-
65
- search_output=$(invoke_node "$search_script" \
66
- --query "$prompt" --project "$cwd" --limit 5 \
67
- ${changed_files:+--files "$changed_files"} 2>/dev/null || echo "")
48
+ # --- Search (skipped for short prompts and /mneme commands) ---
49
+ context_message=""
50
+ rules_message=""
68
51
 
69
- if [ -z "$search_output" ]; then
70
- exit 0
71
- fi
52
+ if [ "$run_search" = true ]; then
53
+ # Cap very large prompts to avoid overly expensive search
54
+ if [ ${#prompt} -gt 4000 ]; then
55
+ prompt="${prompt:0:4000}"
56
+ fi
72
57
 
73
- success=$(echo "$search_output" | jq -r ".success // false" 2>/dev/null || echo "false")
74
- if [ "$success" != "true" ]; then
75
- exit 0
76
- fi
58
+ PLUGIN_ROOT="$(get_plugin_root)"
59
+
60
+ search_script=$(find_script "$PLUGIN_ROOT" "prompt-search")
61
+ if [ -n "$search_script" ]; then
62
+ # Detect changed files for file-based session recommendation
63
+ changed_files=""
64
+ if command -v git >/dev/null 2>&1 && git -C "$cwd" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
65
+ changed_files=$(cd "$cwd" && {
66
+ git diff --name-only HEAD 2>/dev/null
67
+ git diff --name-only --cached 2>/dev/null
68
+ } | sort -u | head -20 | paste -sd "," - 2>/dev/null || echo "")
69
+ fi
77
70
 
78
- # Format session/interaction context (existing behavior)
79
- context_message=""
80
- context_lines=$(echo "$search_output" | jq -r '
81
- .results
82
- | map(select(.score >= 3 and (.type == "session" or .type == "unit")))
83
- | .[:3]
84
- | map("[\(.type):\(.id)] \(.title) | match: \((.matchedFields // []) | join(","))")
85
- | join("\n")
86
- ')
87
-
88
- # Format file-based session recommendations
89
- file_rec_lines=$(echo "$search_output" | jq -r '
90
- .fileRecommendations // []
91
- | .[:3]
92
- | map("[session:\(.sessionId)] \(.title) | files: \(.matchedFiles | join(", "))")
93
- | join("\n")
94
- ')
95
-
96
- if [ -n "$context_lines" ] && [ "$context_lines" != "null" ] || \
97
- [ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
98
- context_parts=""
99
- if [ -n "$context_lines" ] && [ "$context_lines" != "null" ]; then
100
- context_parts="Related context found (sessions/units):
71
+ search_output=$(invoke_node "$search_script" \
72
+ --query "$prompt" --project "$cwd" --limit 5 \
73
+ ${changed_files:+--files "$changed_files"} 2>/dev/null || echo "")
74
+
75
+ if [ -n "$search_output" ]; then
76
+ success=$(echo "$search_output" | jq -r ".success // false" 2>/dev/null || echo "false")
77
+ if [ "$success" = "true" ]; then
78
+ # Format session/interaction context
79
+ context_lines=$(echo "$search_output" | jq -r '
80
+ .results
81
+ | map(select(.score >= 3 and (.type == "session" or .type == "unit")))
82
+ | .[:3]
83
+ | map("[\(.type):\(.id)] \(.title) | match: \((.matchedFields // []) | join(","))")
84
+ | join("\n")
85
+ ')
86
+
87
+ # Format file-based session recommendations
88
+ file_rec_lines=$(echo "$search_output" | jq -r '
89
+ .fileRecommendations // []
90
+ | .[:3]
91
+ | map("[session:\(.sessionId)] \(.title) | files: \(.matchedFiles | join(", "))")
92
+ | join("\n")
93
+ ')
94
+
95
+ if [ -n "$context_lines" ] && [ "$context_lines" != "null" ] || \
96
+ [ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
97
+ context_parts=""
98
+ if [ -n "$context_lines" ] && [ "$context_lines" != "null" ]; then
99
+ context_parts="Related context found (sessions/units):
101
100
  ${context_lines}"
102
- fi
103
- if [ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
104
- if [ -n "$context_parts" ]; then
105
- context_parts="${context_parts}
101
+ fi
102
+ if [ -n "$file_rec_lines" ] && [ "$file_rec_lines" != "null" ]; then
103
+ if [ -n "$context_parts" ]; then
104
+ context_parts="${context_parts}
106
105
  "
107
- fi
108
- context_parts="${context_parts}Related sessions (editing same files):
106
+ fi
107
+ context_parts="${context_parts}Related sessions (editing same files):
109
108
  ${file_rec_lines}"
110
- fi
111
- context_message="<mneme-context>
109
+ fi
110
+ context_message="<mneme-context>
112
111
  ${context_parts}
113
112
  To explore deeper: use /mneme:search with specific technical terms, error messages, or file paths.
114
113
  </mneme-context>"
115
- fi
116
-
117
- # Format approved rules
118
- rules_message=""
119
- rules_lines=$(echo "$search_output" | jq -r '
120
- .rules // []
121
- | map(select(.score >= 2))
122
- | .[:5]
123
- | map("[\(.sourceType):\(.id)] (\(.priority // "—")) \(.text)")
124
- | join("\n")
125
- ')
126
-
127
- if [ -n "$rules_lines" ] && [ "$rules_lines" != "null" ]; then
128
- rules_message="<mneme-rules>
114
+ fi
115
+
116
+ # Format approved rules
117
+ rules_lines=$(echo "$search_output" | jq -r '
118
+ .rules // []
119
+ | map(select(.score >= 2))
120
+ | .[:5]
121
+ | map("[\(.sourceType):\(.id)] (\(.priority // "—")) \(.text)")
122
+ | join("\n")
123
+ ')
124
+
125
+ if [ -n "$rules_lines" ] && [ "$rules_lines" != "null" ]; then
126
+ rules_message="<mneme-rules>
129
127
  Approved development rules (apply during this response):
130
128
  ${rules_lines}
131
129
  </mneme-rules>"
130
+ fi
131
+ fi
132
+ fi
133
+ fi
132
134
  fi
133
135
 
134
- # Combine both sections
136
+ # --- Assemble full context ---
135
137
  full_context=""
138
+
139
+ # Session ID injection (workaround for anthropics/claude-code#16538:
140
+ # Plugin SessionStart hooks don't surface additionalContext to Claude)
141
+ if [ -n "$session_id" ]; then
142
+ full_context="**Claude Session ID:** ${session_id}"
143
+ fi
144
+
136
145
  if [ -n "$context_message" ]; then
137
- full_context="$context_message"
146
+ if [ -n "$full_context" ]; then
147
+ full_context="${full_context}
148
+ ${context_message}"
149
+ else
150
+ full_context="$context_message"
151
+ fi
138
152
  fi
139
153
  if [ -n "$rules_message" ]; then
140
154
  if [ -n "$full_context" ]; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hir4ta/mneme",
3
- "version": "0.24.2",
3
+ "version": "0.24.3",
4
4
  "description": "Long-term memory plugin for Claude Code - automated session saving, recording technical decisions, and web dashboard",
5
5
  "keywords": [
6
6
  "claude",
@@ -45,7 +45,7 @@ Always render missing required fields as blocking errors before write.
45
45
 
46
46
  **STOP. Before doing ANYTHING else, find the Claude Session ID.**
47
47
 
48
- Scan upward in this conversation for the SessionStart context block. It contains a line matching this exact format:
48
+ The UserPromptSubmit hook injects the session ID into every prompt's context. Look for this exact line in the system-reminder messages above:
49
49
 
50
50
  ```
51
51
  **Claude Session ID:** <UUID>
@@ -54,8 +54,8 @@ Scan upward in this conversation for the SessionStart context block. It contains
54
54
  Copy the full UUID value (36 characters, e.g. `a1b2c3d4-e5f6-7890-abcd-ef1234567890`).
55
55
 
56
56
  <required>
57
- - The Claude Session ID is ALREADY in this conversation — injected by the session-start hook at the very beginning
58
- - Search for the literal text `**Claude Session ID:**` in the messages above
57
+ - The Claude Session ID is ALREADY in this conversation — injected by the UserPromptSubmit hook on every prompt
58
+ - Search for the literal text `**Claude Session ID:**` in system-reminder messages above
59
59
  - Copy the full 36-character UUID that follows it
60
60
  - Do NOT run Bash, Glob, Grep, or any other tool to discover the session ID
61
61
  - Do NOT call `mneme_list_sessions` to find it (that is only for the fallback below)