@mnemopay/sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/index.d.ts +161 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +537 -0
- package/dist/index.js.map +1 -0
- package/dist/langgraph/tools.d.ts +84 -0
- package/dist/langgraph/tools.d.ts.map +1 -0
- package/dist/langgraph/tools.js +129 -0
- package/dist/langgraph/tools.js.map +1 -0
- package/dist/mcp/server.d.ts +21 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +431 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/middleware/anthropic.d.ts +28 -0
- package/dist/middleware/anthropic.d.ts.map +1 -0
- package/dist/middleware/anthropic.js +95 -0
- package/dist/middleware/anthropic.js.map +1 -0
- package/dist/middleware/openai.d.ts +31 -0
- package/dist/middleware/openai.d.ts.map +1 -0
- package/dist/middleware/openai.js +96 -0
- package/dist/middleware/openai.js.map +1 -0
- package/dist/recall/engine.d.ts +109 -0
- package/dist/recall/engine.d.ts.map +1 -0
- package/dist/recall/engine.js +253 -0
- package/dist/recall/engine.js.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Anthropic Middleware — wraps any Anthropic client so memory becomes invisible.
|
|
4
|
+
*
|
|
5
|
+
* Every messages.create call automatically:
|
|
6
|
+
* 1. Recalls the top 5 memories and injects them into the system parameter
|
|
7
|
+
* 2. Calls Anthropic with the enriched request
|
|
8
|
+
* 3. Stores the conversation exchange as a new memory
|
|
9
|
+
* 4. Returns the response exactly as Anthropic would
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AnthropicMiddleware = void 0;
|
|
13
|
+
function formatMemoriesAsContext(memories) {
|
|
14
|
+
if (memories.length === 0)
|
|
15
|
+
return "";
|
|
16
|
+
const lines = memories.map((m, i) => `[Memory ${i + 1}] ${m.content} (relevance: ${m.score.toFixed(2)})`);
|
|
17
|
+
return ("\n\n--- Agent Memory (auto-injected by MnemoPay) ---\n" +
|
|
18
|
+
lines.join("\n") +
|
|
19
|
+
"\n--- End Memory ---\n");
|
|
20
|
+
}
|
|
21
|
+
function extractContent(content) {
|
|
22
|
+
if (typeof content === "string")
|
|
23
|
+
return content;
|
|
24
|
+
return content
|
|
25
|
+
.filter((b) => b.type === "text" && b.text)
|
|
26
|
+
.map((b) => b.text)
|
|
27
|
+
.join("\n");
|
|
28
|
+
}
|
|
29
|
+
class AnthropicMiddleware {
|
|
30
|
+
/**
|
|
31
|
+
* Wrap an Anthropic client instance. Returns a proxy with an identical API,
|
|
32
|
+
* but messages.create auto-injects and stores memories.
|
|
33
|
+
*/
|
|
34
|
+
static wrap(client, agent, opts) {
|
|
35
|
+
const recallLimit = opts?.recallLimit ?? 5;
|
|
36
|
+
const originalCreate = client.messages.create.bind(client.messages);
|
|
37
|
+
const wrappedCreate = async (params, ...rest) => {
|
|
38
|
+
// 1. Recall memories
|
|
39
|
+
const memories = await agent.recall(recallLimit);
|
|
40
|
+
const memoryContext = formatMemoriesAsContext(memories);
|
|
41
|
+
// 2. Inject into system parameter
|
|
42
|
+
let system = params.system;
|
|
43
|
+
if (memoryContext) {
|
|
44
|
+
if (typeof system === "string") {
|
|
45
|
+
system = system + memoryContext;
|
|
46
|
+
}
|
|
47
|
+
else if (Array.isArray(system)) {
|
|
48
|
+
system = [
|
|
49
|
+
...system,
|
|
50
|
+
{ type: "text", text: memoryContext },
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
system = `You are a helpful assistant with persistent memory.${memoryContext}`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 3. Call Anthropic
|
|
58
|
+
const response = await originalCreate({ ...params, system }, ...rest);
|
|
59
|
+
// 4. Store the exchange as a memory
|
|
60
|
+
try {
|
|
61
|
+
const lastUser = [...params.messages].reverse().find((m) => m.role === "user");
|
|
62
|
+
const userText = lastUser ? extractContent(lastUser.content).slice(0, 300) : "[no input]";
|
|
63
|
+
const assistantText = response?.content
|
|
64
|
+
?.filter((b) => b.type === "text")
|
|
65
|
+
?.map((b) => b.text)
|
|
66
|
+
?.join("\n")
|
|
67
|
+
?.slice(0, 300) ?? "[no response]";
|
|
68
|
+
await agent.remember(`User: ${userText}\nAssistant: ${assistantText}`);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Non-blocking
|
|
72
|
+
}
|
|
73
|
+
return response;
|
|
74
|
+
};
|
|
75
|
+
const proxy = new Proxy(client, {
|
|
76
|
+
get(target, prop) {
|
|
77
|
+
if (prop === "memories")
|
|
78
|
+
return agent;
|
|
79
|
+
if (prop === "messages") {
|
|
80
|
+
return new Proxy(target.messages, {
|
|
81
|
+
get(msgTarget, msgProp) {
|
|
82
|
+
if (msgProp === "create")
|
|
83
|
+
return wrappedCreate;
|
|
84
|
+
return msgTarget[msgProp];
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return target[prop];
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
return proxy;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.AnthropicMiddleware = AnthropicMiddleware;
|
|
95
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/middleware/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Middleware — wraps any OpenAI client so memory becomes invisible.
|
|
3
|
+
*
|
|
4
|
+
* Every chat.completions.create call automatically:
|
|
5
|
+
* 1. Recalls the top 5 memories and injects them as system context
|
|
6
|
+
* 2. Calls OpenAI with the enriched messages
|
|
7
|
+
* 3. Stores the conversation exchange as a new memory
|
|
8
|
+
* 4. Returns the response exactly as OpenAI would
|
|
9
|
+
*/
|
|
10
|
+
import type { MnemoPayLite, MnemoPay } from "../index.js";
|
|
11
|
+
type Agent = MnemoPayLite | MnemoPay;
|
|
12
|
+
interface OpenAILike {
|
|
13
|
+
chat: {
|
|
14
|
+
completions: {
|
|
15
|
+
create: (...args: any[]) => Promise<any>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare class MnemoPayMiddleware {
|
|
20
|
+
/**
|
|
21
|
+
* Wrap an OpenAI client instance. Returns a proxy with an identical API,
|
|
22
|
+
* but chat.completions.create auto-injects and stores memories.
|
|
23
|
+
*/
|
|
24
|
+
static wrap<T extends OpenAILike>(client: T, agent: Agent, opts?: {
|
|
25
|
+
recallLimit?: number;
|
|
26
|
+
}): T & {
|
|
27
|
+
memories: Agent;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/middleware/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAU,MAAM,aAAa,CAAC;AAElE,KAAK,KAAK,GAAG,YAAY,GAAG,QAAQ,CAAC;AAmCrC,UAAU,UAAU;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;SAC1C,CAAC;KACH,CAAC;CACH;AAED,qBAAa,kBAAkB;IAC7B;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,UAAU,EAC9B,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,KAAK,EACZ,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9B,CAAC,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE;CAiE3B"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI Middleware — wraps any OpenAI client so memory becomes invisible.
|
|
4
|
+
*
|
|
5
|
+
* Every chat.completions.create call automatically:
|
|
6
|
+
* 1. Recalls the top 5 memories and injects them as system context
|
|
7
|
+
* 2. Calls OpenAI with the enriched messages
|
|
8
|
+
* 3. Stores the conversation exchange as a new memory
|
|
9
|
+
* 4. Returns the response exactly as OpenAI would
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MnemoPayMiddleware = void 0;
|
|
13
|
+
function formatMemoriesAsContext(memories) {
|
|
14
|
+
if (memories.length === 0)
|
|
15
|
+
return "";
|
|
16
|
+
const lines = memories.map((m, i) => `[Memory ${i + 1}] ${m.content} (relevance: ${m.score.toFixed(2)})`);
|
|
17
|
+
return ("\n\n--- Agent Memory (auto-injected by MnemoPay) ---\n" +
|
|
18
|
+
lines.join("\n") +
|
|
19
|
+
"\n--- End Memory ---\n");
|
|
20
|
+
}
|
|
21
|
+
function extractExchange(messages, response) {
|
|
22
|
+
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
23
|
+
const assistantContent = response?.choices?.[0]?.message?.content ?? "[no response]";
|
|
24
|
+
const userContent = typeof lastUser?.content === "string" ? lastUser.content : "[no user message]";
|
|
25
|
+
return `User: ${userContent.slice(0, 300)}\nAssistant: ${assistantContent.slice(0, 300)}`;
|
|
26
|
+
}
|
|
27
|
+
class MnemoPayMiddleware {
|
|
28
|
+
/**
|
|
29
|
+
* Wrap an OpenAI client instance. Returns a proxy with an identical API,
|
|
30
|
+
* but chat.completions.create auto-injects and stores memories.
|
|
31
|
+
*/
|
|
32
|
+
static wrap(client, agent, opts) {
|
|
33
|
+
const recallLimit = opts?.recallLimit ?? 5;
|
|
34
|
+
const originalCreate = client.chat.completions.create.bind(client.chat.completions);
|
|
35
|
+
const wrappedCreate = async (params, ...rest) => {
|
|
36
|
+
// 1. Recall memories
|
|
37
|
+
const memories = await agent.recall(recallLimit);
|
|
38
|
+
const memoryContext = formatMemoriesAsContext(memories);
|
|
39
|
+
// 2. Inject into system message
|
|
40
|
+
const enrichedMessages = [...params.messages];
|
|
41
|
+
if (memoryContext) {
|
|
42
|
+
const systemIdx = enrichedMessages.findIndex((m) => m.role === "system");
|
|
43
|
+
if (systemIdx >= 0) {
|
|
44
|
+
enrichedMessages[systemIdx] = {
|
|
45
|
+
...enrichedMessages[systemIdx],
|
|
46
|
+
content: (enrichedMessages[systemIdx].content || "") + memoryContext,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
enrichedMessages.unshift({
|
|
51
|
+
role: "system",
|
|
52
|
+
content: `You are a helpful assistant with persistent memory.${memoryContext}`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 3. Call OpenAI
|
|
57
|
+
const response = await originalCreate({ ...params, messages: enrichedMessages }, ...rest);
|
|
58
|
+
// 4. Store the exchange as a memory
|
|
59
|
+
try {
|
|
60
|
+
const exchange = extractExchange(params.messages, response);
|
|
61
|
+
await agent.remember(exchange);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Non-blocking: don't fail the response if memory store fails
|
|
65
|
+
}
|
|
66
|
+
return response;
|
|
67
|
+
};
|
|
68
|
+
// Create a proxy that intercepts chat.completions.create
|
|
69
|
+
const proxy = new Proxy(client, {
|
|
70
|
+
get(target, prop) {
|
|
71
|
+
if (prop === "memories")
|
|
72
|
+
return agent;
|
|
73
|
+
if (prop === "chat") {
|
|
74
|
+
return new Proxy(target.chat, {
|
|
75
|
+
get(chatTarget, chatProp) {
|
|
76
|
+
if (chatProp === "completions") {
|
|
77
|
+
return new Proxy(chatTarget.completions, {
|
|
78
|
+
get(compTarget, compProp) {
|
|
79
|
+
if (compProp === "create")
|
|
80
|
+
return wrappedCreate;
|
|
81
|
+
return compTarget[compProp];
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return chatTarget[chatProp];
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return target[prop];
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
return proxy;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.MnemoPayMiddleware = MnemoPayMiddleware;
|
|
96
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/middleware/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable Recall Engine — adds semantic search to MnemoPay.
|
|
3
|
+
*
|
|
4
|
+
* Strategies:
|
|
5
|
+
* "score" — Current: importance × recency × frequency (default, zero deps)
|
|
6
|
+
* "vector" — Embeddings-based cosine similarity (requires OpenAI or local provider)
|
|
7
|
+
* "hybrid" — Score + Vector combined (best quality, higher latency)
|
|
8
|
+
*
|
|
9
|
+
* All strategies are compatible with the feedback loop — settle() still reinforces results.
|
|
10
|
+
*/
|
|
11
|
+
export type RecallStrategy = "score" | "vector" | "hybrid";
|
|
12
|
+
export type EmbeddingProvider = "openai" | "local";
|
|
13
|
+
export interface RecallEngineConfig {
|
|
14
|
+
strategy: RecallStrategy;
|
|
15
|
+
/** Embedding provider for vector/hybrid modes */
|
|
16
|
+
embeddingProvider?: EmbeddingProvider;
|
|
17
|
+
/** OpenAI API key (required if provider is "openai") */
|
|
18
|
+
openaiApiKey?: string;
|
|
19
|
+
/** OpenAI embedding model (default: "text-embedding-3-small") */
|
|
20
|
+
embeddingModel?: string;
|
|
21
|
+
/** Embedding dimensions (default: 1536 for OpenAI, 384 for local) */
|
|
22
|
+
dimensions?: number;
|
|
23
|
+
/** Weight for score component in hybrid mode (0-1, default: 0.4) */
|
|
24
|
+
scoreWeight?: number;
|
|
25
|
+
/** Weight for vector component in hybrid mode (0-1, default: 0.6) */
|
|
26
|
+
vectorWeight?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface VectorMemory {
|
|
29
|
+
id: string;
|
|
30
|
+
content: string;
|
|
31
|
+
importance: number;
|
|
32
|
+
embedding: Float32Array;
|
|
33
|
+
createdAt: Date;
|
|
34
|
+
lastAccessed: Date;
|
|
35
|
+
accessCount: number;
|
|
36
|
+
tags: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface RecallResult {
|
|
39
|
+
id: string;
|
|
40
|
+
content: string;
|
|
41
|
+
importance: number;
|
|
42
|
+
score: number;
|
|
43
|
+
vectorScore?: number;
|
|
44
|
+
combinedScore: number;
|
|
45
|
+
createdAt: Date;
|
|
46
|
+
lastAccessed: Date;
|
|
47
|
+
accessCount: number;
|
|
48
|
+
tags: string[];
|
|
49
|
+
}
|
|
50
|
+
export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
51
|
+
export declare function l2Normalize(vec: Float32Array): Float32Array;
|
|
52
|
+
/**
|
|
53
|
+
* Local embedding: TF-IDF-style hashing into a fixed-dimension vector.
|
|
54
|
+
* No external API needed. Good enough for semantic similarity in small corpora.
|
|
55
|
+
*/
|
|
56
|
+
export declare function localEmbed(text: string, dimensions?: number): Float32Array;
|
|
57
|
+
export declare class RecallEngine {
|
|
58
|
+
private config;
|
|
59
|
+
private vectors;
|
|
60
|
+
constructor(config?: Partial<RecallEngineConfig>);
|
|
61
|
+
get strategy(): RecallStrategy;
|
|
62
|
+
/**
|
|
63
|
+
* Generate embedding for content and cache it.
|
|
64
|
+
*/
|
|
65
|
+
embed(id: string, content: string): Promise<Float32Array>;
|
|
66
|
+
/**
|
|
67
|
+
* Get cached embedding or generate new one.
|
|
68
|
+
*/
|
|
69
|
+
getOrEmbed(id: string, content: string): Promise<Float32Array>;
|
|
70
|
+
/**
|
|
71
|
+
* Remove embedding from cache.
|
|
72
|
+
*/
|
|
73
|
+
remove(id: string): void;
|
|
74
|
+
/**
|
|
75
|
+
* Remove multiple embeddings from cache.
|
|
76
|
+
*/
|
|
77
|
+
removeBatch(ids: string[]): void;
|
|
78
|
+
/**
|
|
79
|
+
* Clear all cached embeddings.
|
|
80
|
+
*/
|
|
81
|
+
clear(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Semantic search: find memories similar to a query.
|
|
84
|
+
*/
|
|
85
|
+
search(query: string, memories: Array<{
|
|
86
|
+
id: string;
|
|
87
|
+
content: string;
|
|
88
|
+
importance: number;
|
|
89
|
+
score: number;
|
|
90
|
+
createdAt: Date;
|
|
91
|
+
lastAccessed: Date;
|
|
92
|
+
accessCount: number;
|
|
93
|
+
tags: string[];
|
|
94
|
+
}>, limit: number): Promise<RecallResult[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Embed a query string.
|
|
97
|
+
*/
|
|
98
|
+
private embedQuery;
|
|
99
|
+
/**
|
|
100
|
+
* Get engine stats.
|
|
101
|
+
*/
|
|
102
|
+
stats(): {
|
|
103
|
+
strategy: string;
|
|
104
|
+
cachedEmbeddings: number;
|
|
105
|
+
dimensions: number;
|
|
106
|
+
provider: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/recall/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3D,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,YAAY,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAID,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAazE;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAQ3D;AA0BD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,YAAY,CAwCvE;AA+BD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAwC;gBAE3C,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAYpD,IAAI,QAAQ,IAAI,cAAc,CAE7B;IAED;;OAEG;IACG,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAa/D;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAMpE;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIxB;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAIhC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,IAAI,CAAC;QAChB,YAAY,EAAE,IAAI,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,EACF,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,EAAE,CAAC;IAiD1B;;OAEG;YACW,UAAU;IAOxB;;OAEG;IACH,KAAK,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;CAQ9F"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pluggable Recall Engine — adds semantic search to MnemoPay.
|
|
4
|
+
*
|
|
5
|
+
* Strategies:
|
|
6
|
+
* "score" — Current: importance × recency × frequency (default, zero deps)
|
|
7
|
+
* "vector" — Embeddings-based cosine similarity (requires OpenAI or local provider)
|
|
8
|
+
* "hybrid" — Score + Vector combined (best quality, higher latency)
|
|
9
|
+
*
|
|
10
|
+
* All strategies are compatible with the feedback loop — settle() still reinforces results.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RecallEngine = void 0;
|
|
14
|
+
exports.cosineSimilarity = cosineSimilarity;
|
|
15
|
+
exports.l2Normalize = l2Normalize;
|
|
16
|
+
exports.localEmbed = localEmbed;
|
|
17
|
+
// ─── Math: Cosine Similarity ────────────────────────────────────────────────
|
|
18
|
+
function cosineSimilarity(a, b) {
|
|
19
|
+
if (a.length !== b.length)
|
|
20
|
+
throw new Error(`Dimension mismatch: ${a.length} vs ${b.length}`);
|
|
21
|
+
let dot = 0;
|
|
22
|
+
let normA = 0;
|
|
23
|
+
let normB = 0;
|
|
24
|
+
for (let i = 0; i < a.length; i++) {
|
|
25
|
+
dot += a[i] * b[i];
|
|
26
|
+
normA += a[i] * a[i];
|
|
27
|
+
normB += b[i] * b[i];
|
|
28
|
+
}
|
|
29
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
30
|
+
if (denom === 0)
|
|
31
|
+
return 0;
|
|
32
|
+
return dot / denom;
|
|
33
|
+
}
|
|
34
|
+
// ─── Math: L2 Normalize ────────────────────────────────────────────────────
|
|
35
|
+
function l2Normalize(vec) {
|
|
36
|
+
let norm = 0;
|
|
37
|
+
for (let i = 0; i < vec.length; i++)
|
|
38
|
+
norm += vec[i] * vec[i];
|
|
39
|
+
norm = Math.sqrt(norm);
|
|
40
|
+
if (norm === 0)
|
|
41
|
+
return vec;
|
|
42
|
+
const result = new Float32Array(vec.length);
|
|
43
|
+
for (let i = 0; i < vec.length; i++)
|
|
44
|
+
result[i] = vec[i] / norm;
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
// ─── Local Embedding (TF-IDF bag-of-words, zero dependencies) ──────────────
|
|
48
|
+
const STOP_WORDS = new Set([
|
|
49
|
+
"the", "a", "an", "is", "are", "was", "were", "be", "been", "being",
|
|
50
|
+
"have", "has", "had", "do", "does", "did", "will", "would", "could",
|
|
51
|
+
"should", "may", "might", "shall", "can", "to", "of", "in", "for",
|
|
52
|
+
"on", "with", "at", "by", "from", "as", "into", "through", "during",
|
|
53
|
+
"before", "after", "above", "below", "between", "out", "off", "over",
|
|
54
|
+
"under", "again", "further", "then", "once", "and", "but", "or", "nor",
|
|
55
|
+
"not", "so", "yet", "both", "each", "few", "more", "most", "other",
|
|
56
|
+
"some", "such", "no", "only", "own", "same", "than", "too", "very",
|
|
57
|
+
"just", "because", "about", "up", "it", "its", "this", "that", "these",
|
|
58
|
+
"those", "i", "me", "my", "we", "our", "you", "your", "he", "him",
|
|
59
|
+
"his", "she", "her", "they", "them", "their", "what", "which", "who",
|
|
60
|
+
]);
|
|
61
|
+
function tokenize(text) {
|
|
62
|
+
return text
|
|
63
|
+
.toLowerCase()
|
|
64
|
+
.replace(/[^a-z0-9\s]/g, " ")
|
|
65
|
+
.split(/\s+/)
|
|
66
|
+
.filter((w) => w.length > 1 && !STOP_WORDS.has(w));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Local embedding: TF-IDF-style hashing into a fixed-dimension vector.
|
|
70
|
+
* No external API needed. Good enough for semantic similarity in small corpora.
|
|
71
|
+
*/
|
|
72
|
+
function localEmbed(text, dimensions = 384) {
|
|
73
|
+
const tokens = tokenize(text);
|
|
74
|
+
const vec = new Float32Array(dimensions);
|
|
75
|
+
// Hash each token into multiple dimensions (simulated IDF weighting)
|
|
76
|
+
for (const token of tokens) {
|
|
77
|
+
// FNV-1a hash for distribution
|
|
78
|
+
let hash = 2166136261;
|
|
79
|
+
for (let i = 0; i < token.length; i++) {
|
|
80
|
+
hash ^= token.charCodeAt(i);
|
|
81
|
+
hash = Math.imul(hash, 16777619);
|
|
82
|
+
}
|
|
83
|
+
// Map to 3 dimensions per token for better coverage
|
|
84
|
+
const idx1 = Math.abs(hash) % dimensions;
|
|
85
|
+
const idx2 = Math.abs(hash * 31) % dimensions;
|
|
86
|
+
const idx3 = Math.abs(hash * 97) % dimensions;
|
|
87
|
+
// Weight by inverse token length (longer = more specific = higher weight)
|
|
88
|
+
const weight = 1 + Math.log(token.length);
|
|
89
|
+
vec[idx1] += weight;
|
|
90
|
+
vec[idx2] += weight * 0.5;
|
|
91
|
+
vec[idx3] += weight * 0.3;
|
|
92
|
+
// Prefix hash for fuzzy stem matching (e.g. "deploy" ≈ "deployment")
|
|
93
|
+
if (token.length > 4) {
|
|
94
|
+
const prefix = token.slice(0, 4);
|
|
95
|
+
let ph = 2166136261;
|
|
96
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
97
|
+
ph ^= prefix.charCodeAt(i);
|
|
98
|
+
ph = Math.imul(ph, 16777619);
|
|
99
|
+
}
|
|
100
|
+
const pi1 = Math.abs(ph) % dimensions;
|
|
101
|
+
const pi2 = Math.abs(ph * 31) % dimensions;
|
|
102
|
+
vec[pi1] += weight * 0.3;
|
|
103
|
+
vec[pi2] += weight * 0.15;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return l2Normalize(vec);
|
|
107
|
+
}
|
|
108
|
+
// ─── OpenAI Embedding ───────────────────────────────────────────────────────
|
|
109
|
+
async function openaiEmbed(text, apiKey, model = "text-embedding-3-small") {
|
|
110
|
+
const res = await fetch("https://api.openai.com/v1/embeddings", {
|
|
111
|
+
method: "POST",
|
|
112
|
+
headers: {
|
|
113
|
+
Authorization: `Bearer ${apiKey}`,
|
|
114
|
+
"Content-Type": "application/json",
|
|
115
|
+
},
|
|
116
|
+
body: JSON.stringify({ input: text, model }),
|
|
117
|
+
});
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
const err = await res.text().catch(() => "");
|
|
120
|
+
throw new Error(`OpenAI Embeddings ${res.status}: ${err}`);
|
|
121
|
+
}
|
|
122
|
+
const data = (await res.json());
|
|
123
|
+
const embedding = data.data?.[0]?.embedding;
|
|
124
|
+
if (!embedding)
|
|
125
|
+
throw new Error("No embedding returned");
|
|
126
|
+
return new Float32Array(embedding);
|
|
127
|
+
}
|
|
128
|
+
// ─── Recall Engine ──────────────────────────────────────────────────────────
|
|
129
|
+
class RecallEngine {
|
|
130
|
+
config;
|
|
131
|
+
vectors = new Map();
|
|
132
|
+
constructor(config = {}) {
|
|
133
|
+
this.config = {
|
|
134
|
+
strategy: config.strategy ?? "score",
|
|
135
|
+
embeddingProvider: config.embeddingProvider ?? "local",
|
|
136
|
+
openaiApiKey: config.openaiApiKey ?? process.env.OPENAI_API_KEY ?? "",
|
|
137
|
+
embeddingModel: config.embeddingModel ?? "text-embedding-3-small",
|
|
138
|
+
dimensions: config.dimensions ?? (config.embeddingProvider === "openai" ? 1536 : 384),
|
|
139
|
+
scoreWeight: config.scoreWeight ?? 0.4,
|
|
140
|
+
vectorWeight: config.vectorWeight ?? 0.6,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
get strategy() {
|
|
144
|
+
return this.config.strategy;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate embedding for content and cache it.
|
|
148
|
+
*/
|
|
149
|
+
async embed(id, content) {
|
|
150
|
+
let vec;
|
|
151
|
+
if (this.config.embeddingProvider === "openai" && this.config.openaiApiKey) {
|
|
152
|
+
vec = await openaiEmbed(content, this.config.openaiApiKey, this.config.embeddingModel);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
vec = localEmbed(content, this.config.dimensions);
|
|
156
|
+
}
|
|
157
|
+
this.vectors.set(id, vec);
|
|
158
|
+
return vec;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get cached embedding or generate new one.
|
|
162
|
+
*/
|
|
163
|
+
async getOrEmbed(id, content) {
|
|
164
|
+
const cached = this.vectors.get(id);
|
|
165
|
+
if (cached)
|
|
166
|
+
return cached;
|
|
167
|
+
return this.embed(id, content);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Remove embedding from cache.
|
|
171
|
+
*/
|
|
172
|
+
remove(id) {
|
|
173
|
+
this.vectors.delete(id);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Remove multiple embeddings from cache.
|
|
177
|
+
*/
|
|
178
|
+
removeBatch(ids) {
|
|
179
|
+
for (const id of ids)
|
|
180
|
+
this.vectors.delete(id);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Clear all cached embeddings.
|
|
184
|
+
*/
|
|
185
|
+
clear() {
|
|
186
|
+
this.vectors.clear();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Semantic search: find memories similar to a query.
|
|
190
|
+
*/
|
|
191
|
+
async search(query, memories, limit) {
|
|
192
|
+
const strategy = this.config.strategy;
|
|
193
|
+
// Pure score mode — same as current behavior
|
|
194
|
+
if (strategy === "score") {
|
|
195
|
+
return memories
|
|
196
|
+
.sort((a, b) => b.score - a.score)
|
|
197
|
+
.slice(0, limit)
|
|
198
|
+
.map((m) => ({
|
|
199
|
+
...m,
|
|
200
|
+
combinedScore: m.score,
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
// Vector or hybrid — need embeddings
|
|
204
|
+
const queryVec = await this.embedQuery(query);
|
|
205
|
+
// Ensure all memories have embeddings
|
|
206
|
+
await Promise.all(memories.map((m) => this.getOrEmbed(m.id, m.content)));
|
|
207
|
+
const scored = memories.map((m) => {
|
|
208
|
+
const memVec = this.vectors.get(m.id);
|
|
209
|
+
const vectorScore = memVec ? cosineSimilarity(queryVec, memVec) : 0;
|
|
210
|
+
let combinedScore;
|
|
211
|
+
if (strategy === "vector") {
|
|
212
|
+
// Pure vector: similarity * importance (importance still matters)
|
|
213
|
+
combinedScore = vectorScore * (0.5 + 0.5 * m.importance);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Hybrid: weighted combination
|
|
217
|
+
const normalizedScore = m.score / Math.max(m.score, 1);
|
|
218
|
+
combinedScore =
|
|
219
|
+
this.config.scoreWeight * normalizedScore +
|
|
220
|
+
this.config.vectorWeight * vectorScore;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
...m,
|
|
224
|
+
vectorScore,
|
|
225
|
+
combinedScore,
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
scored.sort((a, b) => b.combinedScore - a.combinedScore);
|
|
229
|
+
return scored.slice(0, limit);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Embed a query string.
|
|
233
|
+
*/
|
|
234
|
+
async embedQuery(query) {
|
|
235
|
+
if (this.config.embeddingProvider === "openai" && this.config.openaiApiKey) {
|
|
236
|
+
return openaiEmbed(query, this.config.openaiApiKey, this.config.embeddingModel);
|
|
237
|
+
}
|
|
238
|
+
return localEmbed(query, this.config.dimensions);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get engine stats.
|
|
242
|
+
*/
|
|
243
|
+
stats() {
|
|
244
|
+
return {
|
|
245
|
+
strategy: this.config.strategy,
|
|
246
|
+
cachedEmbeddings: this.vectors.size,
|
|
247
|
+
dimensions: this.config.dimensions,
|
|
248
|
+
provider: this.config.embeddingProvider,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
exports.RecallEngine = RecallEngine;
|
|
253
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/recall/engine.ts"],"names":[],"mappings":"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"}
|