claude-memory-layer 1.0.15 → 1.0.17
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/README.md +3 -0
- package/dist/cli/index.js +105 -74
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +53 -40
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +53 -40
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/session-end.js +53 -40
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +53 -40
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +53 -40
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +72 -43
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/server/api/index.js +53 -40
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +53 -40
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +53 -40
- package/dist/services/memory-service.js.map +2 -2
- package/memory/_index.md +3 -0
- package/memory/agent_response/uncategorized/2026-02-26.md +26 -0
- package/memory/tool_observation/uncategorized/2026-02-26.md +201 -0
- package/memory/user_prompt/uncategorized/2026-02-26.md +16 -0
- package/package.json +1 -1
- package/src/cli/index.ts +55 -33
- package/src/core/sqlite-event-store.ts +52 -40
- package/src/hooks/user-prompt-submit.ts +22 -3
package/README.md
CHANGED
|
@@ -71,6 +71,9 @@ npx claude-memory-layer search "배포 이슈"
|
|
|
71
71
|
- `GET /health` (서버 헬스)
|
|
72
72
|
- `GET /api/health` (outbox pending/failed 포함 상세 헬스)
|
|
73
73
|
- `GET /api/stats/retrieval-traces` (검색→컨텍스트 채택 추적)
|
|
74
|
+
- 주입 임계값 튜닝(환경변수):
|
|
75
|
+
- `CLAUDE_MEMORY_MIN_SCORE` (기본 0.4)
|
|
76
|
+
- `CLAUDE_MEMORY_FALLBACK_MIN_SCORE` (기본 0.3, 결과 0건일 때 재시도)
|
|
74
77
|
|
|
75
78
|
---
|
|
76
79
|
|
package/dist/cli/index.js
CHANGED
|
@@ -2046,49 +2046,62 @@ var SQLiteEventStore = class {
|
|
|
2046
2046
|
}
|
|
2047
2047
|
async getRecentRetrievalTraces(limit = 50) {
|
|
2048
2048
|
await this.initialize();
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2049
|
+
try {
|
|
2050
|
+
const rows = sqliteAll(
|
|
2051
|
+
this.db,
|
|
2052
|
+
`SELECT * FROM retrieval_traces ORDER BY created_at DESC LIMIT ?`,
|
|
2053
|
+
[limit]
|
|
2054
|
+
);
|
|
2055
|
+
return rows.map((row) => ({
|
|
2056
|
+
traceId: row.trace_id,
|
|
2057
|
+
sessionId: row.session_id || void 0,
|
|
2058
|
+
projectHash: row.project_hash || void 0,
|
|
2059
|
+
queryText: row.query_text,
|
|
2060
|
+
strategy: row.strategy || void 0,
|
|
2061
|
+
candidateEventIds: row.candidate_event_ids ? JSON.parse(row.candidate_event_ids) : [],
|
|
2062
|
+
selectedEventIds: row.selected_event_ids ? JSON.parse(row.selected_event_ids) : [],
|
|
2063
|
+
candidateDetails: row.candidate_details_json ? JSON.parse(row.candidate_details_json) : [],
|
|
2064
|
+
selectedDetails: row.selected_details_json ? JSON.parse(row.selected_details_json) : [],
|
|
2065
|
+
candidateCount: Number(row.candidate_count || 0),
|
|
2066
|
+
selectedCount: Number(row.selected_count || 0),
|
|
2067
|
+
confidence: row.confidence || void 0,
|
|
2068
|
+
fallbackTrace: row.fallback_trace ? JSON.parse(row.fallback_trace) : [],
|
|
2069
|
+
createdAt: toDateFromSQLite(row.created_at)
|
|
2070
|
+
}));
|
|
2071
|
+
} catch (err) {
|
|
2072
|
+
if (err?.message?.includes("no such table"))
|
|
2073
|
+
return [];
|
|
2074
|
+
throw err;
|
|
2075
|
+
}
|
|
2070
2076
|
}
|
|
2071
2077
|
async getRetrievalTraceStats() {
|
|
2072
2078
|
await this.initialize();
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2079
|
+
try {
|
|
2080
|
+
const row = sqliteGet(
|
|
2081
|
+
this.db,
|
|
2082
|
+
`SELECT
|
|
2083
|
+
COUNT(*) as total_queries,
|
|
2084
|
+
AVG(candidate_count) as avg_candidate_count,
|
|
2085
|
+
AVG(selected_count) as avg_selected_count,
|
|
2086
|
+
CASE
|
|
2087
|
+
WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))
|
|
2088
|
+
ELSE 0
|
|
2089
|
+
END as selection_rate
|
|
2090
|
+
FROM retrieval_traces`,
|
|
2091
|
+
[]
|
|
2092
|
+
);
|
|
2093
|
+
return {
|
|
2094
|
+
totalQueries: Number(row?.total_queries || 0),
|
|
2095
|
+
avgCandidateCount: Number(row?.avg_candidate_count || 0),
|
|
2096
|
+
avgSelectedCount: Number(row?.avg_selected_count || 0),
|
|
2097
|
+
selectionRate: Number(row?.selection_rate || 0)
|
|
2098
|
+
};
|
|
2099
|
+
} catch (err) {
|
|
2100
|
+
if (err?.message?.includes("no such table")) {
|
|
2101
|
+
return { totalQueries: 0, avgCandidateCount: 0, avgSelectedCount: 0, selectionRate: 0 };
|
|
2102
|
+
}
|
|
2103
|
+
throw err;
|
|
2104
|
+
}
|
|
2092
2105
|
}
|
|
2093
2106
|
/**
|
|
2094
2107
|
* Close database connection
|
|
@@ -9214,41 +9227,51 @@ function saveClaudeSettings(settings) {
|
|
|
9214
9227
|
fs9.writeFileSync(tempPath, JSON.stringify(settings, null, 2));
|
|
9215
9228
|
fs9.renameSync(tempPath, CLAUDE_SETTINGS_PATH);
|
|
9216
9229
|
}
|
|
9230
|
+
var REQUIRED_HOOK_FILES = [
|
|
9231
|
+
"user-prompt-submit.js",
|
|
9232
|
+
"post-tool-use.js",
|
|
9233
|
+
"session-start.js",
|
|
9234
|
+
"stop.js",
|
|
9235
|
+
"session-end.js"
|
|
9236
|
+
];
|
|
9237
|
+
function hasHook(settings, hookName, commandFragment) {
|
|
9238
|
+
const hookEntries = settings.hooks?.[hookName];
|
|
9239
|
+
if (!hookEntries)
|
|
9240
|
+
return false;
|
|
9241
|
+
return hookEntries.some((entry) => entry.hooks?.some((hook) => hook.command?.includes(commandFragment)));
|
|
9242
|
+
}
|
|
9217
9243
|
function getHooksConfig(pluginPath) {
|
|
9244
|
+
const makeHook = (fileName) => [
|
|
9245
|
+
{
|
|
9246
|
+
matcher: "",
|
|
9247
|
+
hooks: [
|
|
9248
|
+
{
|
|
9249
|
+
type: "command",
|
|
9250
|
+
command: `node ${path9.join(pluginPath, "hooks", fileName)}`
|
|
9251
|
+
}
|
|
9252
|
+
]
|
|
9253
|
+
}
|
|
9254
|
+
];
|
|
9218
9255
|
return {
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
type: "command",
|
|
9225
|
-
command: `node ${path9.join(pluginPath, "hooks", "user-prompt-submit.js")}`
|
|
9226
|
-
}
|
|
9227
|
-
]
|
|
9228
|
-
}
|
|
9229
|
-
],
|
|
9230
|
-
PostToolUse: [
|
|
9231
|
-
{
|
|
9232
|
-
matcher: "",
|
|
9233
|
-
hooks: [
|
|
9234
|
-
{
|
|
9235
|
-
type: "command",
|
|
9236
|
-
command: `node ${path9.join(pluginPath, "hooks", "post-tool-use.js")}`
|
|
9237
|
-
}
|
|
9238
|
-
]
|
|
9239
|
-
}
|
|
9240
|
-
]
|
|
9256
|
+
SessionStart: makeHook("session-start.js"),
|
|
9257
|
+
UserPromptSubmit: makeHook("user-prompt-submit.js"),
|
|
9258
|
+
PostToolUse: makeHook("post-tool-use.js"),
|
|
9259
|
+
Stop: makeHook("stop.js"),
|
|
9260
|
+
SessionEnd: makeHook("session-end.js")
|
|
9241
9261
|
};
|
|
9242
9262
|
}
|
|
9243
9263
|
var program = new Command();
|
|
9244
|
-
program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.
|
|
9264
|
+
program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.17");
|
|
9245
9265
|
program.command("install").description("Install hooks into Claude Code settings").option("--path <path>", "Custom plugin path (defaults to auto-detect)").action(async (options) => {
|
|
9246
9266
|
try {
|
|
9247
9267
|
const pluginPath = options.path || getPluginPath();
|
|
9248
|
-
const
|
|
9249
|
-
|
|
9268
|
+
const missingHooks = REQUIRED_HOOK_FILES.filter(
|
|
9269
|
+
(file) => !fs9.existsSync(path9.join(pluginPath, "hooks", file))
|
|
9270
|
+
);
|
|
9271
|
+
if (missingHooks.length > 0) {
|
|
9250
9272
|
console.error(`
|
|
9251
9273
|
\u274C Hook files not found at: ${pluginPath}`);
|
|
9274
|
+
console.error(` Missing: ${missingHooks.join(", ")}`);
|
|
9252
9275
|
console.error(' Make sure you have built the plugin with "npm run build"');
|
|
9253
9276
|
process.exit(1);
|
|
9254
9277
|
}
|
|
@@ -9261,8 +9284,11 @@ program.command("install").description("Install hooks into Claude Code settings"
|
|
|
9261
9284
|
saveClaudeSettings(settings);
|
|
9262
9285
|
console.log("\n\u2705 Claude Memory Layer installed!\n");
|
|
9263
9286
|
console.log("Hooks registered:");
|
|
9287
|
+
console.log(" - SessionStart: Register session -> project mapping");
|
|
9264
9288
|
console.log(" - UserPromptSubmit: Memory retrieval on user input");
|
|
9265
|
-
console.log(" - PostToolUse: Store tool observations
|
|
9289
|
+
console.log(" - PostToolUse: Store tool observations");
|
|
9290
|
+
console.log(" - Stop: Store assistant responses");
|
|
9291
|
+
console.log(" - SessionEnd: Persist session summary\n");
|
|
9266
9292
|
console.log("Plugin path:", pluginPath);
|
|
9267
9293
|
console.log("\n\u26A0\uFE0F Restart Claude Code for changes to take effect.\n");
|
|
9268
9294
|
console.log("Commands:");
|
|
@@ -9282,8 +9308,11 @@ program.command("uninstall").description("Remove hooks from Claude Code settings
|
|
|
9282
9308
|
console.log("\n\u{1F4CB} No hooks installed.\n");
|
|
9283
9309
|
return;
|
|
9284
9310
|
}
|
|
9311
|
+
delete settings.hooks.SessionStart;
|
|
9285
9312
|
delete settings.hooks.UserPromptSubmit;
|
|
9286
9313
|
delete settings.hooks.PostToolUse;
|
|
9314
|
+
delete settings.hooks.Stop;
|
|
9315
|
+
delete settings.hooks.SessionEnd;
|
|
9287
9316
|
if (Object.keys(settings.hooks).length === 0) {
|
|
9288
9317
|
delete settings.hooks;
|
|
9289
9318
|
}
|
|
@@ -9303,23 +9332,25 @@ program.command("status").description("Check plugin installation status").action
|
|
|
9303
9332
|
const settings = loadClaudeSettings();
|
|
9304
9333
|
const pluginPath = getPluginPath();
|
|
9305
9334
|
console.log("\n\u{1F9E0} Claude Memory Layer Status\n");
|
|
9306
|
-
const
|
|
9307
|
-
|
|
9308
|
-
);
|
|
9309
|
-
const
|
|
9310
|
-
|
|
9311
|
-
);
|
|
9335
|
+
const hasSessionStartHook = hasHook(settings, "SessionStart", "session-start");
|
|
9336
|
+
const hasUserPromptHook = hasHook(settings, "UserPromptSubmit", "user-prompt-submit");
|
|
9337
|
+
const hasPostToolHook = hasHook(settings, "PostToolUse", "post-tool-use");
|
|
9338
|
+
const hasStopHook = hasHook(settings, "Stop", "stop");
|
|
9339
|
+
const hasSessionEndHook = hasHook(settings, "SessionEnd", "session-end");
|
|
9312
9340
|
console.log("Hooks:");
|
|
9341
|
+
console.log(` SessionStart: ${hasSessionStartHook ? "\u2705 Installed" : "\u274C Not installed"}`);
|
|
9313
9342
|
console.log(` UserPromptSubmit: ${hasUserPromptHook ? "\u2705 Installed" : "\u274C Not installed"}`);
|
|
9314
9343
|
console.log(` PostToolUse: ${hasPostToolHook ? "\u2705 Installed" : "\u274C Not installed"}`);
|
|
9315
|
-
|
|
9344
|
+
console.log(` Stop: ${hasStopHook ? "\u2705 Installed" : "\u274C Not installed"}`);
|
|
9345
|
+
console.log(` SessionEnd: ${hasSessionEndHook ? "\u2705 Installed" : "\u274C Not installed"}`);
|
|
9346
|
+
const hooksExist = REQUIRED_HOOK_FILES.every((file) => fs9.existsSync(path9.join(pluginPath, "hooks", file)));
|
|
9316
9347
|
console.log(`
|
|
9317
9348
|
Plugin files: ${hooksExist ? "\u2705 Found" : "\u274C Not found"}`);
|
|
9318
9349
|
console.log(` Path: ${pluginPath}`);
|
|
9319
9350
|
const dashboardRunning = await isServerRunning(37777);
|
|
9320
9351
|
console.log(`
|
|
9321
9352
|
Dashboard: ${dashboardRunning ? "\u2705 Running at http://localhost:37777" : "\u23F9\uFE0F Not running"}`);
|
|
9322
|
-
if (!hasUserPromptHook || !hasPostToolHook) {
|
|
9353
|
+
if (!hasSessionStartHook || !hasUserPromptHook || !hasPostToolHook || !hasStopHook || !hasSessionEndHook) {
|
|
9323
9354
|
console.log('\n\u{1F4A1} Run "claude-memory-layer install" to set up hooks.\n');
|
|
9324
9355
|
} else {
|
|
9325
9356
|
console.log("\n\u2705 Plugin is fully installed and configured.\n");
|