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/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,9 +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
|
-
normalize: true
|
|
2701
|
+
normalize: true,
|
|
2702
|
+
truncation: true,
|
|
2703
|
+
max_length: 512
|
|
2682
2704
|
});
|
|
2683
2705
|
const vector = Array.from(output.data);
|
|
2684
2706
|
return {
|
|
@@ -2700,9 +2722,11 @@ var Embedder = class {
|
|
|
2700
2722
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
2701
2723
|
const batch = texts.slice(i, i + batchSize);
|
|
2702
2724
|
for (const text of batch) {
|
|
2703
|
-
const output = await this.pipeline(text, {
|
|
2725
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2704
2726
|
pooling: "mean",
|
|
2705
|
-
normalize: true
|
|
2727
|
+
normalize: true,
|
|
2728
|
+
truncation: true,
|
|
2729
|
+
max_length: 512
|
|
2706
2730
|
});
|
|
2707
2731
|
const vector = Array.from(output.data);
|
|
2708
2732
|
results.push({
|
|
@@ -5968,6 +5992,7 @@ var MemoryService = class {
|
|
|
5968
5992
|
projectPath = null;
|
|
5969
5993
|
readOnly;
|
|
5970
5994
|
lightweightMode;
|
|
5995
|
+
embeddingOnly;
|
|
5971
5996
|
mdMirror;
|
|
5972
5997
|
storagePath;
|
|
5973
5998
|
constructor(config) {
|
|
@@ -5975,6 +6000,7 @@ var MemoryService = class {
|
|
|
5975
6000
|
this.storagePath = storagePath;
|
|
5976
6001
|
this.readOnly = config.readOnly ?? false;
|
|
5977
6002
|
this.lightweightMode = config.lightweightMode ?? false;
|
|
6003
|
+
this.embeddingOnly = config.embeddingOnly ?? false;
|
|
5978
6004
|
this.mdMirror = new MarkdownMirror2(process.cwd());
|
|
5979
6005
|
if (!this.readOnly && !fs4.existsSync(storagePath)) {
|
|
5980
6006
|
fs4.mkdirSync(storagePath, { recursive: true });
|
|
@@ -6048,19 +6074,21 @@ var MemoryService = class {
|
|
|
6048
6074
|
this.embedder
|
|
6049
6075
|
);
|
|
6050
6076
|
this.vectorWorker.start();
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
this.
|
|
6054
|
-
this.graduation
|
|
6055
|
-
);
|
|
6056
|
-
this.graduationWorker.start();
|
|
6057
|
-
if (this.analyticsStore) {
|
|
6058
|
-
this.syncWorker = new SyncWorker(
|
|
6077
|
+
if (!this.embeddingOnly) {
|
|
6078
|
+
this.retriever.setGraduationPipeline(this.graduation);
|
|
6079
|
+
this.graduationWorker = createGraduationWorker(
|
|
6059
6080
|
this.sqliteStore,
|
|
6060
|
-
this.
|
|
6061
|
-
{ intervalMs: 3e4, batchSize: 500 }
|
|
6081
|
+
this.graduation
|
|
6062
6082
|
);
|
|
6063
|
-
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
|
+
}
|
|
6064
6092
|
}
|
|
6065
6093
|
const savedMode = await this.sqliteStore.getEndlessConfig("mode");
|
|
6066
6094
|
if (savedMode === "endless") {
|
|
@@ -6784,6 +6812,19 @@ var MemoryService = class {
|
|
|
6784
6812
|
await this.initialize();
|
|
6785
6813
|
await this.sqliteStore.recordRetrieval(eventId, sessionId, score, query);
|
|
6786
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
|
+
}
|
|
6787
6828
|
/**
|
|
6788
6829
|
* Evaluate helpfulness of retrievals in a session (called at session end)
|
|
6789
6830
|
*/
|
|
@@ -6791,6 +6832,20 @@ var MemoryService = class {
|
|
|
6791
6832
|
await this.initialize();
|
|
6792
6833
|
await this.sqliteStore.evaluateSessionHelpfulness(sessionId);
|
|
6793
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
|
+
}
|
|
6794
6849
|
/**
|
|
6795
6850
|
* Get most helpful memories ranked by helpfulness score
|
|
6796
6851
|
*/
|