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
|
@@ -1834,6 +1834,21 @@ var SQLiteEventStore = class {
|
|
|
1834
1834
|
[id, eventId, sessionId, score, query.slice(0, 100)]
|
|
1835
1835
|
);
|
|
1836
1836
|
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Get session IDs that have unevaluated retrievals (measured_at IS NULL).
|
|
1839
|
+
* Excludes the current session. Used to backfill sessions that ended without Stop hook.
|
|
1840
|
+
*/
|
|
1841
|
+
async getUnevaluatedSessions(currentSessionId, limit = 5) {
|
|
1842
|
+
await this.initialize();
|
|
1843
|
+
const rows = sqliteAll(
|
|
1844
|
+
this.db,
|
|
1845
|
+
`SELECT DISTINCT session_id FROM memory_helpfulness
|
|
1846
|
+
WHERE measured_at IS NULL AND session_id != ?
|
|
1847
|
+
ORDER BY created_at DESC LIMIT ?`,
|
|
1848
|
+
[currentSessionId, limit]
|
|
1849
|
+
);
|
|
1850
|
+
return rows.map((r) => r.session_id);
|
|
1851
|
+
}
|
|
1837
1852
|
/**
|
|
1838
1853
|
* Evaluate helpfulness for all retrievals in a session
|
|
1839
1854
|
* Called at session end - uses behavioral signals to compute score
|
|
@@ -2621,7 +2636,7 @@ var VectorStore = class {
|
|
|
2621
2636
|
|
|
2622
2637
|
// src/core/embedder.ts
|
|
2623
2638
|
import { pipeline } from "@huggingface/transformers";
|
|
2624
|
-
var Embedder = class {
|
|
2639
|
+
var Embedder = class _Embedder {
|
|
2625
2640
|
pipeline = null;
|
|
2626
2641
|
modelName;
|
|
2627
2642
|
activeModelName;
|
|
@@ -2652,6 +2667,11 @@ var Embedder = class {
|
|
|
2652
2667
|
this.initialized = true;
|
|
2653
2668
|
}
|
|
2654
2669
|
}
|
|
2670
|
+
// ~4 chars per token; 512 tokens * 4 = 2048, use 2000 to be safe
|
|
2671
|
+
static MAX_CHARS = 2e3;
|
|
2672
|
+
truncate(text) {
|
|
2673
|
+
return text.length > _Embedder.MAX_CHARS ? text.slice(0, _Embedder.MAX_CHARS) : text;
|
|
2674
|
+
}
|
|
2655
2675
|
/**
|
|
2656
2676
|
* Generate embedding for a single text
|
|
2657
2677
|
*/
|
|
@@ -2660,10 +2680,11 @@ var Embedder = class {
|
|
|
2660
2680
|
if (!this.pipeline) {
|
|
2661
2681
|
throw new Error("Embedding pipeline not initialized");
|
|
2662
2682
|
}
|
|
2663
|
-
const output = await this.pipeline(text, {
|
|
2683
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2664
2684
|
pooling: "mean",
|
|
2665
2685
|
normalize: true,
|
|
2666
|
-
truncation: true
|
|
2686
|
+
truncation: true,
|
|
2687
|
+
max_length: 512
|
|
2667
2688
|
});
|
|
2668
2689
|
const vector = Array.from(output.data);
|
|
2669
2690
|
return {
|
|
@@ -2685,10 +2706,11 @@ var Embedder = class {
|
|
|
2685
2706
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
2686
2707
|
const batch = texts.slice(i, i + batchSize);
|
|
2687
2708
|
for (const text of batch) {
|
|
2688
|
-
const output = await this.pipeline(text, {
|
|
2709
|
+
const output = await this.pipeline(this.truncate(text), {
|
|
2689
2710
|
pooling: "mean",
|
|
2690
2711
|
normalize: true,
|
|
2691
|
-
truncation: true
|
|
2712
|
+
truncation: true,
|
|
2713
|
+
max_length: 512
|
|
2692
2714
|
});
|
|
2693
2715
|
const vector = Array.from(output.data);
|
|
2694
2716
|
results.push({
|
|
@@ -5958,6 +5980,7 @@ var MemoryService = class {
|
|
|
5958
5980
|
projectPath = null;
|
|
5959
5981
|
readOnly;
|
|
5960
5982
|
lightweightMode;
|
|
5983
|
+
embeddingOnly;
|
|
5961
5984
|
mdMirror;
|
|
5962
5985
|
storagePath;
|
|
5963
5986
|
constructor(config) {
|
|
@@ -5965,6 +5988,7 @@ var MemoryService = class {
|
|
|
5965
5988
|
this.storagePath = storagePath;
|
|
5966
5989
|
this.readOnly = config.readOnly ?? false;
|
|
5967
5990
|
this.lightweightMode = config.lightweightMode ?? false;
|
|
5991
|
+
this.embeddingOnly = config.embeddingOnly ?? false;
|
|
5968
5992
|
this.mdMirror = new MarkdownMirror2(process.cwd());
|
|
5969
5993
|
if (!this.readOnly && !fs4.existsSync(storagePath)) {
|
|
5970
5994
|
fs4.mkdirSync(storagePath, { recursive: true });
|
|
@@ -6038,19 +6062,21 @@ var MemoryService = class {
|
|
|
6038
6062
|
this.embedder
|
|
6039
6063
|
);
|
|
6040
6064
|
this.vectorWorker.start();
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
this.
|
|
6044
|
-
this.graduation
|
|
6045
|
-
);
|
|
6046
|
-
this.graduationWorker.start();
|
|
6047
|
-
if (this.analyticsStore) {
|
|
6048
|
-
this.syncWorker = new SyncWorker(
|
|
6065
|
+
if (!this.embeddingOnly) {
|
|
6066
|
+
this.retriever.setGraduationPipeline(this.graduation);
|
|
6067
|
+
this.graduationWorker = createGraduationWorker(
|
|
6049
6068
|
this.sqliteStore,
|
|
6050
|
-
this.
|
|
6051
|
-
{ intervalMs: 3e4, batchSize: 500 }
|
|
6069
|
+
this.graduation
|
|
6052
6070
|
);
|
|
6053
|
-
this.
|
|
6071
|
+
this.graduationWorker.start();
|
|
6072
|
+
if (this.analyticsStore) {
|
|
6073
|
+
this.syncWorker = new SyncWorker(
|
|
6074
|
+
this.sqliteStore,
|
|
6075
|
+
this.analyticsStore,
|
|
6076
|
+
{ intervalMs: 3e4, batchSize: 500 }
|
|
6077
|
+
);
|
|
6078
|
+
this.syncWorker.start();
|
|
6079
|
+
}
|
|
6054
6080
|
}
|
|
6055
6081
|
const savedMode = await this.sqliteStore.getEndlessConfig("mode");
|
|
6056
6082
|
if (savedMode === "endless") {
|
|
@@ -6774,6 +6800,19 @@ var MemoryService = class {
|
|
|
6774
6800
|
await this.initialize();
|
|
6775
6801
|
await this.sqliteStore.recordRetrieval(eventId, sessionId, score, query);
|
|
6776
6802
|
}
|
|
6803
|
+
/**
|
|
6804
|
+
* Record a query-level retrieval trace (used by user-prompt-submit hook).
|
|
6805
|
+
* Feeds the retrieval_traces table that powers dashboard stats.
|
|
6806
|
+
*/
|
|
6807
|
+
async recordQueryTrace(input) {
|
|
6808
|
+
await this.initialize();
|
|
6809
|
+
await this.sqliteStore.recordRetrievalTrace({
|
|
6810
|
+
...input,
|
|
6811
|
+
candidateDetails: [],
|
|
6812
|
+
selectedDetails: [],
|
|
6813
|
+
fallbackTrace: []
|
|
6814
|
+
});
|
|
6815
|
+
}
|
|
6777
6816
|
/**
|
|
6778
6817
|
* Evaluate helpfulness of retrievals in a session (called at session end)
|
|
6779
6818
|
*/
|
|
@@ -6781,6 +6820,20 @@ var MemoryService = class {
|
|
|
6781
6820
|
await this.initialize();
|
|
6782
6821
|
await this.sqliteStore.evaluateSessionHelpfulness(sessionId);
|
|
6783
6822
|
}
|
|
6823
|
+
/**
|
|
6824
|
+
* Backfill helpfulness evaluation for sessions that ended without Stop hook.
|
|
6825
|
+
* Call on first turn of a new session to catch missed evaluations.
|
|
6826
|
+
*/
|
|
6827
|
+
async evaluatePendingSessions(currentSessionId) {
|
|
6828
|
+
await this.initialize();
|
|
6829
|
+
const sessions = await this.sqliteStore.getUnevaluatedSessions(currentSessionId, 5);
|
|
6830
|
+
for (const sid of sessions) {
|
|
6831
|
+
try {
|
|
6832
|
+
await this.sqliteStore.evaluateSessionHelpfulness(sid);
|
|
6833
|
+
} catch {
|
|
6834
|
+
}
|
|
6835
|
+
}
|
|
6836
|
+
}
|
|
6784
6837
|
/**
|
|
6785
6838
|
* Get most helpful memories ranked by helpfulness score
|
|
6786
6839
|
*/
|