@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
package/src/config.ts
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
/**
|
|
3
|
-
* Shared Configuration Helpers
|
|
4
|
-
* Extracted from index.ts for reuse by MCP server and gateway plugin.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { homedir } from "node:os";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { readFileSync } from "node:fs";
|
|
10
|
-
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Configuration Types
|
|
13
|
-
// ============================================================================
|
|
14
|
-
|
|
15
|
-
export interface PluginConfig {
|
|
16
|
-
embedding: {
|
|
17
|
-
provider: "openai-compatible";
|
|
18
|
-
apiKey: string | string[];
|
|
19
|
-
model?: string;
|
|
20
|
-
baseURL?: string;
|
|
21
|
-
dimensions?: number;
|
|
22
|
-
taskQuery?: string;
|
|
23
|
-
taskPassage?: string;
|
|
24
|
-
normalized?: boolean;
|
|
25
|
-
};
|
|
26
|
-
dbPath?: string;
|
|
27
|
-
autoCapture?: boolean;
|
|
28
|
-
autoRecall?: boolean;
|
|
29
|
-
autoRecallMinLength?: number;
|
|
30
|
-
autoRecallMinRepeated?: number;
|
|
31
|
-
captureAssistant?: boolean;
|
|
32
|
-
retrieval?: {
|
|
33
|
-
mode?: "hybrid" | "vector";
|
|
34
|
-
vectorWeight?: number;
|
|
35
|
-
bm25Weight?: number;
|
|
36
|
-
minScore?: number;
|
|
37
|
-
rerank?: "cross-encoder" | "lightweight" | "none";
|
|
38
|
-
candidatePoolSize?: number;
|
|
39
|
-
rerankApiKey?: string;
|
|
40
|
-
rerankModel?: string;
|
|
41
|
-
rerankEndpoint?: string;
|
|
42
|
-
rerankProvider?: "jina" | "siliconflow" | "voyage" | "pinecone";
|
|
43
|
-
recencyHalfLifeDays?: number;
|
|
44
|
-
recencyWeight?: number;
|
|
45
|
-
filterNoise?: boolean;
|
|
46
|
-
lengthNormAnchor?: number;
|
|
47
|
-
hardMinScore?: number;
|
|
48
|
-
timeDecayHalfLifeDays?: number;
|
|
49
|
-
reinforcementFactor?: number;
|
|
50
|
-
maxHalfLifeMultiplier?: number;
|
|
51
|
-
};
|
|
52
|
-
scopes?: {
|
|
53
|
-
default?: string;
|
|
54
|
-
definitions?: Record<string, { description: string }>;
|
|
55
|
-
agentAccess?: Record<string, string[]>;
|
|
56
|
-
};
|
|
57
|
-
enableManagementTools?: boolean;
|
|
58
|
-
sessionMemory?: { enabled?: boolean; messageCount?: number };
|
|
59
|
-
mdMirror?: { enabled?: boolean; dir?: string };
|
|
60
|
-
autoCaptureLLM?: {
|
|
61
|
-
enabled?: boolean;
|
|
62
|
-
endpoint?: string;
|
|
63
|
-
model?: string;
|
|
64
|
-
timeoutMs?: number;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ============================================================================
|
|
69
|
-
// Helpers
|
|
70
|
-
// ============================================================================
|
|
71
|
-
|
|
72
|
-
export function getDefaultDbPath(): string {
|
|
73
|
-
// Prefer MNEMO_DB_PATH env, then ~/.mnemo/memory-db (open source default),
|
|
74
|
-
// then ~/.openclaw/memory/lancedb-pro (OpenClaw integration fallback)
|
|
75
|
-
if (process.env.MNEMO_DB_PATH) return process.env.MNEMO_DB_PATH;
|
|
76
|
-
const mnemoPath = join(homedir(), ".mnemo", "memory-db");
|
|
77
|
-
const openclawPath = join(homedir(), ".openclaw", "memory", "lancedb-pro");
|
|
78
|
-
try {
|
|
79
|
-
const { existsSync } = require("fs");
|
|
80
|
-
if (existsSync(openclawPath)) return openclawPath;
|
|
81
|
-
} catch {}
|
|
82
|
-
return mnemoPath;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function resolveEnvVars(value: string): string {
|
|
86
|
-
return value.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
|
|
87
|
-
const envValue = process.env[envVar];
|
|
88
|
-
if (!envValue) {
|
|
89
|
-
throw new Error(`Environment variable ${envVar} is not set`);
|
|
90
|
-
}
|
|
91
|
-
return envValue;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function parsePositiveInt(value: unknown): number | undefined {
|
|
96
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
97
|
-
return Math.floor(value);
|
|
98
|
-
}
|
|
99
|
-
if (typeof value === "string") {
|
|
100
|
-
const s = value.trim();
|
|
101
|
-
if (!s) return undefined;
|
|
102
|
-
const resolved = resolveEnvVars(s);
|
|
103
|
-
const n = Number(resolved);
|
|
104
|
-
if (Number.isFinite(n) && n > 0) return Math.floor(n);
|
|
105
|
-
}
|
|
106
|
-
return undefined;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// ============================================================================
|
|
110
|
-
// Config Parser
|
|
111
|
-
// ============================================================================
|
|
112
|
-
|
|
113
|
-
export function parsePluginConfig(value: unknown): PluginConfig {
|
|
114
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
115
|
-
throw new Error("mnemo config required");
|
|
116
|
-
}
|
|
117
|
-
const cfg = value as Record<string, unknown>;
|
|
118
|
-
|
|
119
|
-
const embedding = cfg.embedding as Record<string, unknown> | undefined;
|
|
120
|
-
if (!embedding) {
|
|
121
|
-
throw new Error("embedding config is required");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Accept single key (string) or array of keys for round-robin rotation
|
|
125
|
-
let apiKey: string | string[];
|
|
126
|
-
if (typeof embedding.apiKey === "string") {
|
|
127
|
-
apiKey = embedding.apiKey;
|
|
128
|
-
} else if (Array.isArray(embedding.apiKey) && embedding.apiKey.length > 0) {
|
|
129
|
-
const invalid = embedding.apiKey.findIndex(
|
|
130
|
-
(k: unknown) => typeof k !== "string" || (k as string).trim().length === 0,
|
|
131
|
-
);
|
|
132
|
-
if (invalid !== -1) {
|
|
133
|
-
throw new Error(
|
|
134
|
-
`embedding.apiKey[${invalid}] is invalid: expected non-empty string`,
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
apiKey = embedding.apiKey as string[];
|
|
138
|
-
} else if (embedding.apiKey !== undefined) {
|
|
139
|
-
throw new Error("embedding.apiKey must be a string or non-empty array of strings");
|
|
140
|
-
} else {
|
|
141
|
-
apiKey = process.env.OPENAI_API_KEY || "";
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (!apiKey || (Array.isArray(apiKey) && apiKey.length === 0)) {
|
|
145
|
-
throw new Error("embedding.apiKey is required (set directly or via OPENAI_API_KEY env var)");
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
embedding: {
|
|
150
|
-
provider: "openai-compatible",
|
|
151
|
-
apiKey,
|
|
152
|
-
model:
|
|
153
|
-
typeof embedding.model === "string"
|
|
154
|
-
? embedding.model
|
|
155
|
-
: "text-embedding-3-small",
|
|
156
|
-
baseURL:
|
|
157
|
-
typeof embedding.baseURL === "string"
|
|
158
|
-
? resolveEnvVars(embedding.baseURL)
|
|
159
|
-
: undefined,
|
|
160
|
-
dimensions: parsePositiveInt(embedding.dimensions ?? cfg.dimensions),
|
|
161
|
-
taskQuery:
|
|
162
|
-
typeof embedding.taskQuery === "string"
|
|
163
|
-
? embedding.taskQuery
|
|
164
|
-
: undefined,
|
|
165
|
-
taskPassage:
|
|
166
|
-
typeof embedding.taskPassage === "string"
|
|
167
|
-
? embedding.taskPassage
|
|
168
|
-
: undefined,
|
|
169
|
-
normalized:
|
|
170
|
-
typeof embedding.normalized === "boolean"
|
|
171
|
-
? embedding.normalized
|
|
172
|
-
: undefined,
|
|
173
|
-
},
|
|
174
|
-
dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : undefined,
|
|
175
|
-
autoCapture: cfg.autoCapture !== false,
|
|
176
|
-
autoRecall: cfg.autoRecall === true,
|
|
177
|
-
autoRecallMinLength: parsePositiveInt(cfg.autoRecallMinLength),
|
|
178
|
-
autoRecallMinRepeated: parsePositiveInt(cfg.autoRecallMinRepeated),
|
|
179
|
-
captureAssistant: cfg.captureAssistant === true,
|
|
180
|
-
retrieval:
|
|
181
|
-
typeof cfg.retrieval === "object" && cfg.retrieval !== null
|
|
182
|
-
? (cfg.retrieval as any)
|
|
183
|
-
: undefined,
|
|
184
|
-
scopes:
|
|
185
|
-
typeof cfg.scopes === "object" && cfg.scopes !== null
|
|
186
|
-
? (cfg.scopes as any)
|
|
187
|
-
: undefined,
|
|
188
|
-
enableManagementTools: cfg.enableManagementTools === true,
|
|
189
|
-
sessionMemory:
|
|
190
|
-
typeof cfg.sessionMemory === "object" && cfg.sessionMemory !== null
|
|
191
|
-
? {
|
|
192
|
-
enabled:
|
|
193
|
-
(cfg.sessionMemory as Record<string, unknown>).enabled !== false,
|
|
194
|
-
messageCount:
|
|
195
|
-
typeof (cfg.sessionMemory as Record<string, unknown>)
|
|
196
|
-
.messageCount === "number"
|
|
197
|
-
? ((cfg.sessionMemory as Record<string, unknown>)
|
|
198
|
-
.messageCount as number)
|
|
199
|
-
: undefined,
|
|
200
|
-
}
|
|
201
|
-
: undefined,
|
|
202
|
-
mdMirror:
|
|
203
|
-
typeof cfg.mdMirror === "object" && cfg.mdMirror !== null
|
|
204
|
-
? {
|
|
205
|
-
enabled:
|
|
206
|
-
(cfg.mdMirror as Record<string, unknown>).enabled === true,
|
|
207
|
-
dir:
|
|
208
|
-
typeof (cfg.mdMirror as Record<string, unknown>).dir === "string"
|
|
209
|
-
? ((cfg.mdMirror as Record<string, unknown>).dir as string)
|
|
210
|
-
: undefined,
|
|
211
|
-
}
|
|
212
|
-
: undefined,
|
|
213
|
-
autoCaptureLLM:
|
|
214
|
-
typeof cfg.autoCaptureLLM === "object" && cfg.autoCaptureLLM !== null
|
|
215
|
-
? {
|
|
216
|
-
enabled:
|
|
217
|
-
(cfg.autoCaptureLLM as Record<string, unknown>).enabled === true,
|
|
218
|
-
endpoint:
|
|
219
|
-
typeof (cfg.autoCaptureLLM as Record<string, unknown>).endpoint === "string"
|
|
220
|
-
? ((cfg.autoCaptureLLM as Record<string, unknown>).endpoint as string)
|
|
221
|
-
: undefined,
|
|
222
|
-
model:
|
|
223
|
-
typeof (cfg.autoCaptureLLM as Record<string, unknown>).model === "string"
|
|
224
|
-
? ((cfg.autoCaptureLLM as Record<string, unknown>).model as string)
|
|
225
|
-
: undefined,
|
|
226
|
-
timeoutMs: parsePositiveInt(
|
|
227
|
-
(cfg.autoCaptureLLM as Record<string, unknown>).timeoutMs,
|
|
228
|
-
),
|
|
229
|
-
}
|
|
230
|
-
: undefined,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// ============================================================================
|
|
235
|
-
// Load config from config file
|
|
236
|
-
// Checks: MNEMO_CONFIG env → ~/.mnemo/mnemo.json → ~/.openclaw/openclaw.json
|
|
237
|
-
// ============================================================================
|
|
238
|
-
|
|
239
|
-
export function loadConfigFromOpenClaw(): PluginConfig {
|
|
240
|
-
const { existsSync } = require("fs");
|
|
241
|
-
const envPath = process.env.MNEMO_CONFIG;
|
|
242
|
-
const mnemoPath = join(homedir(), ".mnemo", "mnemo.json");
|
|
243
|
-
const openclawPath = join(homedir(), ".openclaw", "openclaw.json");
|
|
244
|
-
const configPath = envPath || (existsSync(mnemoPath) ? mnemoPath : openclawPath);
|
|
245
|
-
let raw: string;
|
|
246
|
-
try {
|
|
247
|
-
raw = readFileSync(configPath, "utf8");
|
|
248
|
-
} catch (err) {
|
|
249
|
-
throw new Error(
|
|
250
|
-
`Failed to read ${configPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
let json: any;
|
|
255
|
-
try {
|
|
256
|
-
json = JSON.parse(raw);
|
|
257
|
-
} catch (err) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`Failed to parse ${configPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const pluginConfig = json?.plugins?.entries?.["memory-lancedb-pro"]?.config;
|
|
264
|
-
if (!pluginConfig) {
|
|
265
|
-
throw new Error(
|
|
266
|
-
`No config found at plugins.entries["memory-lancedb-pro"].config in ${configPath}`,
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return parsePluginConfig(pluginConfig);
|
|
271
|
-
}
|
package/src/decay-engine.ts
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
/**
|
|
3
|
-
* Decay Engine — Weibull stretched-exponential decay model
|
|
4
|
-
*
|
|
5
|
-
* Composite score = recencyWeight * recency + frequencyWeight * frequency + intrinsicWeight * intrinsic
|
|
6
|
-
*
|
|
7
|
-
* - Recency: Weibull decay with importance-modulated half-life and tier-specific beta
|
|
8
|
-
* - Frequency: Logarithmic saturation with time-weighted access pattern bonus
|
|
9
|
-
* - Intrinsic: importance × confidence
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { MemoryTier } from "./memory-categories.js";
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Types
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
const MS_PER_DAY = 86_400_000;
|
|
19
|
-
|
|
20
|
-
export interface DecayConfig {
|
|
21
|
-
/** Days until recency score halves (default: 30) */
|
|
22
|
-
recencyHalfLifeDays: number;
|
|
23
|
-
/** Weight of recency in composite (default: 0.4) */
|
|
24
|
-
recencyWeight: number;
|
|
25
|
-
/** Weight of access frequency (default: 0.3) */
|
|
26
|
-
frequencyWeight: number;
|
|
27
|
-
/** Weight of importance × confidence (default: 0.3) */
|
|
28
|
-
intrinsicWeight: number;
|
|
29
|
-
/** Below this composite = stale (default: 0.3) */
|
|
30
|
-
staleThreshold: number;
|
|
31
|
-
/** Minimum search boost (default: 0.3) */
|
|
32
|
-
searchBoostMin: number;
|
|
33
|
-
/** Importance modulation coefficient for half-life (default: 1.5) */
|
|
34
|
-
importanceModulation: number;
|
|
35
|
-
/** Weibull beta for Core tier — sub-exponential (default: 0.8) */
|
|
36
|
-
betaCore: number;
|
|
37
|
-
/** Weibull beta for Working tier — standard exponential (default: 1.0) */
|
|
38
|
-
betaWorking: number;
|
|
39
|
-
/** Weibull beta for Peripheral tier — super-exponential (default: 1.3) */
|
|
40
|
-
betaPeripheral: number;
|
|
41
|
-
/** Decay floor for Core memories (default: 0.9) */
|
|
42
|
-
coreDecayFloor: number;
|
|
43
|
-
/** Decay floor for Working memories (default: 0.7) */
|
|
44
|
-
workingDecayFloor: number;
|
|
45
|
-
/** Decay floor for Peripheral memories (default: 0.5) */
|
|
46
|
-
peripheralDecayFloor: number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// NOTE: These weights are initial values pending grid-search optimization.
|
|
50
|
-
export const DEFAULT_DECAY_CONFIG: DecayConfig = {
|
|
51
|
-
recencyHalfLifeDays: 30,
|
|
52
|
-
recencyWeight: 0.4, // initial — pending optimization
|
|
53
|
-
frequencyWeight: 0.3, // initial — pending optimization
|
|
54
|
-
intrinsicWeight: 0.3, // initial — pending optimization
|
|
55
|
-
staleThreshold: 0.3,
|
|
56
|
-
searchBoostMin: 0.3,
|
|
57
|
-
importanceModulation: 1.5,
|
|
58
|
-
betaCore: 0.8,
|
|
59
|
-
betaWorking: 1.0,
|
|
60
|
-
betaPeripheral: 1.3,
|
|
61
|
-
coreDecayFloor: 0.9,
|
|
62
|
-
workingDecayFloor: 0.7,
|
|
63
|
-
peripheralDecayFloor: 0.5,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export interface DecayScore {
|
|
67
|
-
memoryId: string;
|
|
68
|
-
recency: number;
|
|
69
|
-
frequency: number;
|
|
70
|
-
intrinsic: number;
|
|
71
|
-
composite: number;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Minimal memory fields needed for decay calculation. */
|
|
75
|
-
export interface DecayableMemory {
|
|
76
|
-
id: string;
|
|
77
|
-
importance: number;
|
|
78
|
-
confidence: number;
|
|
79
|
-
tier: MemoryTier;
|
|
80
|
-
accessCount: number;
|
|
81
|
-
createdAt: number;
|
|
82
|
-
lastAccessedAt: number;
|
|
83
|
-
/** Emotional salience (0-1). Modulates decay: high salience = slower decay. */
|
|
84
|
-
emotionalSalience: number;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface DecayEngine {
|
|
88
|
-
/** Calculate decay score for a single memory */
|
|
89
|
-
score(memory: DecayableMemory, now?: number): DecayScore;
|
|
90
|
-
/** Calculate decay scores for multiple memories */
|
|
91
|
-
scoreAll(memories: DecayableMemory[], now?: number): DecayScore[];
|
|
92
|
-
/** Apply decay boost to search results (multiplies each score by boost) */
|
|
93
|
-
applySearchBoost(
|
|
94
|
-
results: Array<{ memory: DecayableMemory; score: number }>,
|
|
95
|
-
now?: number,
|
|
96
|
-
): void;
|
|
97
|
-
/** Find stale memories (composite below threshold) */
|
|
98
|
-
getStaleMemories(
|
|
99
|
-
memories: DecayableMemory[],
|
|
100
|
-
now?: number,
|
|
101
|
-
): DecayScore[];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ============================================================================
|
|
105
|
-
// Factory
|
|
106
|
-
// ============================================================================
|
|
107
|
-
|
|
108
|
-
export function createDecayEngine(
|
|
109
|
-
config: DecayConfig = DEFAULT_DECAY_CONFIG,
|
|
110
|
-
): DecayEngine {
|
|
111
|
-
const {
|
|
112
|
-
recencyHalfLifeDays: halfLife,
|
|
113
|
-
recencyWeight: rw,
|
|
114
|
-
frequencyWeight: fw,
|
|
115
|
-
intrinsicWeight: iw,
|
|
116
|
-
staleThreshold,
|
|
117
|
-
searchBoostMin: boostMin,
|
|
118
|
-
importanceModulation: mu,
|
|
119
|
-
betaCore,
|
|
120
|
-
betaWorking,
|
|
121
|
-
betaPeripheral,
|
|
122
|
-
coreDecayFloor,
|
|
123
|
-
workingDecayFloor,
|
|
124
|
-
peripheralDecayFloor,
|
|
125
|
-
} = config;
|
|
126
|
-
|
|
127
|
-
function getTierBeta(tier: MemoryTier): number {
|
|
128
|
-
switch (tier) {
|
|
129
|
-
case "core":
|
|
130
|
-
return betaCore;
|
|
131
|
-
case "working":
|
|
132
|
-
return betaWorking;
|
|
133
|
-
case "peripheral":
|
|
134
|
-
return betaPeripheral;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function getTierFloor(tier: MemoryTier): number {
|
|
139
|
-
switch (tier) {
|
|
140
|
-
case "core":
|
|
141
|
-
return coreDecayFloor;
|
|
142
|
-
case "working":
|
|
143
|
-
return workingDecayFloor;
|
|
144
|
-
case "peripheral":
|
|
145
|
-
return peripheralDecayFloor;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Recency: Weibull stretched-exponential decay with importance + salience modulated half-life.
|
|
151
|
-
* effectiveHL = halfLife * exp(mu * importance) * (1 + salience * 0.5)
|
|
152
|
-
*
|
|
153
|
-
* Salience effect: a memory with salience=1.0 gets 1.5x the half-life.
|
|
154
|
-
* This models the human brain's amygdala tagging: emotionally charged
|
|
155
|
-
* memories decay slower regardless of their "importance" category.
|
|
156
|
-
*/
|
|
157
|
-
function recency(memory: DecayableMemory, now: number): number {
|
|
158
|
-
const lastActive =
|
|
159
|
-
memory.accessCount > 0 ? memory.lastAccessedAt : memory.createdAt;
|
|
160
|
-
const daysSince = Math.max(0, (now - lastActive) / MS_PER_DAY);
|
|
161
|
-
const salience = memory.emotionalSalience ?? 0.3;
|
|
162
|
-
const effectiveHL = halfLife * Math.exp(mu * memory.importance) * (1 + salience * 0.5);
|
|
163
|
-
const lambda = Math.LN2 / effectiveHL;
|
|
164
|
-
const beta = getTierBeta(memory.tier);
|
|
165
|
-
return Math.exp(-lambda * Math.pow(daysSince, beta));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Frequency: logarithmic saturation curve with time-weighted access pattern bonus.
|
|
170
|
-
* base = 1 - exp(-accessCount / 5)
|
|
171
|
-
* For memories with >1 access, a recentness bonus is applied.
|
|
172
|
-
*/
|
|
173
|
-
function frequency(memory: DecayableMemory): number {
|
|
174
|
-
const base = 1 - Math.exp(-memory.accessCount / 5);
|
|
175
|
-
if (memory.accessCount <= 1) return base;
|
|
176
|
-
|
|
177
|
-
const lastActive =
|
|
178
|
-
memory.accessCount > 0 ? memory.lastAccessedAt : memory.createdAt;
|
|
179
|
-
const accessSpanDays = Math.max(
|
|
180
|
-
1,
|
|
181
|
-
(lastActive - memory.createdAt) / MS_PER_DAY,
|
|
182
|
-
);
|
|
183
|
-
const avgGapDays = accessSpanDays / Math.max(memory.accessCount - 1, 1);
|
|
184
|
-
const recentnessBonus = Math.exp(-avgGapDays / 30);
|
|
185
|
-
return base * (0.5 + 0.5 * recentnessBonus);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Intrinsic value: importance × confidence × (1 + salience * 0.3).
|
|
190
|
-
* Salience gives a mild intrinsic boost — emotionally significant memories
|
|
191
|
-
* are inherently more valuable even if importance score is moderate.
|
|
192
|
-
*/
|
|
193
|
-
function intrinsic(memory: DecayableMemory): number {
|
|
194
|
-
const salience = memory.emotionalSalience ?? 0.3;
|
|
195
|
-
return memory.importance * memory.confidence * (1 + salience * 0.3);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function scoreOne(memory: DecayableMemory, now: number): DecayScore {
|
|
199
|
-
const r = recency(memory, now);
|
|
200
|
-
const f = frequency(memory);
|
|
201
|
-
const i = intrinsic(memory);
|
|
202
|
-
const composite = rw * r + fw * f + iw * i;
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
memoryId: memory.id,
|
|
206
|
-
recency: r,
|
|
207
|
-
frequency: f,
|
|
208
|
-
intrinsic: i,
|
|
209
|
-
composite,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return {
|
|
214
|
-
score(memory, now = Date.now()) {
|
|
215
|
-
return scoreOne(memory, now);
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
scoreAll(memories, now = Date.now()) {
|
|
219
|
-
return memories.map((m) => scoreOne(m, now));
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
applySearchBoost(results, now = Date.now()) {
|
|
223
|
-
for (const r of results) {
|
|
224
|
-
const ds = scoreOne(r.memory, now);
|
|
225
|
-
const tierFloor = Math.max(getTierFloor(r.memory.tier), ds.composite);
|
|
226
|
-
const multiplier = boostMin + ((1 - boostMin) * tierFloor);
|
|
227
|
-
r.score *= Math.min(1, Math.max(boostMin, multiplier));
|
|
228
|
-
}
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
getStaleMemories(memories, now = Date.now()) {
|
|
232
|
-
const scores = memories.map((m) => scoreOne(m, now));
|
|
233
|
-
return scores
|
|
234
|
-
.filter((s) => s.composite < staleThreshold)
|
|
235
|
-
.sort((a, b) => a.composite - b.composite);
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
}
|