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
package/dist/server/api/index.js
CHANGED
|
@@ -1850,6 +1850,21 @@ var SQLiteEventStore = class {
|
|
|
1850
1850
|
[id, eventId, sessionId, score, query.slice(0, 100)]
|
|
1851
1851
|
);
|
|
1852
1852
|
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Get session IDs that have unevaluated retrievals (measured_at IS NULL).
|
|
1855
|
+
* Excludes the current session. Used to backfill sessions that ended without Stop hook.
|
|
1856
|
+
*/
|
|
1857
|
+
async getUnevaluatedSessions(currentSessionId, limit = 5) {
|
|
1858
|
+
await this.initialize();
|
|
1859
|
+
const rows = sqliteAll(
|
|
1860
|
+
this.db,
|
|
1861
|
+
`SELECT DISTINCT session_id FROM memory_helpfulness
|
|
1862
|
+
WHERE measured_at IS NULL AND session_id != ?
|
|
1863
|
+
ORDER BY created_at DESC LIMIT ?`,
|
|
1864
|
+
[currentSessionId, limit]
|
|
1865
|
+
);
|
|
1866
|
+
return rows.map((r) => r.session_id);
|
|
1867
|
+
}
|
|
1853
1868
|
/**
|
|
1854
1869
|
* Evaluate helpfulness for all retrievals in a session
|
|
1855
1870
|
* Called at session end - uses behavioral signals to compute score
|
|
@@ -2637,7 +2652,7 @@ var VectorStore = class {
|
|
|
2637
2652
|
|
|
2638
2653
|
// src/core/embedder.ts
|
|
2639
2654
|
import { pipeline } from "@huggingface/transformers";
|
|
2640
|
-
var Embedder = class {
|
|
2655
|
+
var Embedder = class _Embedder {
|
|
2641
2656
|
pipeline = null;
|
|
2642
2657
|
modelName;
|
|
2643
2658
|
activeModelName;
|
|
@@ -2668,6 +2683,11 @@ var Embedder = class {
|
|
|
2668
2683
|
this.initialized = true;
|
|
2669
2684
|
}
|
|
2670
2685
|
}
|
|
2686
|
+
// ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe
|
|
2687
|
+
static MAX_CHARS = 2e3;
|
|
2688
|
+
truncate(text) {
|
|
2689
|
+
return text.length > _Embedder.MAX_CHARS ? text.slice(0, _Embedder.MAX_CHARS) : text;
|
|
2690
|
+
}
|
|
2671
2691
|
/**
|
|
2672
2692
|
* Generate embedding for a single text
|
|
2673
2693
|
*/
|
|
@@ -2676,10 +2696,11 @@ var Embedder = class {
|
|
|
2676
2696
|
if (!this.pipeline) {
|
|
2677
2697
|
throw new Error("Embedding pipeline not initialized");
|
|
2678
2698
|
}
|
|
2679
|
-
const output = await this.pipeline(text, {
|
|
2699
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2680
2700
|
pooling: "mean",
|
|
2681
2701
|
normalize: true,
|
|
2682
|
-
truncation: true
|
|
2702
|
+
truncation: true,
|
|
2703
|
+
max_length: 512
|
|
2683
2704
|
});
|
|
2684
2705
|
const vector = Array.from(output.data);
|
|
2685
2706
|
return {
|
|
@@ -2701,10 +2722,11 @@ var Embedder = class {
|
|
|
2701
2722
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
2702
2723
|
const batch = texts.slice(i, i + batchSize);
|
|
2703
2724
|
for (const text of batch) {
|
|
2704
|
-
const output = await this.pipeline(text, {
|
|
2725
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2705
2726
|
pooling: "mean",
|
|
2706
2727
|
normalize: true,
|
|
2707
|
-
truncation: true
|
|
2728
|
+
truncation: true,
|
|
2729
|
+
max_length: 512
|
|
2708
2730
|
});
|
|
2709
2731
|
const vector = Array.from(output.data);
|
|
2710
2732
|
results.push({
|
|
@@ -5970,6 +5992,7 @@ var MemoryService = class {
|
|
|
5970
5992
|
projectPath = null;
|
|
5971
5993
|
readOnly;
|
|
5972
5994
|
lightweightMode;
|
|
5995
|
+
embeddingOnly;
|
|
5973
5996
|
mdMirror;
|
|
5974
5997
|
storagePath;
|
|
5975
5998
|
constructor(config) {
|
|
@@ -5977,6 +6000,7 @@ var MemoryService = class {
|
|
|
5977
6000
|
this.storagePath = storagePath;
|
|
5978
6001
|
this.readOnly = config.readOnly ?? false;
|
|
5979
6002
|
this.lightweightMode = config.lightweightMode ?? false;
|
|
6003
|
+
this.embeddingOnly = config.embeddingOnly ?? false;
|
|
5980
6004
|
this.mdMirror = new MarkdownMirror2(process.cwd());
|
|
5981
6005
|
if (!this.readOnly && !fs4.existsSync(storagePath)) {
|
|
5982
6006
|
fs4.mkdirSync(storagePath, { recursive: true });
|
|
@@ -6050,19 +6074,21 @@ var MemoryService = class {
|
|
|
6050
6074
|
this.embedder
|
|
6051
6075
|
);
|
|
6052
6076
|
this.vectorWorker.start();
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
this.
|
|
6056
|
-
this.graduation
|
|
6057
|
-
);
|
|
6058
|
-
this.graduationWorker.start();
|
|
6059
|
-
if (this.analyticsStore) {
|
|
6060
|
-
this.syncWorker = new SyncWorker(
|
|
6077
|
+
if (!this.embeddingOnly) {
|
|
6078
|
+
this.retriever.setGraduationPipeline(this.graduation);
|
|
6079
|
+
this.graduationWorker = createGraduationWorker(
|
|
6061
6080
|
this.sqliteStore,
|
|
6062
|
-
this.
|
|
6063
|
-
{ intervalMs: 3e4, batchSize: 500 }
|
|
6081
|
+
this.graduation
|
|
6064
6082
|
);
|
|
6065
|
-
this.
|
|
6083
|
+
this.graduationWorker.start();
|
|
6084
|
+
if (this.analyticsStore) {
|
|
6085
|
+
this.syncWorker = new SyncWorker(
|
|
6086
|
+
this.sqliteStore,
|
|
6087
|
+
this.analyticsStore,
|
|
6088
|
+
{ intervalMs: 3e4, batchSize: 500 }
|
|
6089
|
+
);
|
|
6090
|
+
this.syncWorker.start();
|
|
6091
|
+
}
|
|
6066
6092
|
}
|
|
6067
6093
|
const savedMode = await this.sqliteStore.getEndlessConfig("mode");
|
|
6068
6094
|
if (savedMode === "endless") {
|
|
@@ -6786,6 +6812,19 @@ var MemoryService = class {
|
|
|
6786
6812
|
await this.initialize();
|
|
6787
6813
|
await this.sqliteStore.recordRetrieval(eventId, sessionId, score, query);
|
|
6788
6814
|
}
|
|
6815
|
+
/**
|
|
6816
|
+
* Record a query-level retrieval trace (used by user-prompt-submit hook).
|
|
6817
|
+
* Feeds the retrieval_traces table that powers dashboard stats.
|
|
6818
|
+
*/
|
|
6819
|
+
async recordQueryTrace(input) {
|
|
6820
|
+
await this.initialize();
|
|
6821
|
+
await this.sqliteStore.recordRetrievalTrace({
|
|
6822
|
+
...input,
|
|
6823
|
+
candidateDetails: [],
|
|
6824
|
+
selectedDetails: [],
|
|
6825
|
+
fallbackTrace: []
|
|
6826
|
+
});
|
|
6827
|
+
}
|
|
6789
6828
|
/**
|
|
6790
6829
|
* Evaluate helpfulness of retrievals in a session (called at session end)
|
|
6791
6830
|
*/
|
|
@@ -6793,6 +6832,20 @@ var MemoryService = class {
|
|
|
6793
6832
|
await this.initialize();
|
|
6794
6833
|
await this.sqliteStore.evaluateSessionHelpfulness(sessionId);
|
|
6795
6834
|
}
|
|
6835
|
+
/**
|
|
6836
|
+
* Backfill helpfulness evaluation for sessions that ended without Stop hook.
|
|
6837
|
+
* Call on first turn of a new session to catch missed evaluations.
|
|
6838
|
+
*/
|
|
6839
|
+
async evaluatePendingSessions(currentSessionId) {
|
|
6840
|
+
await this.initialize();
|
|
6841
|
+
const sessions = await this.sqliteStore.getUnevaluatedSessions(currentSessionId, 5);
|
|
6842
|
+
for (const sid of sessions) {
|
|
6843
|
+
try {
|
|
6844
|
+
await this.sqliteStore.evaluateSessionHelpfulness(sid);
|
|
6845
|
+
} catch {
|
|
6846
|
+
}
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
6796
6849
|
/**
|
|
6797
6850
|
* Get most helpful memories ranked by helpfulness score
|
|
6798
6851
|
*/
|