claude-mem-lite 2.33.2 → 2.33.4

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.
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "claude-mem-lite",
13
- "version": "2.33.2",
13
+ "version": "2.33.4",
14
14
  "source": "./",
15
15
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall"
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.33.2",
3
+ "version": "2.33.4",
4
4
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/hook.mjs CHANGED
@@ -109,7 +109,16 @@ if (!event) process.exit(0);
109
109
 
110
110
  // ─── Episode Flush ──────────────────────────────────────────────────────────
111
111
 
112
- function flushEpisode(episode) {
112
+ // hookEventName defaults to 'PostToolUse' since that's the most common caller.
113
+ // Stop / SessionStart callers MUST pass their own event name — CC rejects
114
+ // hook output whose hookEventName doesn't match the triggering event
115
+ // (regression introduced in v2.33.1's structured receipt, fixed in v2.33.3).
116
+ // v2.33.4: CC's Stop-event schema does NOT accept hookSpecificOutput at all —
117
+ // only PreToolUse / UserPromptSubmit / PostToolUse / SessionStart carry
118
+ // additionalContext. On Stop we flush the episode to DB but skip the JSON
119
+ // receipt entirely; emitting it triggers "Invalid input" schema rejection.
120
+ const RECEIPT_EVENTS = new Set(['PostToolUse', 'SessionStart', 'UserPromptSubmit']);
121
+ function flushEpisode(episode, hookEventName = 'PostToolUse') {
113
122
  if (!episode || episode.entries.length === 0) return;
114
123
 
115
124
  // Collect Read file paths tracked by post-tool-use.sh
@@ -153,32 +162,35 @@ function flushEpisode(episode) {
153
162
  // and the legacy error→fix nudge consolidates here. PostToolUse JSON with
154
163
  // hookSpecificOutput.additionalContext reliably renders across CC variants;
155
164
  // the old plain-text stdout write was invisible on some variants.
156
- try {
157
- const entries = episode.entries || [];
158
- const hasError = entries.some(e => e.isError);
159
- const hasEdit = entries.some(e => EDIT_TOOLS.has(e.tool));
160
- const toolCounts = {};
161
- for (const e of entries) toolCounts[e.tool] = (toolCounts[e.tool] || 0) + 1;
162
- const toolSummary = Object.entries(toolCounts)
163
- .sort((a, b) => b[1] - a[1])
164
- .slice(0, 3)
165
- .map(([t, n]) => `${t}×${n}`)
166
- .join(', ');
167
- const lines = [`[mem] episode flushed: ${entries.length} entries (${toolSummary})`];
168
- if (hasError && hasEdit && entries.length >= 3) {
169
- const editFiles = entries.filter(e => EDIT_TOOLS.has(e.tool)).flatMap(e => e.files || []);
170
- const uniqueFiles = [...new Set(editFiles)].slice(0, 3);
171
- const filesHint = uniqueFiles.length > 0 ? ` (${uniqueFiles.join(', ')})` : '';
172
- lines.push(`[mem] 💡 error→fix pattern${filesHint} — consider: mem_save(type="bugfix", lesson_learned="<root cause + fix>")`);
173
- }
174
- process.stdout.write(JSON.stringify({
175
- suppressOutput: true,
176
- hookSpecificOutput: {
177
- hookEventName: 'PostToolUse',
178
- additionalContext: lines.join('\n'),
179
- },
180
- }));
181
- } catch { /* never block on receipt */ }
165
+ // v2.33.4: Stop event rejects hookSpecificOutput entirely — skip receipt.
166
+ if (RECEIPT_EVENTS.has(hookEventName)) {
167
+ try {
168
+ const entries = episode.entries || [];
169
+ const hasError = entries.some(e => e.isError);
170
+ const hasEdit = entries.some(e => EDIT_TOOLS.has(e.tool));
171
+ const toolCounts = {};
172
+ for (const e of entries) toolCounts[e.tool] = (toolCounts[e.tool] || 0) + 1;
173
+ const toolSummary = Object.entries(toolCounts)
174
+ .sort((a, b) => b[1] - a[1])
175
+ .slice(0, 3)
176
+ .map(([t, n]) => `${t}×${n}`)
177
+ .join(', ');
178
+ const lines = [`[mem] episode flushed: ${entries.length} entries (${toolSummary})`];
179
+ if (hasError && hasEdit && entries.length >= 3) {
180
+ const editFiles = entries.filter(e => EDIT_TOOLS.has(e.tool)).flatMap(e => e.files || []);
181
+ const uniqueFiles = [...new Set(editFiles)].slice(0, 3);
182
+ const filesHint = uniqueFiles.length > 0 ? ` (${uniqueFiles.join(', ')})` : '';
183
+ lines.push(`[mem] 💡 error→fix pattern${filesHint} — consider: mem_save(type="bugfix", lesson_learned="<root cause + fix>")`);
184
+ }
185
+ process.stdout.write(JSON.stringify({
186
+ suppressOutput: true,
187
+ hookSpecificOutput: {
188
+ hookEventName,
189
+ additionalContext: lines.join('\n'),
190
+ },
191
+ }));
192
+ } catch { /* never block on receipt */ }
193
+ }
182
194
  } else {
183
195
  try { unlinkSync(flushFile); } catch {}
184
196
  }
@@ -356,7 +368,7 @@ async function handleStop() {
356
368
  try {
357
369
  const episode = readEpisode();
358
370
  if (episode) {
359
- flushEpisode(episode);
371
+ flushEpisode(episode, 'Stop');
360
372
  }
361
373
  } finally {
362
374
  releaseLock();
@@ -509,7 +521,7 @@ async function handleSessionStart() {
509
521
  try {
510
522
  const prevEpisode = readEpisode();
511
523
  if (prevEpisode && prevEpisode.entries && prevEpisode.entries.length > 0) {
512
- flushEpisode(prevEpisode);
524
+ flushEpisode(prevEpisode, 'SessionStart');
513
525
  }
514
526
  } finally {
515
527
  releaseLock();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.33.2",
3
+ "version": "2.33.4",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {