memorix 0.9.6 → 0.9.8
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.
- package/CHANGELOG.md +14 -0
- package/dist/cli/index.js +42 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.9.8] — 2026-02-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Claude Code hooks installed to wrong file** — Hooks were written to `.github/hooks/memorix.json` but Claude Code reads from `.claude/settings.local.json` (project-level) or `~/.claude/settings.json` (global). Now correctly writes to `.claude/settings.local.json` for project-level installation.
|
|
9
|
+
- **Hooks merge overwrites existing settings** — Shallow spread `{...existing, ...generated}` would overwrite the entire `hooks` key, destroying user's other hook configurations. Now deep-merges the `hooks` object so existing hooks from other tools are preserved.
|
|
10
|
+
|
|
11
|
+
## [0.9.7] — 2026-02-25
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- **Claude Code hooks never triggering auto-memory** — Claude Code sends `hook_event_name` (snake_case) but the normalizer expected `hookEventName` (camelCase). This caused **every event** (SessionStart, UserPromptSubmit, PostToolUse, PreCompact, Stop) to be misidentified as `post_tool`, breaking event routing, prompt extraction, memory injection, and session tracking. Also fixed `session_id` → `sessionId` and `tool_response` → `toolResult` field mappings.
|
|
15
|
+
- **Empty content extraction from Claude Code tool events** — `extractContent()` now unpacks `toolInput` fields (Bash commands, Write file content, etc.) when no other content is available. Previously tool events produced empty or near-empty content strings.
|
|
16
|
+
- **User prompts silently dropped** — `MIN_STORE_LENGTH=100` was too high for typical user prompts. Added `MIN_PROMPT_LENGTH=20` specifically for `user_prompt` events.
|
|
17
|
+
- **Post-tool events too aggressively filtered** — Tool events with substantial content (>200 chars) are now stored even without keyword pattern matches.
|
|
18
|
+
|
|
5
19
|
## [0.9.6] — 2026-02-25
|
|
6
20
|
|
|
7
21
|
### Fixed
|
package/dist/cli/index.js
CHANGED
|
@@ -3823,6 +3823,7 @@ ${resolveHookCommand()} hook
|
|
|
3823
3823
|
function getProjectConfigPath(agent, projectRoot) {
|
|
3824
3824
|
switch (agent) {
|
|
3825
3825
|
case "claude":
|
|
3826
|
+
return path6.join(projectRoot, ".claude", "settings.local.json");
|
|
3826
3827
|
case "copilot":
|
|
3827
3828
|
return path6.join(projectRoot, ".github", "hooks", "memorix.json");
|
|
3828
3829
|
case "windsurf":
|
|
@@ -3930,10 +3931,12 @@ async function installHooks(agent, projectRoot, global = false) {
|
|
|
3930
3931
|
existing = JSON.parse(content);
|
|
3931
3932
|
} catch {
|
|
3932
3933
|
}
|
|
3933
|
-
const
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3934
|
+
const gen = generated;
|
|
3935
|
+
const merged = { ...existing };
|
|
3936
|
+
if (gen.hooks && typeof gen.hooks === "object") {
|
|
3937
|
+
const existingHooks = existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {};
|
|
3938
|
+
merged.hooks = { ...existingHooks, ...gen.hooks };
|
|
3939
|
+
}
|
|
3937
3940
|
await fs4.writeFile(configPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
3938
3941
|
}
|
|
3939
3942
|
const events = [];
|
|
@@ -6894,9 +6897,8 @@ var init_sync = __esm({
|
|
|
6894
6897
|
function detectAgent(payload) {
|
|
6895
6898
|
if ("agent_action_name" in payload) return "windsurf";
|
|
6896
6899
|
if ("hook_event_name" in payload && "conversation_id" in payload) return "cursor";
|
|
6897
|
-
if ("
|
|
6898
|
-
|
|
6899
|
-
}
|
|
6900
|
+
if ("hook_event_name" in payload) return "claude";
|
|
6901
|
+
if ("hookEventName" in payload) return "copilot";
|
|
6900
6902
|
if ("event_type" in payload) return "kiro";
|
|
6901
6903
|
if ("hook_type" in payload) return "codex";
|
|
6902
6904
|
return "claude";
|
|
@@ -6907,8 +6909,9 @@ function extractEventName(payload, agent) {
|
|
|
6907
6909
|
return payload.agent_action_name ?? "";
|
|
6908
6910
|
case "cursor":
|
|
6909
6911
|
return payload.hook_event_name ?? "";
|
|
6910
|
-
case "copilot":
|
|
6911
6912
|
case "claude":
|
|
6913
|
+
return payload.hook_event_name ?? payload.hookEventName ?? "";
|
|
6914
|
+
case "copilot":
|
|
6912
6915
|
return payload.hookEventName ?? "";
|
|
6913
6916
|
case "kiro":
|
|
6914
6917
|
return payload.event_type ?? "";
|
|
@@ -6920,7 +6923,7 @@ function extractEventName(payload, agent) {
|
|
|
6920
6923
|
}
|
|
6921
6924
|
function normalizeClaude(payload, event) {
|
|
6922
6925
|
const result = {
|
|
6923
|
-
sessionId: payload.sessionId ?? "",
|
|
6926
|
+
sessionId: payload.session_id ?? payload.sessionId ?? "",
|
|
6924
6927
|
cwd: payload.cwd ?? "",
|
|
6925
6928
|
transcriptPath: payload.transcript_path
|
|
6926
6929
|
};
|
|
@@ -6928,10 +6931,18 @@ function normalizeClaude(payload, event) {
|
|
|
6928
6931
|
if (toolName) {
|
|
6929
6932
|
result.toolName = toolName;
|
|
6930
6933
|
result.toolInput = payload.tool_input;
|
|
6931
|
-
|
|
6932
|
-
if (
|
|
6933
|
-
|
|
6934
|
-
|
|
6934
|
+
const toolResponse = payload.tool_response ?? payload.tool_result;
|
|
6935
|
+
if (typeof toolResponse === "string") {
|
|
6936
|
+
result.toolResult = toolResponse;
|
|
6937
|
+
} else if (toolResponse && typeof toolResponse === "object") {
|
|
6938
|
+
result.toolResult = JSON.stringify(toolResponse);
|
|
6939
|
+
}
|
|
6940
|
+
const toolInput = payload.tool_input;
|
|
6941
|
+
if (/^bash$/i.test(toolName) && toolInput?.command) {
|
|
6942
|
+
result.command = toolInput.command;
|
|
6943
|
+
}
|
|
6944
|
+
if (/^(write|edit|multi_edit|multiedittool)$/i.test(toolName)) {
|
|
6945
|
+
result.filePath = toolInput?.file_path ?? toolInput?.filePath;
|
|
6935
6946
|
}
|
|
6936
6947
|
}
|
|
6937
6948
|
if (event === "user_prompt") {
|
|
@@ -7231,6 +7242,19 @@ function extractContent(input) {
|
|
|
7231
7242
|
parts.push(`Edit: ${edit.oldString} \u2192 ${edit.newString}`);
|
|
7232
7243
|
}
|
|
7233
7244
|
}
|
|
7245
|
+
if (parts.length === 0 && input.toolInput && typeof input.toolInput === "object") {
|
|
7246
|
+
if (input.toolName) parts.push(`Tool: ${input.toolName}`);
|
|
7247
|
+
if (input.toolInput.command) parts.push(`Command: ${input.toolInput.command}`);
|
|
7248
|
+
if (input.toolInput.file_path) parts.push(`File: ${input.toolInput.file_path}`);
|
|
7249
|
+
if (input.toolInput.content) {
|
|
7250
|
+
const content = input.toolInput.content;
|
|
7251
|
+
parts.push(content.slice(0, 1e3));
|
|
7252
|
+
}
|
|
7253
|
+
if (parts.length <= 1) {
|
|
7254
|
+
const summary = JSON.stringify(input.toolInput).slice(0, 500);
|
|
7255
|
+
parts.push(summary);
|
|
7256
|
+
}
|
|
7257
|
+
}
|
|
7234
7258
|
return parts.join("\n").slice(0, MAX_CONTENT_LENGTH);
|
|
7235
7259
|
}
|
|
7236
7260
|
function deriveEntityName(input) {
|
|
@@ -7421,7 +7445,7 @@ ${lines.join("\n")}`;
|
|
|
7421
7445
|
return { observation: null, output: defaultOutput };
|
|
7422
7446
|
}
|
|
7423
7447
|
const toolPattern = detectBestPattern(toolContent);
|
|
7424
|
-
if (!toolPattern) {
|
|
7448
|
+
if (!toolPattern && toolContent.length < 200) {
|
|
7425
7449
|
return { observation: null, output: defaultOutput };
|
|
7426
7450
|
}
|
|
7427
7451
|
markTriggered(toolKey);
|
|
@@ -7437,7 +7461,8 @@ ${lines.join("\n")}`;
|
|
|
7437
7461
|
return { observation: null, output: defaultOutput };
|
|
7438
7462
|
}
|
|
7439
7463
|
const content = extractContent(input);
|
|
7440
|
-
|
|
7464
|
+
const minLen = input.event === "user_prompt" ? MIN_PROMPT_LENGTH : MIN_STORE_LENGTH;
|
|
7465
|
+
if (content.length < minLen) {
|
|
7441
7466
|
return { observation: null, output: defaultOutput };
|
|
7442
7467
|
}
|
|
7443
7468
|
detectBestPattern(content);
|
|
@@ -7484,7 +7509,7 @@ async function runHook() {
|
|
|
7484
7509
|
}
|
|
7485
7510
|
process.stdout.write(JSON.stringify(output));
|
|
7486
7511
|
}
|
|
7487
|
-
var cooldowns, COOLDOWN_MS, MIN_STORE_LENGTH, MIN_EDIT_LENGTH, NOISE_COMMANDS, MAX_CONTENT_LENGTH;
|
|
7512
|
+
var cooldowns, COOLDOWN_MS, MIN_STORE_LENGTH, MIN_PROMPT_LENGTH, MIN_EDIT_LENGTH, NOISE_COMMANDS, MAX_CONTENT_LENGTH;
|
|
7488
7513
|
var init_handler = __esm({
|
|
7489
7514
|
"src/hooks/handler.ts"() {
|
|
7490
7515
|
"use strict";
|
|
@@ -7494,6 +7519,7 @@ var init_handler = __esm({
|
|
|
7494
7519
|
cooldowns = /* @__PURE__ */ new Map();
|
|
7495
7520
|
COOLDOWN_MS = 3e4;
|
|
7496
7521
|
MIN_STORE_LENGTH = 100;
|
|
7522
|
+
MIN_PROMPT_LENGTH = 20;
|
|
7497
7523
|
MIN_EDIT_LENGTH = 30;
|
|
7498
7524
|
NOISE_COMMANDS = [
|
|
7499
7525
|
/^(ls|dir|cd|pwd|echo|cat|type|head|tail|wc|find|which|where|whoami)\b/i,
|