claude-memory-layer 1.0.23 → 1.0.24
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/.claude/settings.local.json +11 -0
- package/README.md +2 -0
- package/dist/cli/index.js +85 -17
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +28 -5
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +115 -18
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +7337 -0
- package/dist/hooks/semantic-daemon.js.map +7 -0
- package/dist/hooks/session-end.js +69 -16
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +154 -24
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +99 -18
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +289 -102
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/server/api/index.js +69 -16
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +69 -16
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +69 -16
- package/dist/services/memory-service.js.map +2 -2
- package/dist/ui/app.js +48 -1
- package/dist/ui/index.html +11 -3
- package/memory/_index.md +1 -0
- package/memory/agent_response/uncategorized/2026-03-04.md +1098 -1
- package/memory/session_summary/uncategorized/2026-03-04.md +31 -0
- package/memory/tool_observation/uncategorized/2026-03-04.md +733 -1
- package/memory/user_prompt/uncategorized/2026-03-04.md +371 -1
- package/package.json +1 -1
- package/scripts/build.ts +2 -1
- package/specs/selective-tool-observation/context.md +100 -0
- package/specs/selective-tool-observation/plan.md +158 -0
- package/specs/selective-tool-observation/spec.md +127 -0
- package/src/cli/index.ts +1 -0
- package/src/core/embedder.ts +13 -4
- package/src/core/sqlite-event-store.ts +16 -0
- package/src/core/turn-state.ts +48 -0
- package/src/core/types.ts +1 -0
- package/src/hooks/post-tool-use.ts +47 -2
- package/src/hooks/semantic-daemon-client.ts +208 -0
- package/src/hooks/semantic-daemon.ts +276 -0
- package/src/hooks/session-start.ts +7 -0
- package/src/hooks/stop.ts +19 -4
- package/src/hooks/user-prompt-submit.ts +48 -40
- package/src/services/memory-service.ts +59 -16
- package/src/services/session-history-importer.ts +18 -0
- package/src/ui/app.js +48 -1
- package/src/ui/index.html +11 -3
|
@@ -1833,6 +1833,21 @@ var SQLiteEventStore = class {
|
|
|
1833
1833
|
[id, eventId, sessionId, score, query.slice(0, 100)]
|
|
1834
1834
|
);
|
|
1835
1835
|
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Get session IDs that have unevaluated retrievals (measured_at IS NULL).
|
|
1838
|
+
* Excludes the current session. Used to backfill sessions that ended without Stop hook.
|
|
1839
|
+
*/
|
|
1840
|
+
async getUnevaluatedSessions(currentSessionId, limit = 5) {
|
|
1841
|
+
await this.initialize();
|
|
1842
|
+
const rows = sqliteAll(
|
|
1843
|
+
this.db,
|
|
1844
|
+
`SELECT DISTINCT session_id FROM memory_helpfulness
|
|
1845
|
+
WHERE measured_at IS NULL AND session_id != ?
|
|
1846
|
+
ORDER BY created_at DESC LIMIT ?`,
|
|
1847
|
+
[currentSessionId, limit]
|
|
1848
|
+
);
|
|
1849
|
+
return rows.map((r) => r.session_id);
|
|
1850
|
+
}
|
|
1836
1851
|
/**
|
|
1837
1852
|
* Evaluate helpfulness for all retrievals in a session
|
|
1838
1853
|
* Called at session end - uses behavioral signals to compute score
|
|
@@ -2620,7 +2635,7 @@ var VectorStore = class {
|
|
|
2620
2635
|
|
|
2621
2636
|
// src/core/embedder.ts
|
|
2622
2637
|
import { pipeline } from "@huggingface/transformers";
|
|
2623
|
-
var Embedder = class {
|
|
2638
|
+
var Embedder = class _Embedder {
|
|
2624
2639
|
pipeline = null;
|
|
2625
2640
|
modelName;
|
|
2626
2641
|
activeModelName;
|
|
@@ -2651,6 +2666,11 @@ var Embedder = class {
|
|
|
2651
2666
|
this.initialized = true;
|
|
2652
2667
|
}
|
|
2653
2668
|
}
|
|
2669
|
+
// ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe
|
|
2670
|
+
static MAX_CHARS = 2e3;
|
|
2671
|
+
truncate(text) {
|
|
2672
|
+
return text.length > _Embedder.MAX_CHARS ? text.slice(0, _Embedder.MAX_CHARS) : text;
|
|
2673
|
+
}
|
|
2654
2674
|
/**
|
|
2655
2675
|
* Generate embedding for a single text
|
|
2656
2676
|
*/
|
|
@@ -2659,10 +2679,11 @@ var Embedder = class {
|
|
|
2659
2679
|
if (!this.pipeline) {
|
|
2660
2680
|
throw new Error("Embedding pipeline not initialized");
|
|
2661
2681
|
}
|
|
2662
|
-
const output = await this.pipeline(text, {
|
|
2682
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2663
2683
|
pooling: "mean",
|
|
2664
2684
|
normalize: true,
|
|
2665
|
-
truncation: true
|
|
2685
|
+
truncation: true,
|
|
2686
|
+
max_length: 512
|
|
2666
2687
|
});
|
|
2667
2688
|
const vector = Array.from(output.data);
|
|
2668
2689
|
return {
|
|
@@ -2684,10 +2705,11 @@ var Embedder = class {
|
|
|
2684
2705
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
2685
2706
|
const batch = texts.slice(i, i + batchSize);
|
|
2686
2707
|
for (const text of batch) {
|
|
2687
|
-
const output = await this.pipeline(text, {
|
|
2708
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2688
2709
|
pooling: "mean",
|
|
2689
2710
|
normalize: true,
|
|
2690
|
-
truncation: true
|
|
2711
|
+
truncation: true,
|
|
2712
|
+
max_length: 512
|
|
2691
2713
|
});
|
|
2692
2714
|
const vector = Array.from(output.data);
|
|
2693
2715
|
results.push({
|
|
@@ -5982,6 +6004,7 @@ var MemoryService = class {
|
|
|
5982
6004
|
projectPath = null;
|
|
5983
6005
|
readOnly;
|
|
5984
6006
|
lightweightMode;
|
|
6007
|
+
embeddingOnly;
|
|
5985
6008
|
mdMirror;
|
|
5986
6009
|
storagePath;
|
|
5987
6010
|
constructor(config) {
|
|
@@ -5989,6 +6012,7 @@ var MemoryService = class {
|
|
|
5989
6012
|
this.storagePath = storagePath;
|
|
5990
6013
|
this.readOnly = config.readOnly ?? false;
|
|
5991
6014
|
this.lightweightMode = config.lightweightMode ?? false;
|
|
6015
|
+
this.embeddingOnly = config.embeddingOnly ?? false;
|
|
5992
6016
|
this.mdMirror = new MarkdownMirror2(process.cwd());
|
|
5993
6017
|
if (!this.readOnly && !fs4.existsSync(storagePath)) {
|
|
5994
6018
|
fs4.mkdirSync(storagePath, { recursive: true });
|
|
@@ -6062,19 +6086,21 @@ var MemoryService = class {
|
|
|
6062
6086
|
this.embedder
|
|
6063
6087
|
);
|
|
6064
6088
|
this.vectorWorker.start();
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
this.
|
|
6068
|
-
this.graduation
|
|
6069
|
-
);
|
|
6070
|
-
this.graduationWorker.start();
|
|
6071
|
-
if (this.analyticsStore) {
|
|
6072
|
-
this.syncWorker = new SyncWorker(
|
|
6089
|
+
if (!this.embeddingOnly) {
|
|
6090
|
+
this.retriever.setGraduationPipeline(this.graduation);
|
|
6091
|
+
this.graduationWorker = createGraduationWorker(
|
|
6073
6092
|
this.sqliteStore,
|
|
6074
|
-
this.
|
|
6075
|
-
{ intervalMs: 3e4, batchSize: 500 }
|
|
6093
|
+
this.graduation
|
|
6076
6094
|
);
|
|
6077
|
-
this.
|
|
6095
|
+
this.graduationWorker.start();
|
|
6096
|
+
if (this.analyticsStore) {
|
|
6097
|
+
this.syncWorker = new SyncWorker(
|
|
6098
|
+
this.sqliteStore,
|
|
6099
|
+
this.analyticsStore,
|
|
6100
|
+
{ intervalMs: 3e4, batchSize: 500 }
|
|
6101
|
+
);
|
|
6102
|
+
this.syncWorker.start();
|
|
6103
|
+
}
|
|
6078
6104
|
}
|
|
6079
6105
|
const savedMode = await this.sqliteStore.getEndlessConfig("mode");
|
|
6080
6106
|
if (savedMode === "endless") {
|
|
@@ -6798,6 +6824,19 @@ var MemoryService = class {
|
|
|
6798
6824
|
await this.initialize();
|
|
6799
6825
|
await this.sqliteStore.recordRetrieval(eventId, sessionId, score, query);
|
|
6800
6826
|
}
|
|
6827
|
+
/**
|
|
6828
|
+
* Record a query-level retrieval trace (used by user-prompt-submit hook).
|
|
6829
|
+
* Feeds the retrieval_traces table that powers dashboard stats.
|
|
6830
|
+
*/
|
|
6831
|
+
async recordQueryTrace(input) {
|
|
6832
|
+
await this.initialize();
|
|
6833
|
+
await this.sqliteStore.recordRetrievalTrace({
|
|
6834
|
+
...input,
|
|
6835
|
+
candidateDetails: [],
|
|
6836
|
+
selectedDetails: [],
|
|
6837
|
+
fallbackTrace: []
|
|
6838
|
+
});
|
|
6839
|
+
}
|
|
6801
6840
|
/**
|
|
6802
6841
|
* Evaluate helpfulness of retrievals in a session (called at session end)
|
|
6803
6842
|
*/
|
|
@@ -6805,6 +6844,20 @@ var MemoryService = class {
|
|
|
6805
6844
|
await this.initialize();
|
|
6806
6845
|
await this.sqliteStore.evaluateSessionHelpfulness(sessionId);
|
|
6807
6846
|
}
|
|
6847
|
+
/**
|
|
6848
|
+
* Backfill helpfulness evaluation for sessions that ended without Stop hook.
|
|
6849
|
+
* Call on first turn of a new session to catch missed evaluations.
|
|
6850
|
+
*/
|
|
6851
|
+
async evaluatePendingSessions(currentSessionId) {
|
|
6852
|
+
await this.initialize();
|
|
6853
|
+
const sessions = await this.sqliteStore.getUnevaluatedSessions(currentSessionId, 5);
|
|
6854
|
+
for (const sid of sessions) {
|
|
6855
|
+
try {
|
|
6856
|
+
await this.sqliteStore.evaluateSessionHelpfulness(sid);
|
|
6857
|
+
} catch {
|
|
6858
|
+
}
|
|
6859
|
+
}
|
|
6860
|
+
}
|
|
6808
6861
|
/**
|
|
6809
6862
|
* Get most helpful memories ranked by helpfulness score
|
|
6810
6863
|
*/
|