claude-memory-layer 1.0.22 → 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 +87 -17
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +30 -5
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +117 -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 +71 -16
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +156 -24
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +101 -18
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +291 -102
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/server/api/index.js +71 -16
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +71 -16
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +71 -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 +1138 -1
- package/memory/session_summary/uncategorized/2026-03-04.md +31 -0
- package/memory/tool_observation/uncategorized/2026-03-04.md +785 -1
- package/memory/user_prompt/uncategorized/2026-03-04.md +438 -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 +15 -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
package/dist/server/index.js
CHANGED
|
@@ -1859,6 +1859,21 @@ var SQLiteEventStore = class {
|
|
|
1859
1859
|
[id, eventId, sessionId, score, query.slice(0, 100)]
|
|
1860
1860
|
);
|
|
1861
1861
|
}
|
|
1862
|
+
/**
|
|
1863
|
+
* Get session IDs that have unevaluated retrievals (measured_at IS NULL).
|
|
1864
|
+
* Excludes the current session. Used to backfill sessions that ended without Stop hook.
|
|
1865
|
+
*/
|
|
1866
|
+
async getUnevaluatedSessions(currentSessionId, limit = 5) {
|
|
1867
|
+
await this.initialize();
|
|
1868
|
+
const rows = sqliteAll(
|
|
1869
|
+
this.db,
|
|
1870
|
+
`SELECT DISTINCT session_id FROM memory_helpfulness
|
|
1871
|
+
WHERE measured_at IS NULL AND session_id != ?
|
|
1872
|
+
ORDER BY created_at DESC LIMIT ?`,
|
|
1873
|
+
[currentSessionId, limit]
|
|
1874
|
+
);
|
|
1875
|
+
return rows.map((r) => r.session_id);
|
|
1876
|
+
}
|
|
1862
1877
|
/**
|
|
1863
1878
|
* Evaluate helpfulness for all retrievals in a session
|
|
1864
1879
|
* Called at session end - uses behavioral signals to compute score
|
|
@@ -2646,7 +2661,7 @@ var VectorStore = class {
|
|
|
2646
2661
|
|
|
2647
2662
|
// src/core/embedder.ts
|
|
2648
2663
|
import { pipeline } from "@huggingface/transformers";
|
|
2649
|
-
var Embedder = class {
|
|
2664
|
+
var Embedder = class _Embedder {
|
|
2650
2665
|
pipeline = null;
|
|
2651
2666
|
modelName;
|
|
2652
2667
|
activeModelName;
|
|
@@ -2677,6 +2692,11 @@ var Embedder = class {
|
|
|
2677
2692
|
this.initialized = true;
|
|
2678
2693
|
}
|
|
2679
2694
|
}
|
|
2695
|
+
// ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe
|
|
2696
|
+
static MAX_CHARS = 2e3;
|
|
2697
|
+
truncate(text) {
|
|
2698
|
+
return text.length > _Embedder.MAX_CHARS ? text.slice(0, _Embedder.MAX_CHARS) : text;
|
|
2699
|
+
}
|
|
2680
2700
|
/**
|
|
2681
2701
|
* Generate embedding for a single text
|
|
2682
2702
|
*/
|
|
@@ -2685,9 +2705,11 @@ var Embedder = class {
|
|
|
2685
2705
|
if (!this.pipeline) {
|
|
2686
2706
|
throw new Error("Embedding pipeline not initialized");
|
|
2687
2707
|
}
|
|
2688
|
-
const output = await this.pipeline(text, {
|
|
2708
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2689
2709
|
pooling: "mean",
|
|
2690
|
-
normalize: true
|
|
2710
|
+
normalize: true,
|
|
2711
|
+
truncation: true,
|
|
2712
|
+
max_length: 512
|
|
2691
2713
|
});
|
|
2692
2714
|
const vector = Array.from(output.data);
|
|
2693
2715
|
return {
|
|
@@ -2709,9 +2731,11 @@ var Embedder = class {
|
|
|
2709
2731
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
2710
2732
|
const batch = texts.slice(i, i + batchSize);
|
|
2711
2733
|
for (const text of batch) {
|
|
2712
|
-
const output = await this.pipeline(text, {
|
|
2734
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2713
2735
|
pooling: "mean",
|
|
2714
|
-
normalize: true
|
|
2736
|
+
normalize: true,
|
|
2737
|
+
truncation: true,
|
|
2738
|
+
max_length: 512
|
|
2715
2739
|
});
|
|
2716
2740
|
const vector = Array.from(output.data);
|
|
2717
2741
|
results.push({
|
|
@@ -5977,6 +6001,7 @@ var MemoryService = class {
|
|
|
5977
6001
|
projectPath = null;
|
|
5978
6002
|
readOnly;
|
|
5979
6003
|
lightweightMode;
|
|
6004
|
+
embeddingOnly;
|
|
5980
6005
|
mdMirror;
|
|
5981
6006
|
storagePath;
|
|
5982
6007
|
constructor(config) {
|
|
@@ -5984,6 +6009,7 @@ var MemoryService = class {
|
|
|
5984
6009
|
this.storagePath = storagePath;
|
|
5985
6010
|
this.readOnly = config.readOnly ?? false;
|
|
5986
6011
|
this.lightweightMode = config.lightweightMode ?? false;
|
|
6012
|
+
this.embeddingOnly = config.embeddingOnly ?? false;
|
|
5987
6013
|
this.mdMirror = new MarkdownMirror2(process.cwd());
|
|
5988
6014
|
if (!this.readOnly && !fs4.existsSync(storagePath)) {
|
|
5989
6015
|
fs4.mkdirSync(storagePath, { recursive: true });
|
|
@@ -6057,19 +6083,21 @@ var MemoryService = class {
|
|
|
6057
6083
|
this.embedder
|
|
6058
6084
|
);
|
|
6059
6085
|
this.vectorWorker.start();
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
this.
|
|
6063
|
-
this.graduation
|
|
6064
|
-
);
|
|
6065
|
-
this.graduationWorker.start();
|
|
6066
|
-
if (this.analyticsStore) {
|
|
6067
|
-
this.syncWorker = new SyncWorker(
|
|
6086
|
+
if (!this.embeddingOnly) {
|
|
6087
|
+
this.retriever.setGraduationPipeline(this.graduation);
|
|
6088
|
+
this.graduationWorker = createGraduationWorker(
|
|
6068
6089
|
this.sqliteStore,
|
|
6069
|
-
this.
|
|
6070
|
-
{ intervalMs: 3e4, batchSize: 500 }
|
|
6090
|
+
this.graduation
|
|
6071
6091
|
);
|
|
6072
|
-
this.
|
|
6092
|
+
this.graduationWorker.start();
|
|
6093
|
+
if (this.analyticsStore) {
|
|
6094
|
+
this.syncWorker = new SyncWorker(
|
|
6095
|
+
this.sqliteStore,
|
|
6096
|
+
this.analyticsStore,
|
|
6097
|
+
{ intervalMs: 3e4, batchSize: 500 }
|
|
6098
|
+
);
|
|
6099
|
+
this.syncWorker.start();
|
|
6100
|
+
}
|
|
6073
6101
|
}
|
|
6074
6102
|
const savedMode = await this.sqliteStore.getEndlessConfig("mode");
|
|
6075
6103
|
if (savedMode === "endless") {
|
|
@@ -6793,6 +6821,19 @@ var MemoryService = class {
|
|
|
6793
6821
|
await this.initialize();
|
|
6794
6822
|
await this.sqliteStore.recordRetrieval(eventId, sessionId, score, query);
|
|
6795
6823
|
}
|
|
6824
|
+
/**
|
|
6825
|
+
* Record a query-level retrieval trace (used by user-prompt-submit hook).
|
|
6826
|
+
* Feeds the retrieval_traces table that powers dashboard stats.
|
|
6827
|
+
*/
|
|
6828
|
+
async recordQueryTrace(input) {
|
|
6829
|
+
await this.initialize();
|
|
6830
|
+
await this.sqliteStore.recordRetrievalTrace({
|
|
6831
|
+
...input,
|
|
6832
|
+
candidateDetails: [],
|
|
6833
|
+
selectedDetails: [],
|
|
6834
|
+
fallbackTrace: []
|
|
6835
|
+
});
|
|
6836
|
+
}
|
|
6796
6837
|
/**
|
|
6797
6838
|
* Evaluate helpfulness of retrievals in a session (called at session end)
|
|
6798
6839
|
*/
|
|
@@ -6800,6 +6841,20 @@ var MemoryService = class {
|
|
|
6800
6841
|
await this.initialize();
|
|
6801
6842
|
await this.sqliteStore.evaluateSessionHelpfulness(sessionId);
|
|
6802
6843
|
}
|
|
6844
|
+
/**
|
|
6845
|
+
* Backfill helpfulness evaluation for sessions that ended without Stop hook.
|
|
6846
|
+
* Call on first turn of a new session to catch missed evaluations.
|
|
6847
|
+
*/
|
|
6848
|
+
async evaluatePendingSessions(currentSessionId) {
|
|
6849
|
+
await this.initialize();
|
|
6850
|
+
const sessions = await this.sqliteStore.getUnevaluatedSessions(currentSessionId, 5);
|
|
6851
|
+
for (const sid of sessions) {
|
|
6852
|
+
try {
|
|
6853
|
+
await this.sqliteStore.evaluateSessionHelpfulness(sid);
|
|
6854
|
+
} catch {
|
|
6855
|
+
}
|
|
6856
|
+
}
|
|
6857
|
+
}
|
|
6803
6858
|
/**
|
|
6804
6859
|
* Get most helpful memories ranked by helpfulness score
|
|
6805
6860
|
*/
|