@mnemoai/core 1.1.0 → 1.1.1
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/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +128 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.ts → dist/index.js} +526 -1333
- package/dist/index.js.map +7 -0
- package/dist/src/access-tracker.d.ts +97 -0
- package/dist/src/access-tracker.d.ts.map +1 -0
- package/dist/src/access-tracker.js +184 -0
- package/dist/src/access-tracker.js.map +7 -0
- package/dist/src/adapters/chroma.d.ts +31 -0
- package/dist/src/adapters/chroma.d.ts.map +1 -0
- package/{src/adapters/chroma.ts → dist/src/adapters/chroma.js} +45 -107
- package/dist/src/adapters/chroma.js.map +7 -0
- package/dist/src/adapters/lancedb.d.ts +29 -0
- package/dist/src/adapters/lancedb.d.ts.map +1 -0
- package/{src/adapters/lancedb.ts → dist/src/adapters/lancedb.js} +41 -109
- package/dist/src/adapters/lancedb.js.map +7 -0
- package/dist/src/adapters/pgvector.d.ts +33 -0
- package/dist/src/adapters/pgvector.d.ts.map +1 -0
- package/{src/adapters/pgvector.ts → dist/src/adapters/pgvector.js} +42 -104
- package/dist/src/adapters/pgvector.js.map +7 -0
- package/dist/src/adapters/qdrant.d.ts +34 -0
- package/dist/src/adapters/qdrant.d.ts.map +1 -0
- package/dist/src/adapters/qdrant.js +132 -0
- package/dist/src/adapters/qdrant.js.map +7 -0
- package/dist/src/adaptive-retrieval.d.ts +14 -0
- package/dist/src/adaptive-retrieval.d.ts.map +1 -0
- package/dist/src/adaptive-retrieval.js +52 -0
- package/dist/src/adaptive-retrieval.js.map +7 -0
- package/dist/src/audit-log.d.ts +56 -0
- package/dist/src/audit-log.d.ts.map +1 -0
- package/dist/src/audit-log.js +139 -0
- package/dist/src/audit-log.js.map +7 -0
- package/dist/src/chunker.d.ts +45 -0
- package/dist/src/chunker.d.ts.map +1 -0
- package/dist/src/chunker.js +157 -0
- package/dist/src/chunker.js.map +7 -0
- package/dist/src/config.d.ts +70 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +142 -0
- package/dist/src/config.js.map +7 -0
- package/dist/src/decay-engine.d.ts +73 -0
- package/dist/src/decay-engine.d.ts.map +1 -0
- package/dist/src/decay-engine.js +119 -0
- package/dist/src/decay-engine.js.map +7 -0
- package/dist/src/embedder.d.ts +94 -0
- package/dist/src/embedder.d.ts.map +1 -0
- package/{src/embedder.ts → dist/src/embedder.js} +119 -317
- package/dist/src/embedder.js.map +7 -0
- package/dist/src/extraction-prompts.d.ts +12 -0
- package/dist/src/extraction-prompts.d.ts.map +1 -0
- package/dist/src/extraction-prompts.js +311 -0
- package/dist/src/extraction-prompts.js.map +7 -0
- package/dist/src/license.d.ts +29 -0
- package/dist/src/license.d.ts.map +1 -0
- package/{src/license.ts → dist/src/license.js} +42 -113
- package/dist/src/license.js.map +7 -0
- package/dist/src/llm-client.d.ts +23 -0
- package/dist/src/llm-client.d.ts.map +1 -0
- package/{src/llm-client.ts → dist/src/llm-client.js} +22 -55
- package/dist/src/llm-client.js.map +7 -0
- package/dist/src/logger.d.ts +33 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +35 -0
- package/dist/src/logger.js.map +7 -0
- package/dist/src/mcp-server.d.ts +16 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/{src/mcp-server.ts → dist/src/mcp-server.js} +81 -181
- package/dist/src/mcp-server.js.map +7 -0
- package/dist/src/memory-categories.d.ts +40 -0
- package/dist/src/memory-categories.d.ts.map +1 -0
- package/dist/src/memory-categories.js +33 -0
- package/dist/src/memory-categories.js.map +7 -0
- package/dist/src/memory-upgrader.d.ts +71 -0
- package/dist/src/memory-upgrader.d.ts.map +1 -0
- package/dist/src/memory-upgrader.js +238 -0
- package/dist/src/memory-upgrader.js.map +7 -0
- package/dist/src/migrate.d.ts +47 -0
- package/dist/src/migrate.d.ts.map +1 -0
- package/{src/migrate.ts → dist/src/migrate.js} +57 -165
- package/dist/src/migrate.js.map +7 -0
- package/dist/src/mnemo.d.ts +67 -0
- package/dist/src/mnemo.d.ts.map +1 -0
- package/dist/src/mnemo.js +66 -0
- package/dist/src/mnemo.js.map +7 -0
- package/dist/src/noise-filter.d.ts +23 -0
- package/dist/src/noise-filter.d.ts.map +1 -0
- package/dist/src/noise-filter.js +62 -0
- package/dist/src/noise-filter.js.map +7 -0
- package/dist/src/noise-prototypes.d.ts +40 -0
- package/dist/src/noise-prototypes.d.ts.map +1 -0
- package/dist/src/noise-prototypes.js +116 -0
- package/dist/src/noise-prototypes.js.map +7 -0
- package/dist/src/observability.d.ts +16 -0
- package/dist/src/observability.d.ts.map +1 -0
- package/dist/src/observability.js +53 -0
- package/dist/src/observability.js.map +7 -0
- package/dist/src/query-tracker.d.ts +27 -0
- package/dist/src/query-tracker.d.ts.map +1 -0
- package/dist/src/query-tracker.js +32 -0
- package/dist/src/query-tracker.js.map +7 -0
- package/dist/src/reflection-event-store.d.ts +44 -0
- package/dist/src/reflection-event-store.d.ts.map +1 -0
- package/dist/src/reflection-event-store.js +50 -0
- package/dist/src/reflection-event-store.js.map +7 -0
- package/dist/src/reflection-item-store.d.ts +58 -0
- package/dist/src/reflection-item-store.d.ts.map +1 -0
- package/dist/src/reflection-item-store.js +69 -0
- package/dist/src/reflection-item-store.js.map +7 -0
- package/dist/src/reflection-mapped-metadata.d.ts +47 -0
- package/dist/src/reflection-mapped-metadata.d.ts.map +1 -0
- package/dist/src/reflection-mapped-metadata.js +40 -0
- package/dist/src/reflection-mapped-metadata.js.map +7 -0
- package/dist/src/reflection-metadata.d.ts +11 -0
- package/dist/src/reflection-metadata.d.ts.map +1 -0
- package/dist/src/reflection-metadata.js +24 -0
- package/dist/src/reflection-metadata.js.map +7 -0
- package/dist/src/reflection-ranking.d.ts +13 -0
- package/dist/src/reflection-ranking.d.ts.map +1 -0
- package/{src/reflection-ranking.ts → dist/src/reflection-ranking.js} +12 -21
- package/dist/src/reflection-ranking.js.map +7 -0
- package/dist/src/reflection-retry.d.ts +30 -0
- package/dist/src/reflection-retry.d.ts.map +1 -0
- package/{src/reflection-retry.ts → dist/src/reflection-retry.js} +24 -64
- package/dist/src/reflection-retry.js.map +7 -0
- package/dist/src/reflection-slices.d.ts +42 -0
- package/dist/src/reflection-slices.d.ts.map +1 -0
- package/{src/reflection-slices.ts → dist/src/reflection-slices.js} +60 -136
- package/dist/src/reflection-slices.js.map +7 -0
- package/dist/src/reflection-store.d.ts +85 -0
- package/dist/src/reflection-store.d.ts.map +1 -0
- package/dist/src/reflection-store.js +407 -0
- package/dist/src/reflection-store.js.map +7 -0
- package/dist/src/resonance-state.d.ts +19 -0
- package/dist/src/resonance-state.d.ts.map +1 -0
- package/{src/resonance-state.ts → dist/src/resonance-state.js} +13 -42
- package/dist/src/resonance-state.js.map +7 -0
- package/dist/src/retriever.d.ts +228 -0
- package/dist/src/retriever.d.ts.map +1 -0
- package/dist/src/retriever.js +1006 -0
- package/dist/src/retriever.js.map +7 -0
- package/dist/src/scopes.d.ts +58 -0
- package/dist/src/scopes.d.ts.map +1 -0
- package/dist/src/scopes.js +252 -0
- package/dist/src/scopes.js.map +7 -0
- package/dist/src/self-improvement-files.d.ts +20 -0
- package/dist/src/self-improvement-files.d.ts.map +1 -0
- package/{src/self-improvement-files.ts → dist/src/self-improvement-files.js} +24 -49
- package/dist/src/self-improvement-files.js.map +7 -0
- package/dist/src/semantic-gate.d.ts +24 -0
- package/dist/src/semantic-gate.d.ts.map +1 -0
- package/dist/src/semantic-gate.js +86 -0
- package/dist/src/semantic-gate.js.map +7 -0
- package/dist/src/session-recovery.d.ts +9 -0
- package/dist/src/session-recovery.d.ts.map +1 -0
- package/{src/session-recovery.ts → dist/src/session-recovery.js} +40 -57
- package/dist/src/session-recovery.js.map +7 -0
- package/dist/src/smart-extractor.d.ts +107 -0
- package/dist/src/smart-extractor.d.ts.map +1 -0
- package/{src/smart-extractor.ts → dist/src/smart-extractor.js} +130 -383
- package/dist/src/smart-extractor.js.map +7 -0
- package/dist/src/smart-metadata.d.ts +103 -0
- package/dist/src/smart-metadata.d.ts.map +1 -0
- package/dist/src/smart-metadata.js +361 -0
- package/dist/src/smart-metadata.js.map +7 -0
- package/dist/src/storage-adapter.d.ts +102 -0
- package/dist/src/storage-adapter.d.ts.map +1 -0
- package/dist/src/storage-adapter.js +22 -0
- package/dist/src/storage-adapter.js.map +7 -0
- package/dist/src/store.d.ts +108 -0
- package/dist/src/store.d.ts.map +1 -0
- package/dist/src/store.js +939 -0
- package/dist/src/store.js.map +7 -0
- package/dist/src/tier-manager.d.ts +57 -0
- package/dist/src/tier-manager.d.ts.map +1 -0
- package/dist/src/tier-manager.js +80 -0
- package/dist/src/tier-manager.js.map +7 -0
- package/dist/src/tools.d.ts +43 -0
- package/dist/src/tools.d.ts.map +1 -0
- package/dist/src/tools.js +1075 -0
- package/dist/src/tools.js.map +7 -0
- package/dist/src/wal-recovery.d.ts +30 -0
- package/dist/src/wal-recovery.d.ts.map +1 -0
- package/{src/wal-recovery.ts → dist/src/wal-recovery.js} +26 -79
- package/dist/src/wal-recovery.js.map +7 -0
- package/package.json +21 -2
- package/openclaw.plugin.json +0 -815
- package/src/access-tracker.ts +0 -341
- package/src/adapters/README.md +0 -78
- package/src/adapters/qdrant.ts +0 -191
- package/src/adaptive-retrieval.ts +0 -90
- package/src/audit-log.ts +0 -238
- package/src/chunker.ts +0 -254
- package/src/config.ts +0 -271
- package/src/decay-engine.ts +0 -238
- package/src/extraction-prompts.ts +0 -339
- package/src/memory-categories.ts +0 -71
- package/src/memory-upgrader.ts +0 -388
- package/src/mnemo.ts +0 -142
- package/src/noise-filter.ts +0 -97
- package/src/noise-prototypes.ts +0 -164
- package/src/observability.ts +0 -81
- package/src/query-tracker.ts +0 -57
- package/src/reflection-event-store.ts +0 -98
- package/src/reflection-item-store.ts +0 -112
- package/src/reflection-mapped-metadata.ts +0 -84
- package/src/reflection-metadata.ts +0 -23
- package/src/reflection-store.ts +0 -602
- package/src/retriever.ts +0 -1510
- package/src/scopes.ts +0 -375
- package/src/semantic-gate.ts +0 -121
- package/src/smart-metadata.ts +0 -561
- package/src/storage-adapter.ts +0 -153
- package/src/store.ts +0 -1330
- package/src/tier-manager.ts +0 -189
- package/src/tools.ts +0 -1292
- package/test/core.test.mjs +0 -301
|
@@ -1,30 +1,24 @@
|
|
|
1
|
-
// SPDX-License-Identifier: LicenseRef-Mnemo-Pro
|
|
2
1
|
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
2
|
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
export const DEFAULT_LEARNINGS_TEMPLATE = `# Learnings
|
|
3
|
+
const DEFAULT_LEARNINGS_TEMPLATE = `# Learnings
|
|
6
4
|
|
|
7
5
|
Append structured entries:
|
|
8
6
|
- LRN-YYYYMMDD-XXX for corrections / best practices / knowledge gaps
|
|
9
7
|
- Include summary, details, suggested action, metadata, and status`;
|
|
10
|
-
|
|
11
|
-
export const DEFAULT_ERRORS_TEMPLATE = `# Errors
|
|
8
|
+
const DEFAULT_ERRORS_TEMPLATE = `# Errors
|
|
12
9
|
|
|
13
10
|
Append structured entries:
|
|
14
11
|
- ERR-YYYYMMDD-XXX for command/tool/integration failures
|
|
15
12
|
- Include symptom, context, probable cause, and prevention`;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async function withFileWriteQueue<T>(filePath: string, action: () => Promise<T>): Promise<T> {
|
|
13
|
+
const fileWriteQueues = /* @__PURE__ */ new Map();
|
|
14
|
+
async function withFileWriteQueue(filePath, action) {
|
|
20
15
|
const previous = fileWriteQueues.get(filePath) ?? Promise.resolve();
|
|
21
|
-
let release
|
|
22
|
-
const lock = new Promise
|
|
16
|
+
let release;
|
|
17
|
+
const lock = new Promise((resolve) => {
|
|
23
18
|
release = resolve;
|
|
24
19
|
});
|
|
25
20
|
const next = previous.then(() => lock);
|
|
26
21
|
fileWriteQueues.set(filePath, next);
|
|
27
|
-
|
|
28
22
|
await previous;
|
|
29
23
|
try {
|
|
30
24
|
return await action();
|
|
@@ -35,12 +29,10 @@ async function withFileWriteQueue<T>(filePath: string, action: () => Promise<T>)
|
|
|
35
29
|
}
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
|
32
|
+
function todayYmd() {
|
|
33
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
41
34
|
}
|
|
42
|
-
|
|
43
|
-
async function nextLearningId(filePath: string, prefix: "LRN" | "ERR"): Promise<string> {
|
|
35
|
+
async function nextLearningId(filePath, prefix) {
|
|
44
36
|
const date = todayYmd();
|
|
45
37
|
let count = 0;
|
|
46
38
|
try {
|
|
@@ -48,46 +40,25 @@ async function nextLearningId(filePath: string, prefix: "LRN" | "ERR"): Promise<
|
|
|
48
40
|
const matches = content.match(new RegExp(`\\[${prefix}-${date}-\\d{3}\\]`, "g"));
|
|
49
41
|
count = matches?.length ?? 0;
|
|
50
42
|
} catch {
|
|
51
|
-
// ignore
|
|
52
43
|
}
|
|
53
44
|
return `${prefix}-${date}-${String(count + 1).padStart(3, "0")}`;
|
|
54
45
|
}
|
|
55
|
-
|
|
56
|
-
export async function ensureSelfImprovementLearningFiles(baseDir: string): Promise<void> {
|
|
46
|
+
async function ensureSelfImprovementLearningFiles(baseDir) {
|
|
57
47
|
const learningsDir = join(baseDir, ".learnings");
|
|
58
48
|
await mkdir(learningsDir, { recursive: true });
|
|
59
|
-
|
|
60
|
-
const ensureFile = async (filePath: string, content: string) => {
|
|
49
|
+
const ensureFile = async (filePath, content) => {
|
|
61
50
|
try {
|
|
62
51
|
const existing = await readFile(filePath, "utf-8");
|
|
63
52
|
if (existing.trim().length > 0) return;
|
|
64
53
|
} catch {
|
|
65
|
-
// write default below
|
|
66
54
|
}
|
|
67
|
-
await writeFile(filePath, `${content.trim()}
|
|
55
|
+
await writeFile(filePath, `${content.trim()}
|
|
56
|
+
`, "utf-8");
|
|
68
57
|
};
|
|
69
|
-
|
|
70
58
|
await ensureFile(join(learningsDir, "LEARNINGS.md"), DEFAULT_LEARNINGS_TEMPLATE);
|
|
71
59
|
await ensureFile(join(learningsDir, "ERRORS.md"), DEFAULT_ERRORS_TEMPLATE);
|
|
72
60
|
}
|
|
73
|
-
|
|
74
|
-
export interface AppendSelfImprovementEntryParams {
|
|
75
|
-
baseDir: string;
|
|
76
|
-
type: "learning" | "error";
|
|
77
|
-
summary: string;
|
|
78
|
-
details?: string;
|
|
79
|
-
suggestedAction?: string;
|
|
80
|
-
category?: string;
|
|
81
|
-
area?: string;
|
|
82
|
-
priority?: string;
|
|
83
|
-
status?: string;
|
|
84
|
-
source?: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function appendSelfImprovementEntry(params: AppendSelfImprovementEntryParams): Promise<{
|
|
88
|
-
id: string;
|
|
89
|
-
filePath: string;
|
|
90
|
-
}> {
|
|
61
|
+
async function appendSelfImprovementEntry(params) {
|
|
91
62
|
const {
|
|
92
63
|
baseDir,
|
|
93
64
|
type,
|
|
@@ -98,18 +69,16 @@ export async function appendSelfImprovementEntry(params: AppendSelfImprovementEn
|
|
|
98
69
|
area = "config",
|
|
99
70
|
priority = "medium",
|
|
100
71
|
status = "pending",
|
|
101
|
-
source = "mnemo/self_improvement_log"
|
|
72
|
+
source = "mnemo/self_improvement_log"
|
|
102
73
|
} = params;
|
|
103
|
-
|
|
104
74
|
await ensureSelfImprovementLearningFiles(baseDir);
|
|
105
75
|
const learningsDir = join(baseDir, ".learnings");
|
|
106
76
|
const fileName = type === "learning" ? "LEARNINGS.md" : "ERRORS.md";
|
|
107
77
|
const filePath = join(learningsDir, fileName);
|
|
108
78
|
const idPrefix = type === "learning" ? "LRN" : "ERR";
|
|
109
|
-
|
|
110
79
|
const id = await withFileWriteQueue(filePath, async () => {
|
|
111
80
|
const entryId = await nextLearningId(filePath, idPrefix);
|
|
112
|
-
const nowIso = new Date().toISOString();
|
|
81
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
113
82
|
const titleSuffix = type === "learning" ? ` ${category}` : "";
|
|
114
83
|
const entry = [
|
|
115
84
|
`## [${entryId}]${titleSuffix}`,
|
|
@@ -131,13 +100,19 @@ export async function appendSelfImprovementEntry(params: AppendSelfImprovementEn
|
|
|
131
100
|
"### Metadata",
|
|
132
101
|
`- Source: ${source}`,
|
|
133
102
|
"---",
|
|
134
|
-
""
|
|
103
|
+
""
|
|
135
104
|
].join("\n");
|
|
136
105
|
const prev = await readFile(filePath, "utf-8").catch(() => "");
|
|
137
106
|
const separator = prev.trimEnd().length > 0 ? "\n\n" : "";
|
|
138
107
|
await appendFile(filePath, `${separator}${entry}`, "utf-8");
|
|
139
108
|
return entryId;
|
|
140
109
|
});
|
|
141
|
-
|
|
142
110
|
return { id, filePath };
|
|
143
111
|
}
|
|
112
|
+
export {
|
|
113
|
+
DEFAULT_ERRORS_TEMPLATE,
|
|
114
|
+
DEFAULT_LEARNINGS_TEMPLATE,
|
|
115
|
+
appendSelfImprovementEntry,
|
|
116
|
+
ensureSelfImprovementLearningFiles
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=self-improvement-files.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/self-improvement-files.ts"],
|
|
4
|
+
"sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\nimport { appendFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport const DEFAULT_LEARNINGS_TEMPLATE = `# Learnings\n\nAppend structured entries:\n- LRN-YYYYMMDD-XXX for corrections / best practices / knowledge gaps\n- Include summary, details, suggested action, metadata, and status`;\n\nexport const DEFAULT_ERRORS_TEMPLATE = `# Errors\n\nAppend structured entries:\n- ERR-YYYYMMDD-XXX for command/tool/integration failures\n- Include symptom, context, probable cause, and prevention`;\n\nconst fileWriteQueues = new Map<string, Promise<void>>();\n\nasync function withFileWriteQueue<T>(filePath: string, action: () => Promise<T>): Promise<T> {\n const previous = fileWriteQueues.get(filePath) ?? Promise.resolve();\n let release: (() => void) | undefined;\n const lock = new Promise<void>((resolve) => {\n release = resolve;\n });\n const next = previous.then(() => lock);\n fileWriteQueues.set(filePath, next);\n\n await previous;\n try {\n return await action();\n } finally {\n release?.();\n if (fileWriteQueues.get(filePath) === next) {\n fileWriteQueues.delete(filePath);\n }\n }\n}\n\nfunction todayYmd(): string {\n return new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n}\n\nasync function nextLearningId(filePath: string, prefix: \"LRN\" | \"ERR\"): Promise<string> {\n const date = todayYmd();\n let count = 0;\n try {\n const content = await readFile(filePath, \"utf-8\");\n const matches = content.match(new RegExp(`\\\\[${prefix}-${date}-\\\\d{3}\\\\]`, \"g\"));\n count = matches?.length ?? 0;\n } catch {\n // ignore\n }\n return `${prefix}-${date}-${String(count + 1).padStart(3, \"0\")}`;\n}\n\nexport async function ensureSelfImprovementLearningFiles(baseDir: string): Promise<void> {\n const learningsDir = join(baseDir, \".learnings\");\n await mkdir(learningsDir, { recursive: true });\n\n const ensureFile = async (filePath: string, content: string) => {\n try {\n const existing = await readFile(filePath, \"utf-8\");\n if (existing.trim().length > 0) return;\n } catch {\n // write default below\n }\n await writeFile(filePath, `${content.trim()}\\n`, \"utf-8\");\n };\n\n await ensureFile(join(learningsDir, \"LEARNINGS.md\"), DEFAULT_LEARNINGS_TEMPLATE);\n await ensureFile(join(learningsDir, \"ERRORS.md\"), DEFAULT_ERRORS_TEMPLATE);\n}\n\nexport interface AppendSelfImprovementEntryParams {\n baseDir: string;\n type: \"learning\" | \"error\";\n summary: string;\n details?: string;\n suggestedAction?: string;\n category?: string;\n area?: string;\n priority?: string;\n status?: string;\n source?: string;\n}\n\nexport async function appendSelfImprovementEntry(params: AppendSelfImprovementEntryParams): Promise<{\n id: string;\n filePath: string;\n}> {\n const {\n baseDir,\n type,\n summary,\n details = \"\",\n suggestedAction = \"\",\n category = \"best_practice\",\n area = \"config\",\n priority = \"medium\",\n status = \"pending\",\n source = \"mnemo/self_improvement_log\",\n } = params;\n\n await ensureSelfImprovementLearningFiles(baseDir);\n const learningsDir = join(baseDir, \".learnings\");\n const fileName = type === \"learning\" ? \"LEARNINGS.md\" : \"ERRORS.md\";\n const filePath = join(learningsDir, fileName);\n const idPrefix = type === \"learning\" ? \"LRN\" : \"ERR\";\n\n const id = await withFileWriteQueue(filePath, async () => {\n const entryId = await nextLearningId(filePath, idPrefix);\n const nowIso = new Date().toISOString();\n const titleSuffix = type === \"learning\" ? ` ${category}` : \"\";\n const entry = [\n `## [${entryId}]${titleSuffix}`,\n \"\",\n `**Logged**: ${nowIso}`,\n `**Priority**: ${priority}`,\n `**Status**: ${status}`,\n `**Area**: ${area}`,\n \"\",\n \"### Summary\",\n summary.trim(),\n \"\",\n \"### Details\",\n details.trim() || \"-\",\n \"\",\n \"### Suggested Action\",\n suggestedAction.trim() || \"-\",\n \"\",\n \"### Metadata\",\n `- Source: ${source}`,\n \"---\",\n \"\",\n ].join(\"\\n\");\n const prev = await readFile(filePath, \"utf-8\").catch(() => \"\");\n const separator = prev.trimEnd().length > 0 ? \"\\n\\n\" : \"\";\n await appendFile(filePath, `${separator}${entry}`, \"utf-8\");\n return entryId;\n });\n\n return { id, filePath };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Noise Gate
|
|
3
|
+
*
|
|
4
|
+
* Pre-filters memory candidates by checking their embedding similarity against
|
|
5
|
+
* domain-relevant anchor texts. Fragments that are too far from any anchor are
|
|
6
|
+
* rejected as noise before reaching the dedup or store pipeline.
|
|
7
|
+
*/
|
|
8
|
+
import type { Embedder } from "./embedder.js";
|
|
9
|
+
export declare class SemanticGate {
|
|
10
|
+
private readonly embedder;
|
|
11
|
+
private anchorEmbeddings;
|
|
12
|
+
private initPromise;
|
|
13
|
+
private readonly threshold;
|
|
14
|
+
constructor(embedder: Embedder, threshold?: number);
|
|
15
|
+
private ensureInitialized;
|
|
16
|
+
private computeAnchors;
|
|
17
|
+
/**
|
|
18
|
+
* Check whether a memory vector passes the semantic gate.
|
|
19
|
+
* Returns true if the memory is relevant enough to persist.
|
|
20
|
+
*/
|
|
21
|
+
shouldPass(vector: number[], text: string): Promise<boolean>;
|
|
22
|
+
private logFiltered;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=semantic-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-gate.d.ts","sourceRoot":"","sources":["../../src/semantic-gate.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuC9C,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,QAAQ,EAAE,QAAQ,EACnC,SAAS,SAAO;YAKJ,iBAAiB;YAWjB,cAAc;IAS5B;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YA2BpD,WAAW;CAS1B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { appendFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
|
+
const ANCHOR_TEXTS = [
|
|
5
|
+
"\u6295\u8D44\u51B3\u7B56 \u4F30\u503C\u5206\u6790 \u6301\u4ED3\u7BA1\u7406 \u5C3D\u804C\u8C03\u67E5",
|
|
6
|
+
"\u4E2A\u4EBA\u504F\u597D \u65E5\u5E38\u4E60\u60EF \u4EBA\u9645\u5173\u7CFB \u751F\u6D3B\u65B9\u5F0F",
|
|
7
|
+
"\u6280\u672F\u67B6\u6784 \u7CFB\u7EDF\u8BBE\u8BA1 \u4EE3\u7801\u5B9E\u73B0 \u5DE5\u7A0B\u4F18\u5316"
|
|
8
|
+
];
|
|
9
|
+
function cosineSimilarity(a, b) {
|
|
10
|
+
if (a.length !== b.length || a.length === 0) return 0;
|
|
11
|
+
let dot = 0;
|
|
12
|
+
let normA = 0;
|
|
13
|
+
let normB = 0;
|
|
14
|
+
for (let i = 0; i < a.length; i++) {
|
|
15
|
+
dot += a[i] * b[i];
|
|
16
|
+
normA += a[i] * a[i];
|
|
17
|
+
normB += b[i] * b[i];
|
|
18
|
+
}
|
|
19
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
20
|
+
return denom === 0 ? 0 : dot / denom;
|
|
21
|
+
}
|
|
22
|
+
const FILTER_LOG_PATH = join(homedir(), ".openclaw", "memory", "store-filtered.log");
|
|
23
|
+
class SemanticGate {
|
|
24
|
+
constructor(embedder, threshold = 0.2) {
|
|
25
|
+
this.embedder = embedder;
|
|
26
|
+
this.threshold = threshold;
|
|
27
|
+
}
|
|
28
|
+
anchorEmbeddings = null;
|
|
29
|
+
initPromise = null;
|
|
30
|
+
threshold;
|
|
31
|
+
async ensureInitialized() {
|
|
32
|
+
if (this.anchorEmbeddings) return;
|
|
33
|
+
if (this.initPromise) return this.initPromise;
|
|
34
|
+
this.initPromise = this.computeAnchors().catch((err) => {
|
|
35
|
+
this.initPromise = null;
|
|
36
|
+
throw err;
|
|
37
|
+
});
|
|
38
|
+
return this.initPromise;
|
|
39
|
+
}
|
|
40
|
+
async computeAnchors() {
|
|
41
|
+
const embeddings = [];
|
|
42
|
+
for (const text of ANCHOR_TEXTS) {
|
|
43
|
+
const vec = await this.embedder.embed(text);
|
|
44
|
+
embeddings.push(vec);
|
|
45
|
+
}
|
|
46
|
+
this.anchorEmbeddings = embeddings;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check whether a memory vector passes the semantic gate.
|
|
50
|
+
* Returns true if the memory is relevant enough to persist.
|
|
51
|
+
*/
|
|
52
|
+
async shouldPass(vector, text) {
|
|
53
|
+
try {
|
|
54
|
+
await this.ensureInitialized();
|
|
55
|
+
} catch {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (!this.anchorEmbeddings || this.anchorEmbeddings.length === 0) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
let maxSim = 0;
|
|
62
|
+
for (const anchor of this.anchorEmbeddings) {
|
|
63
|
+
const sim = cosineSimilarity(vector, anchor);
|
|
64
|
+
if (sim > maxSim) maxSim = sim;
|
|
65
|
+
}
|
|
66
|
+
if (maxSim < this.threshold) {
|
|
67
|
+
this.logFiltered(text, maxSim).catch(() => {
|
|
68
|
+
});
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
async logFiltered(text, maxSim) {
|
|
74
|
+
try {
|
|
75
|
+
await mkdir(dirname(FILTER_LOG_PATH), { recursive: true });
|
|
76
|
+
const line = `${(/* @__PURE__ */ new Date()).toISOString()} maxSim=${maxSim.toFixed(4)} text=${text.slice(0, 200).replace(/\n/g, " ")}
|
|
77
|
+
`;
|
|
78
|
+
await appendFile(FILTER_LOG_PATH, line, "utf8");
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
SemanticGate
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=semantic-gate.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/semantic-gate.ts"],
|
|
4
|
+
"sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Semantic Noise Gate\n *\n * Pre-filters memory candidates by checking their embedding similarity against\n * domain-relevant anchor texts. Fragments that are too far from any anchor are\n * rejected as noise before reaching the dedup or store pipeline.\n */\n\nimport type { Embedder } from \"./embedder.js\";\nimport { appendFile, mkdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\n\n// ============================================================================\n// Anchor Texts\n// ============================================================================\n\nconst ANCHOR_TEXTS = [\n \"\u6295\u8D44\u51B3\u7B56 \u4F30\u503C\u5206\u6790 \u6301\u4ED3\u7BA1\u7406 \u5C3D\u804C\u8C03\u67E5\",\n \"\u4E2A\u4EBA\u504F\u597D \u65E5\u5E38\u4E60\u60EF \u4EBA\u9645\u5173\u7CFB \u751F\u6D3B\u65B9\u5F0F\",\n \"\u6280\u672F\u67B6\u6784 \u7CFB\u7EDF\u8BBE\u8BA1 \u4EE3\u7801\u5B9E\u73B0 \u5DE5\u7A0B\u4F18\u5316\",\n] as const;\n\n// ============================================================================\n// Cosine Similarity\n// ============================================================================\n\nfunction cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0;\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dot / denom;\n}\n\n// ============================================================================\n// Semantic Gate\n// ============================================================================\n\nconst FILTER_LOG_PATH = join(homedir(), \".openclaw\", \"memory\", \"store-filtered.log\");\n\nexport class SemanticGate {\n private anchorEmbeddings: number[][] | null = null;\n private initPromise: Promise<void> | null = null;\n private readonly threshold: number;\n\n constructor(\n private readonly embedder: Embedder,\n threshold = 0.20,\n ) {\n this.threshold = threshold;\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.anchorEmbeddings) return;\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = this.computeAnchors().catch((err) => {\n this.initPromise = null;\n throw err;\n });\n return this.initPromise;\n }\n\n private async computeAnchors(): Promise<void> {\n const embeddings: number[][] = [];\n for (const text of ANCHOR_TEXTS) {\n const vec = await this.embedder.embed(text);\n embeddings.push(vec);\n }\n this.anchorEmbeddings = embeddings;\n }\n\n /**\n * Check whether a memory vector passes the semantic gate.\n * Returns true if the memory is relevant enough to persist.\n */\n async shouldPass(vector: number[], text: string): Promise<boolean> {\n try {\n await this.ensureInitialized();\n } catch {\n // If anchor computation fails, pass everything through\n return true;\n }\n\n if (!this.anchorEmbeddings || this.anchorEmbeddings.length === 0) {\n return true;\n }\n\n let maxSim = 0;\n for (const anchor of this.anchorEmbeddings) {\n const sim = cosineSimilarity(vector, anchor);\n if (sim > maxSim) maxSim = sim;\n }\n\n if (maxSim < this.threshold) {\n // Log filtered content\n this.logFiltered(text, maxSim).catch(() => {});\n return false;\n }\n\n return true;\n }\n\n private async logFiltered(text: string, maxSim: number): Promise<void> {\n try {\n await mkdir(dirname(FILTER_LOG_PATH), { recursive: true });\n const line = `${new Date().toISOString()} maxSim=${maxSim.toFixed(4)} text=${text.slice(0, 200).replace(/\\n/g, \" \")}\\n`;\n await appendFile(FILTER_LOG_PATH, line, \"utf8\");\n } catch {\n // Non-critical\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAUA,SAAS,YAAY,aAAa;AAClC,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAM9B,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF;AAMA,SAAS,iBAAiB,GAAa,GAAqB;AAC1D,MAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAG,QAAO;AACpD,MAAI,MAAM;AACV,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,WAAO,EAAE,CAAC,IAAI,EAAE,CAAC;AACjB,aAAS,EAAE,CAAC,IAAI,EAAE,CAAC;AACnB,aAAS,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,EACrB;AACA,QAAM,QAAQ,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK;AAChD,SAAO,UAAU,IAAI,IAAI,MAAM;AACjC;AAMA,MAAM,kBAAkB,KAAK,QAAQ,GAAG,aAAa,UAAU,oBAAoB;AAE5E,MAAM,aAAa;AAAA,EAKxB,YACmB,UACjB,YAAY,KACZ;AAFiB;AAGjB,SAAK,YAAY;AAAA,EACnB;AAAA,EATQ,mBAAsC;AAAA,EACtC,cAAoC;AAAA,EAC3B;AAAA,EASjB,MAAc,oBAAmC;AAC/C,QAAI,KAAK,iBAAkB;AAC3B,QAAI,KAAK,YAAa,QAAO,KAAK;AAElC,SAAK,cAAc,KAAK,eAAe,EAAE,MAAM,CAAC,QAAQ;AACtD,WAAK,cAAc;AACnB,YAAM;AAAA,IACR,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,iBAAgC;AAC5C,UAAM,aAAyB,CAAC;AAChC,eAAW,QAAQ,cAAc;AAC/B,YAAM,MAAM,MAAM,KAAK,SAAS,MAAM,IAAI;AAC1C,iBAAW,KAAK,GAAG;AAAA,IACrB;AACA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,QAAkB,MAAgC;AACjE,QAAI;AACF,YAAM,KAAK,kBAAkB;AAAA,IAC/B,QAAQ;AAEN,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,KAAK,oBAAoB,KAAK,iBAAiB,WAAW,GAAG;AAChE,aAAO;AAAA,IACT;AAEA,QAAI,SAAS;AACb,eAAW,UAAU,KAAK,kBAAkB;AAC1C,YAAM,MAAM,iBAAiB,QAAQ,MAAM;AAC3C,UAAI,MAAM,OAAQ,UAAS;AAAA,IAC7B;AAEA,QAAI,SAAS,KAAK,WAAW;AAE3B,WAAK,YAAY,MAAM,MAAM,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAC7C,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAY,MAAc,QAA+B;AACrE,QAAI;AACF,YAAM,MAAM,QAAQ,eAAe,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,YAAM,OAAO,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,WAAW,OAAO,QAAQ,CAAC,CAAC,SAAS,KAAK,MAAM,GAAG,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA;AACnH,YAAM,WAAW,iBAAiB,MAAM,MAAM;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function stripResetSuffix(fileName: string): string;
|
|
2
|
+
export declare function resolveReflectionSessionSearchDirs(params: {
|
|
3
|
+
context: Record<string, unknown>;
|
|
4
|
+
cfg: unknown;
|
|
5
|
+
workspaceDir: string;
|
|
6
|
+
currentSessionFile?: string;
|
|
7
|
+
sourceAgentId?: string;
|
|
8
|
+
}): string[];
|
|
9
|
+
//# sourceMappingURL=session-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-recovery.d.ts","sourceRoot":"","sources":["../../src/session-recovery.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAuCD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,EAAE,CAgFX"}
|
|
@@ -1,46 +1,39 @@
|
|
|
1
|
-
// SPDX-License-Identifier: LicenseRef-Mnemo-Pro
|
|
2
1
|
import { dirname, join } from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (typeof value !== "string") return undefined;
|
|
2
|
+
function asNonEmptyString(value) {
|
|
3
|
+
if (typeof value !== "string") return void 0;
|
|
6
4
|
const trimmed = value.trim();
|
|
7
|
-
return trimmed.length ? trimmed :
|
|
5
|
+
return trimmed.length ? trimmed : void 0;
|
|
8
6
|
}
|
|
9
|
-
|
|
10
|
-
export function stripResetSuffix(fileName: string): string {
|
|
7
|
+
function stripResetSuffix(fileName) {
|
|
11
8
|
const resetIndex = fileName.indexOf(".reset.");
|
|
12
9
|
return resetIndex === -1 ? fileName : fileName.slice(0, resetIndex);
|
|
13
10
|
}
|
|
14
|
-
|
|
15
|
-
function deriveOpenClawHomeFromWorkspacePath(workspacePath: string): string | undefined {
|
|
11
|
+
function deriveOpenClawHomeFromWorkspacePath(workspacePath) {
|
|
16
12
|
const normalized = workspacePath.trim().replace(/[\\/]+$/, "");
|
|
17
|
-
if (!normalized) return
|
|
13
|
+
if (!normalized) return void 0;
|
|
18
14
|
const matched = normalized.match(/^(.*?)[\\/]workspace(?:[\\/].*)?$/);
|
|
19
|
-
if (!matched || !matched[1]) return
|
|
15
|
+
if (!matched || !matched[1]) return void 0;
|
|
20
16
|
const home = matched[1].trim();
|
|
21
|
-
return home.length ? home :
|
|
17
|
+
return home.length ? home : void 0;
|
|
22
18
|
}
|
|
23
|
-
|
|
24
|
-
function deriveOpenClawHomeFromSessionFilePath(sessionFilePath: string): string | undefined {
|
|
19
|
+
function deriveOpenClawHomeFromSessionFilePath(sessionFilePath) {
|
|
25
20
|
const normalized = sessionFilePath.trim();
|
|
26
|
-
if (!normalized) return
|
|
21
|
+
if (!normalized) return void 0;
|
|
27
22
|
const matched = normalized.match(/^(.*?)[\\/]agents[\\/][^\\/]+[\\/]sessions(?:[\\/][^\\/]+)?$/);
|
|
28
|
-
if (!matched || !matched[1]) return
|
|
23
|
+
if (!matched || !matched[1]) return void 0;
|
|
29
24
|
const home = matched[1].trim();
|
|
30
|
-
return home.length ? home :
|
|
25
|
+
return home.length ? home : void 0;
|
|
31
26
|
}
|
|
32
|
-
|
|
33
|
-
function listConfiguredAgentIds(cfg: unknown): string[] {
|
|
27
|
+
function listConfiguredAgentIds(cfg) {
|
|
34
28
|
try {
|
|
35
|
-
const root = cfg
|
|
36
|
-
const agents = root.agents
|
|
37
|
-
const list = agents?.list
|
|
29
|
+
const root = cfg;
|
|
30
|
+
const agents = root.agents;
|
|
31
|
+
const list = agents?.list;
|
|
38
32
|
if (!Array.isArray(list)) return [];
|
|
39
|
-
|
|
40
|
-
const ids: string[] = [];
|
|
33
|
+
const ids = [];
|
|
41
34
|
for (const item of list) {
|
|
42
35
|
if (!item || typeof item !== "object") continue;
|
|
43
|
-
const id = asNonEmptyString(
|
|
36
|
+
const id = asNonEmptyString(item.id);
|
|
44
37
|
if (id) ids.push(id);
|
|
45
38
|
}
|
|
46
39
|
return ids;
|
|
@@ -48,37 +41,28 @@ function listConfiguredAgentIds(cfg: unknown): string[] {
|
|
|
48
41
|
return [];
|
|
49
42
|
}
|
|
50
43
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
workspaceDir: string;
|
|
56
|
-
currentSessionFile?: string;
|
|
57
|
-
sourceAgentId?: string;
|
|
58
|
-
}): string[] {
|
|
59
|
-
const out: string[] = [];
|
|
60
|
-
const seen = new Set<string>();
|
|
61
|
-
const addDir = (value: string | undefined) => {
|
|
44
|
+
function resolveReflectionSessionSearchDirs(params) {
|
|
45
|
+
const out = [];
|
|
46
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47
|
+
const addDir = (value) => {
|
|
62
48
|
const dir = asNonEmptyString(value);
|
|
63
49
|
if (!dir || seen.has(dir)) return;
|
|
64
50
|
seen.add(dir);
|
|
65
51
|
out.push(dir);
|
|
66
52
|
};
|
|
67
|
-
const addHome = (homes
|
|
53
|
+
const addHome = (homes, value) => {
|
|
68
54
|
const home = asNonEmptyString(value);
|
|
69
55
|
if (!home || homes.includes(home)) return;
|
|
70
56
|
homes.push(home);
|
|
71
57
|
};
|
|
72
|
-
const addAgentId = (
|
|
58
|
+
const addAgentId = (agentIds2, value) => {
|
|
73
59
|
const agentId = asNonEmptyString(value);
|
|
74
|
-
if (!agentId || agentId.includes("/") || agentId.includes("\\") ||
|
|
75
|
-
|
|
60
|
+
if (!agentId || agentId.includes("/") || agentId.includes("\\") || agentIds2.includes(agentId)) return;
|
|
61
|
+
agentIds2.push(agentId);
|
|
76
62
|
};
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
const sessionEntry = (params.context.sessionEntry || {}) as Record<string, unknown>;
|
|
63
|
+
const previousSessionEntry = params.context.previousSessionEntry || {};
|
|
64
|
+
const sessionEntry = params.context.sessionEntry || {};
|
|
80
65
|
const sessionEntries = [previousSessionEntry, sessionEntry];
|
|
81
|
-
|
|
82
66
|
if (params.currentSessionFile) addDir(dirname(params.currentSessionFile));
|
|
83
67
|
for (const entry of sessionEntries) {
|
|
84
68
|
const file = asNonEmptyString(entry.sessionFile);
|
|
@@ -87,8 +71,7 @@ export function resolveReflectionSessionSearchDirs(params: {
|
|
|
87
71
|
addDir(asNonEmptyString(entry.sessionDir));
|
|
88
72
|
}
|
|
89
73
|
addDir(join(params.workspaceDir, "sessions"));
|
|
90
|
-
|
|
91
|
-
const openclawHomes: string[] = [];
|
|
74
|
+
const openclawHomes = [];
|
|
92
75
|
addHome(openclawHomes, asNonEmptyString(process.env.OPENCLAW_HOME));
|
|
93
76
|
addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(params.workspaceDir));
|
|
94
77
|
if (params.currentSessionFile) {
|
|
@@ -99,25 +82,22 @@ export function resolveReflectionSessionSearchDirs(params: {
|
|
|
99
82
|
if (entryFile) addHome(openclawHomes, deriveOpenClawHomeFromSessionFilePath(entryFile));
|
|
100
83
|
}
|
|
101
84
|
try {
|
|
102
|
-
const root = params.cfg
|
|
103
|
-
const agents = root.agents
|
|
104
|
-
const defaults = agents?.defaults
|
|
85
|
+
const root = params.cfg;
|
|
86
|
+
const agents = root.agents;
|
|
87
|
+
const defaults = agents?.defaults;
|
|
105
88
|
const defaultWorkspace = asNonEmptyString(defaults?.workspace);
|
|
106
89
|
if (defaultWorkspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(defaultWorkspace));
|
|
107
|
-
|
|
108
|
-
const list = agents?.list as unknown;
|
|
90
|
+
const list = agents?.list;
|
|
109
91
|
if (Array.isArray(list)) {
|
|
110
92
|
for (const item of list) {
|
|
111
93
|
if (!item || typeof item !== "object") continue;
|
|
112
|
-
const workspace = asNonEmptyString(
|
|
94
|
+
const workspace = asNonEmptyString(item.workspace);
|
|
113
95
|
if (workspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(workspace));
|
|
114
96
|
}
|
|
115
97
|
}
|
|
116
98
|
} catch {
|
|
117
|
-
// ignore
|
|
118
99
|
}
|
|
119
|
-
|
|
120
|
-
const agentIds: string[] = [];
|
|
100
|
+
const agentIds = [];
|
|
121
101
|
addAgentId(agentIds, params.sourceAgentId);
|
|
122
102
|
addAgentId(agentIds, asNonEmptyString(params.context.agentId));
|
|
123
103
|
for (const entry of sessionEntries) {
|
|
@@ -127,12 +107,15 @@ export function resolveReflectionSessionSearchDirs(params: {
|
|
|
127
107
|
addAgentId(agentIds, configuredId);
|
|
128
108
|
}
|
|
129
109
|
addAgentId(agentIds, "main");
|
|
130
|
-
|
|
131
110
|
for (const home of openclawHomes) {
|
|
132
111
|
for (const agentId of agentIds) {
|
|
133
112
|
addDir(join(home, "agents", agentId, "sessions"));
|
|
134
113
|
}
|
|
135
114
|
}
|
|
136
|
-
|
|
137
115
|
return out;
|
|
138
116
|
}
|
|
117
|
+
export {
|
|
118
|
+
resolveReflectionSessionSearchDirs,
|
|
119
|
+
stripResetSuffix
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=session-recovery.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/session-recovery.ts"],
|
|
4
|
+
"sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\nimport { dirname, join } from \"node:path\";\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length ? trimmed : undefined;\n}\n\nexport function stripResetSuffix(fileName: string): string {\n const resetIndex = fileName.indexOf(\".reset.\");\n return resetIndex === -1 ? fileName : fileName.slice(0, resetIndex);\n}\n\nfunction deriveOpenClawHomeFromWorkspacePath(workspacePath: string): string | undefined {\n const normalized = workspacePath.trim().replace(/[\\\\/]+$/, \"\");\n if (!normalized) return undefined;\n const matched = normalized.match(/^(.*?)[\\\\/]workspace(?:[\\\\/].*)?$/);\n if (!matched || !matched[1]) return undefined;\n const home = matched[1].trim();\n return home.length ? home : undefined;\n}\n\nfunction deriveOpenClawHomeFromSessionFilePath(sessionFilePath: string): string | undefined {\n const normalized = sessionFilePath.trim();\n if (!normalized) return undefined;\n const matched = normalized.match(/^(.*?)[\\\\/]agents[\\\\/][^\\\\/]+[\\\\/]sessions(?:[\\\\/][^\\\\/]+)?$/);\n if (!matched || !matched[1]) return undefined;\n const home = matched[1].trim();\n return home.length ? home : undefined;\n}\n\nfunction listConfiguredAgentIds(cfg: unknown): string[] {\n try {\n const root = cfg as Record<string, unknown>;\n const agents = root.agents as Record<string, unknown> | undefined;\n const list = agents?.list as unknown;\n if (!Array.isArray(list)) return [];\n\n const ids: string[] = [];\n for (const item of list) {\n if (!item || typeof item !== \"object\") continue;\n const id = asNonEmptyString((item as Record<string, unknown>).id);\n if (id) ids.push(id);\n }\n return ids;\n } catch {\n return [];\n }\n}\n\nexport function resolveReflectionSessionSearchDirs(params: {\n context: Record<string, unknown>;\n cfg: unknown;\n workspaceDir: string;\n currentSessionFile?: string;\n sourceAgentId?: string;\n}): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n const addDir = (value: string | undefined) => {\n const dir = asNonEmptyString(value);\n if (!dir || seen.has(dir)) return;\n seen.add(dir);\n out.push(dir);\n };\n const addHome = (homes: string[], value: string | undefined) => {\n const home = asNonEmptyString(value);\n if (!home || homes.includes(home)) return;\n homes.push(home);\n };\n const addAgentId = (agentIds: string[], value: string | undefined) => {\n const agentId = asNonEmptyString(value);\n if (!agentId || agentId.includes(\"/\") || agentId.includes(\"\\\\\") || agentIds.includes(agentId)) return;\n agentIds.push(agentId);\n };\n\n const previousSessionEntry = (params.context.previousSessionEntry || {}) as Record<string, unknown>;\n const sessionEntry = (params.context.sessionEntry || {}) as Record<string, unknown>;\n const sessionEntries = [previousSessionEntry, sessionEntry];\n\n if (params.currentSessionFile) addDir(dirname(params.currentSessionFile));\n for (const entry of sessionEntries) {\n const file = asNonEmptyString(entry.sessionFile);\n if (file) addDir(dirname(file));\n addDir(asNonEmptyString(entry.sessionsDir));\n addDir(asNonEmptyString(entry.sessionDir));\n }\n addDir(join(params.workspaceDir, \"sessions\"));\n\n const openclawHomes: string[] = [];\n addHome(openclawHomes, asNonEmptyString(process.env.OPENCLAW_HOME));\n addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(params.workspaceDir));\n if (params.currentSessionFile) {\n addHome(openclawHomes, deriveOpenClawHomeFromSessionFilePath(params.currentSessionFile));\n }\n for (const entry of sessionEntries) {\n const entryFile = asNonEmptyString(entry.sessionFile);\n if (entryFile) addHome(openclawHomes, deriveOpenClawHomeFromSessionFilePath(entryFile));\n }\n try {\n const root = params.cfg as Record<string, unknown>;\n const agents = root.agents as Record<string, unknown> | undefined;\n const defaults = agents?.defaults as Record<string, unknown> | undefined;\n const defaultWorkspace = asNonEmptyString(defaults?.workspace);\n if (defaultWorkspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(defaultWorkspace));\n\n const list = agents?.list as unknown;\n if (Array.isArray(list)) {\n for (const item of list) {\n if (!item || typeof item !== \"object\") continue;\n const workspace = asNonEmptyString((item as Record<string, unknown>).workspace);\n if (workspace) addHome(openclawHomes, deriveOpenClawHomeFromWorkspacePath(workspace));\n }\n }\n } catch {\n // ignore\n }\n\n const agentIds: string[] = [];\n addAgentId(agentIds, params.sourceAgentId);\n addAgentId(agentIds, asNonEmptyString(params.context.agentId));\n for (const entry of sessionEntries) {\n addAgentId(agentIds, asNonEmptyString(entry.agentId));\n }\n for (const configuredId of listConfiguredAgentIds(params.cfg)) {\n addAgentId(agentIds, configuredId);\n }\n addAgentId(agentIds, \"main\");\n\n for (const home of openclawHomes) {\n for (const agentId of agentIds) {\n addDir(join(home, \"agents\", agentId, \"sessions\"));\n }\n }\n\n return out;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["agentIds"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Memory Extractor — LLM-powered extraction pipeline
|
|
3
|
+
* Replaces regex-triggered capture with intelligent 6-category extraction.
|
|
4
|
+
*
|
|
5
|
+
* Pipeline: conversation → LLM extract → candidates → dedup → persist
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { MemoryStore } from "./store.js";
|
|
9
|
+
import type { Embedder } from "./embedder.js";
|
|
10
|
+
import type { LlmClient } from "./llm-client.js";
|
|
11
|
+
import { type ExtractionStats } from "./memory-categories.js";
|
|
12
|
+
import type { NoisePrototypeBank } from "./noise-prototypes.js";
|
|
13
|
+
export interface SmartExtractorConfig {
|
|
14
|
+
/** User identifier for extraction prompt. */
|
|
15
|
+
user?: string;
|
|
16
|
+
/** Minimum conversation messages before extraction triggers. */
|
|
17
|
+
extractMinMessages?: number;
|
|
18
|
+
/** Maximum characters of conversation text to process. */
|
|
19
|
+
extractMaxChars?: number;
|
|
20
|
+
/** Default scope for new memories. */
|
|
21
|
+
defaultScope?: string;
|
|
22
|
+
/** Logger function. */
|
|
23
|
+
log?: (msg: string) => void;
|
|
24
|
+
/** Debug logger function. */
|
|
25
|
+
debugLog?: (msg: string) => void;
|
|
26
|
+
/** Optional embedding-based noise prototype bank for language-agnostic noise filtering. */
|
|
27
|
+
noiseBank?: NoisePrototypeBank;
|
|
28
|
+
}
|
|
29
|
+
export interface ExtractPersistOptions {
|
|
30
|
+
/** Target scope for newly created memories. */
|
|
31
|
+
scope?: string;
|
|
32
|
+
/** Scopes visible to the current agent for dedup/merge. */
|
|
33
|
+
scopeFilter?: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare class SmartExtractor {
|
|
36
|
+
private store;
|
|
37
|
+
private embedder;
|
|
38
|
+
private llm;
|
|
39
|
+
private config;
|
|
40
|
+
private log;
|
|
41
|
+
private debugLog;
|
|
42
|
+
constructor(store: MemoryStore, embedder: Embedder, llm: LlmClient, config?: SmartExtractorConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Extract memories from a conversation text and persist them.
|
|
45
|
+
* Returns extraction statistics.
|
|
46
|
+
*/
|
|
47
|
+
extractAndPersist(conversationText: string, sessionKey?: string, options?: ExtractPersistOptions): Promise<ExtractionStats>;
|
|
48
|
+
/**
|
|
49
|
+
* Filter out texts that match noise prototypes by embedding similarity.
|
|
50
|
+
* Long texts (>300 chars) are passed through without checking.
|
|
51
|
+
* Only active when noiseBank is configured and initialized.
|
|
52
|
+
*/
|
|
53
|
+
filterNoiseByEmbedding(texts: string[]): Promise<string[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Feed back conversation text to the noise prototype bank.
|
|
56
|
+
* Called when LLM extraction returns zero candidates (strongest noise signal).
|
|
57
|
+
*/
|
|
58
|
+
private learnAsNoise;
|
|
59
|
+
/**
|
|
60
|
+
* Call LLM to extract candidate memories from conversation text.
|
|
61
|
+
*/
|
|
62
|
+
private extractCandidates;
|
|
63
|
+
/**
|
|
64
|
+
* Process a single candidate memory: dedup → merge/create → store
|
|
65
|
+
*/
|
|
66
|
+
private processCandidate;
|
|
67
|
+
/**
|
|
68
|
+
* Two-stage dedup: vector similarity search → LLM decision.
|
|
69
|
+
*/
|
|
70
|
+
private deduplicate;
|
|
71
|
+
private llmDedupDecision;
|
|
72
|
+
/**
|
|
73
|
+
* Profile always-merge: read existing profile, merge with LLM, upsert.
|
|
74
|
+
*/
|
|
75
|
+
private handleProfileMerge;
|
|
76
|
+
/**
|
|
77
|
+
* Merge a candidate into an existing memory using LLM.
|
|
78
|
+
*/
|
|
79
|
+
private handleMerge;
|
|
80
|
+
/**
|
|
81
|
+
* Handle SUPPORT: update support stats on existing memory for a specific context.
|
|
82
|
+
*/
|
|
83
|
+
private handleSupport;
|
|
84
|
+
/**
|
|
85
|
+
* Handle CONTEXTUALIZE: create a new entry that adds situational nuance,
|
|
86
|
+
* linked to the original via a relation in metadata.
|
|
87
|
+
*/
|
|
88
|
+
private handleContextualize;
|
|
89
|
+
/**
|
|
90
|
+
* Handle CONTRADICT: create contradicting entry + record contradiction evidence
|
|
91
|
+
* on the original memory's support stats.
|
|
92
|
+
*/
|
|
93
|
+
private handleContradict;
|
|
94
|
+
/**
|
|
95
|
+
* Store a candidate memory as a new entry with L0/L1/L2 metadata.
|
|
96
|
+
*/
|
|
97
|
+
private storeCandidate;
|
|
98
|
+
/**
|
|
99
|
+
* Map 6-category to existing 5-category store type for backward compatibility.
|
|
100
|
+
*/
|
|
101
|
+
private mapToStoreCategory;
|
|
102
|
+
/**
|
|
103
|
+
* Get default importance score by category.
|
|
104
|
+
*/
|
|
105
|
+
private getDefaultImportance;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=smart-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart-extractor.d.ts","sourceRoot":"","sources":["../../src/smart-extractor.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOjD,OAAO,EAIL,KAAK,eAAe,EAMrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAmChE,MAAM,WAAW,oBAAoB;IACnC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,2FAA2F;IAC3F,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,qBAAa,cAAc;IAKvB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAPhB,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,QAAQ,CAAwB;gBAG9B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,GAAE,oBAAyB;IAU3C;;;OAGG;IACG,iBAAiB,CACrB,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,MAAkB,EAC9B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,eAAe,CAAC;IA8C3B;;;;OAIG;IACG,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiChE;;;OAGG;YACW,YAAY;IAoB1B;;OAEG;YACW,iBAAiB;IAyF/B;;OAEG;YACW,gBAAgB;IAqG9B;;OAEG;YACW,WAAW;YAqBX,gBAAgB;IA0E9B;;OAEG;YACW,kBAAkB;IAuChC;;OAEG;YACW,WAAW;IA4GzB;;OAEG;YACW,aAAa;IA0B3B;;;OAGG;YACW,mBAAmB;IAsCjC;;;OAGG;YACW,gBAAgB;IAyF9B;;OAEG;YACW,cAAc;IA0C5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAkB7B"}
|