memorandum-mcp 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 +674 -0
- package/README.md +237 -0
- package/README.ru.md +237 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.js +63 -0
- package/dist/config.js.map +1 -0
- package/dist/document-store.d.ts +145 -0
- package/dist/document-store.js +682 -0
- package/dist/document-store.js.map +1 -0
- package/dist/document-tools.d.ts +10 -0
- package/dist/document-tools.js +101 -0
- package/dist/document-tools.js.map +1 -0
- package/dist/document-types.d.ts +147 -0
- package/dist/document-types.js +125 -0
- package/dist/document-types.js.map +1 -0
- package/dist/embedder.d.ts +55 -0
- package/dist/embedder.js +152 -0
- package/dist/embedder.js.map +1 -0
- package/dist/embedding-queue.d.ts +66 -0
- package/dist/embedding-queue.js +152 -0
- package/dist/embedding-queue.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.js +46 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.js +22 -0
- package/dist/logger.js.map +1 -0
- package/dist/semantic-index.d.ts +126 -0
- package/dist/semantic-index.js +427 -0
- package/dist/semantic-index.js.map +1 -0
- package/dist/semantic-tools.d.ts +10 -0
- package/dist/semantic-tools.js +80 -0
- package/dist/semantic-tools.js.map +1 -0
- package/dist/semantic-types.d.ts +161 -0
- package/dist/semantic-types.js +101 -0
- package/dist/semantic-types.js.map +1 -0
- package/dist/store.d.ts +130 -0
- package/dist/store.js +389 -0
- package/dist/store.js.map +1 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.js +104 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +97 -0
- package/dist/types.js +88 -0
- package/dist/types.js.map +1 -0
- package/dist/vector-store.d.ts +85 -0
- package/dist/vector-store.js +241 -0
- package/dist/vector-store.js.map +1 -0
- package/package.json +50 -0
package/dist/types.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import safeRegex from 'safe-regex2';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Constants
|
|
5
|
+
// ============================================================================
|
|
6
|
+
export const KEY_MAX_LEN = 256;
|
|
7
|
+
export const NAMESPACE_MAX_LEN = 64;
|
|
8
|
+
export const NAMESPACE_REGEX = /^[a-z0-9\-_.]+$/;
|
|
9
|
+
export const DEFAULT_NAMESPACE = 'default';
|
|
10
|
+
export const DEFAULT_LIST_LIMIT = 50;
|
|
11
|
+
export const DEFAULT_SEARCH_LIMIT = 20;
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Display Schemas (for LLM tool description - all fields optional)
|
|
14
|
+
// ============================================================================
|
|
15
|
+
export const MemoryWriteDisplaySchema = z.object({
|
|
16
|
+
key: z.string().optional().describe('Unique identifier for the fact (1-256 characters)'),
|
|
17
|
+
value: z.unknown().optional().describe('The data to store (any JSON-serializable value)'),
|
|
18
|
+
namespace: z.string().optional().describe(`Namespace to organize facts (default: "${DEFAULT_NAMESPACE}", 1-64 chars, lowercase alphanumeric with -_.)`),
|
|
19
|
+
ttl_seconds: z.number().optional().describe('Optional time-to-live in seconds (positive integer)'),
|
|
20
|
+
});
|
|
21
|
+
export const MemoryReadDisplaySchema = z.object({
|
|
22
|
+
key: z.string().optional().describe('The key of the fact to retrieve'),
|
|
23
|
+
namespace: z.string().optional().describe(`Namespace to read from (default: "${DEFAULT_NAMESPACE}")`),
|
|
24
|
+
});
|
|
25
|
+
export const MemoryManageDisplaySchema = z.object({
|
|
26
|
+
action: z.string().optional().describe('Action to perform: "delete", "delete_namespace", "list", "search", "namespaces", "export", "import", "sync"'),
|
|
27
|
+
key: z.string().optional().describe('Key to delete (required for "delete" action)'),
|
|
28
|
+
namespace: z.string().optional().describe('Namespace to operate on (various actions)'),
|
|
29
|
+
pattern: z.string().optional().describe('Glob pattern to filter keys, e.g. "server-*" (for "list" action)'),
|
|
30
|
+
limit: z.number().optional().describe(`Maximum number of results (default: ${DEFAULT_LIST_LIMIT} for list, ${DEFAULT_SEARCH_LIMIT} for search)`),
|
|
31
|
+
include_values: z.boolean().optional().describe('Include fact values in list results (default: false)'),
|
|
32
|
+
include_stats: z.boolean().optional().describe('Include memory statistics in list results (default: false)'),
|
|
33
|
+
query: z.string().optional().describe('Search query string (required for "search" action)'),
|
|
34
|
+
data: z.string().optional().describe('JSON string to import (required for "import" action)'),
|
|
35
|
+
merge: z.boolean().optional().describe('Merge imported data with existing facts (default: true, for "import" action)'),
|
|
36
|
+
});
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Input Schemas (for runtime validation - strict)
|
|
39
|
+
// ============================================================================
|
|
40
|
+
const namespaceField = z
|
|
41
|
+
.string()
|
|
42
|
+
.min(1, 'Namespace must not be empty')
|
|
43
|
+
.max(NAMESPACE_MAX_LEN, `Namespace must not exceed ${NAMESPACE_MAX_LEN} characters`)
|
|
44
|
+
.regex(NAMESPACE_REGEX, 'Namespace must contain only lowercase letters, numbers, hyphens, underscores, and dots');
|
|
45
|
+
export const MemoryWriteInputSchema = z.strictObject({
|
|
46
|
+
key: z.string().min(1, 'Key must not be empty').max(KEY_MAX_LEN, `Key must not exceed ${KEY_MAX_LEN} characters`),
|
|
47
|
+
value: z.unknown(),
|
|
48
|
+
namespace: namespaceField.default(DEFAULT_NAMESPACE),
|
|
49
|
+
ttl_seconds: z.number().int('TTL must be an integer').positive('TTL must be positive').optional(),
|
|
50
|
+
});
|
|
51
|
+
export const MemoryReadInputSchema = z.strictObject({
|
|
52
|
+
key: z.string().min(1, 'Key must not be empty').max(KEY_MAX_LEN, `Key must not exceed ${KEY_MAX_LEN} characters`),
|
|
53
|
+
namespace: namespaceField.default(DEFAULT_NAMESPACE),
|
|
54
|
+
});
|
|
55
|
+
export const MemoryManageInputSchema = z.discriminatedUnion('action', [
|
|
56
|
+
z.strictObject({
|
|
57
|
+
action: z.literal('delete'),
|
|
58
|
+
key: z.string().min(1).max(KEY_MAX_LEN),
|
|
59
|
+
namespace: namespaceField.default(DEFAULT_NAMESPACE),
|
|
60
|
+
}),
|
|
61
|
+
z.strictObject({
|
|
62
|
+
action: z.literal('delete_namespace'),
|
|
63
|
+
namespace: namespaceField,
|
|
64
|
+
}),
|
|
65
|
+
z.strictObject({
|
|
66
|
+
action: z.literal('list'),
|
|
67
|
+
namespace: namespaceField.optional(),
|
|
68
|
+
pattern: z.string().optional(),
|
|
69
|
+
limit: z.number().int().positive().default(DEFAULT_LIST_LIMIT),
|
|
70
|
+
include_values: z.boolean().default(false),
|
|
71
|
+
include_stats: z.boolean().default(false),
|
|
72
|
+
}),
|
|
73
|
+
z.strictObject({
|
|
74
|
+
action: z.literal('search'),
|
|
75
|
+
query: z.string().min(1, 'Search query must not be empty').refine((val) => safeRegex(val), 'Search query contains unsafe regex pattern (potential ReDoS)'),
|
|
76
|
+
namespace: namespaceField.optional(),
|
|
77
|
+
limit: z.number().int().positive().default(DEFAULT_SEARCH_LIMIT),
|
|
78
|
+
}),
|
|
79
|
+
z.strictObject({ action: z.literal('namespaces') }),
|
|
80
|
+
z.strictObject({ action: z.literal('export') }),
|
|
81
|
+
z.strictObject({
|
|
82
|
+
action: z.literal('import'),
|
|
83
|
+
data: z.string().min(1, 'Import data must not be empty'),
|
|
84
|
+
merge: z.boolean().default(true),
|
|
85
|
+
}),
|
|
86
|
+
z.strictObject({ action: z.literal('sync') }),
|
|
87
|
+
]);
|
|
88
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { VectorEntry, SearchResult, SearchFilterOptions, EmbeddingFailureRecord } from './semantic-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Persisted in-memory vector store that supports cosine-similarity search,
|
|
5
|
+
* atomic saves, and failure tracking for embedding retries.
|
|
6
|
+
*/
|
|
7
|
+
export declare class VectorStore {
|
|
8
|
+
private readonly indexPath;
|
|
9
|
+
private readonly modelId;
|
|
10
|
+
private dimensions;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
private entries;
|
|
13
|
+
private storedModelId;
|
|
14
|
+
private failedEmbeddings;
|
|
15
|
+
private dirty;
|
|
16
|
+
/**
|
|
17
|
+
* @param indexPath - File path for the persisted JSON vector index.
|
|
18
|
+
* @param modelId - Identifier of the embedding model producing the vectors.
|
|
19
|
+
* @param dimensions - Expected dimensionality of embedding vectors.
|
|
20
|
+
* @param logger - Pino logger instance.
|
|
21
|
+
*/
|
|
22
|
+
constructor(indexPath: string, modelId: string, dimensions: number, logger: Logger);
|
|
23
|
+
/** Loads the vector index from disk, or starts with an empty index if the file is missing or corrupt. */
|
|
24
|
+
load(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Atomically persists the vector index to disk via a temp-file rename.
|
|
27
|
+
* Skips the write if nothing has changed, and refuses to overwrite a
|
|
28
|
+
* non-empty file on disk with an empty in-memory index.
|
|
29
|
+
* @returns True if the file was written, false otherwise.
|
|
30
|
+
*/
|
|
31
|
+
save(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Inserts or updates a vector entry by id.
|
|
34
|
+
* @param entry - The vector entry to upsert.
|
|
35
|
+
*/
|
|
36
|
+
upsert(entry: VectorEntry): void;
|
|
37
|
+
/**
|
|
38
|
+
* Removes a vector entry by id.
|
|
39
|
+
* @param id - The entry identifier.
|
|
40
|
+
* @returns True if the entry was found and removed.
|
|
41
|
+
*/
|
|
42
|
+
remove(id: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Replaces all entries in the store with the provided array.
|
|
45
|
+
* @param entries - The new set of vector entries.
|
|
46
|
+
*/
|
|
47
|
+
rebuild(entries: VectorEntry[]): void;
|
|
48
|
+
/**
|
|
49
|
+
* Searches for the most similar entries using cosine similarity.
|
|
50
|
+
* @param queryVector - The query embedding vector.
|
|
51
|
+
* @param options - Optional filters and limits for the search.
|
|
52
|
+
* @returns Matching results sorted by descending similarity score.
|
|
53
|
+
*/
|
|
54
|
+
query(queryVector: number[], options?: SearchFilterOptions): SearchResult[];
|
|
55
|
+
/** The number of vector entries currently stored. */
|
|
56
|
+
get entryCount(): number;
|
|
57
|
+
/** Returns a read-only view of all stored vector entries. */
|
|
58
|
+
allEntries(): ReadonlyArray<VectorEntry>;
|
|
59
|
+
/** Updates the expected embedding dimensions (e.g. after auto-detection). */
|
|
60
|
+
setDimensions(n: number): void;
|
|
61
|
+
/** The embedding model id configured for this store. */
|
|
62
|
+
get currentModelId(): string;
|
|
63
|
+
/** The model id stored in the persisted index, or null if not yet saved. */
|
|
64
|
+
get indexModelId(): string | null;
|
|
65
|
+
/** Returns the current map of failed embedding records. */
|
|
66
|
+
getFailedEmbeddings(): Record<string, EmbeddingFailureRecord>;
|
|
67
|
+
/**
|
|
68
|
+
* Replaces the entire failed-embeddings map (e.g. during reindex reset).
|
|
69
|
+
* @param records - The new failure records to store.
|
|
70
|
+
*/
|
|
71
|
+
setFailedEmbeddings(records: Record<string, EmbeddingFailureRecord>): void;
|
|
72
|
+
/**
|
|
73
|
+
* Removes a failure record for the given id, if one exists.
|
|
74
|
+
* @param id - The entry identifier whose failure record should be cleared.
|
|
75
|
+
*/
|
|
76
|
+
clearFailure(id: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Records or increments a failure for a given entry. Marks it as permanently
|
|
79
|
+
* "failed" once the retry count reaches maxRetries.
|
|
80
|
+
* @param id - The entry identifier that failed.
|
|
81
|
+
* @param error - The error message from the failed attempt.
|
|
82
|
+
* @param maxRetries - Maximum retries before marking as permanently failed.
|
|
83
|
+
*/
|
|
84
|
+
recordFailure(id: string, error: string, maxRetries: number): void;
|
|
85
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { writeFile, rename, mkdir, access } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { VECTOR_INDEX_VERSION, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_THRESHOLD } from './semantic-types.js';
|
|
5
|
+
function cosineSimilarity(a, b) {
|
|
6
|
+
if (a.length !== b.length)
|
|
7
|
+
return 0;
|
|
8
|
+
let dot = 0, normA = 0, normB = 0;
|
|
9
|
+
for (let i = 0; i < a.length; i++) {
|
|
10
|
+
dot += a[i] * b[i];
|
|
11
|
+
normA += a[i] * a[i];
|
|
12
|
+
normB += b[i] * b[i];
|
|
13
|
+
}
|
|
14
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
15
|
+
return denom === 0 ? 0 : dot / denom;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Persisted in-memory vector store that supports cosine-similarity search,
|
|
19
|
+
* atomic saves, and failure tracking for embedding retries.
|
|
20
|
+
*/
|
|
21
|
+
export class VectorStore {
|
|
22
|
+
indexPath;
|
|
23
|
+
modelId;
|
|
24
|
+
dimensions;
|
|
25
|
+
logger;
|
|
26
|
+
entries = [];
|
|
27
|
+
storedModelId = null;
|
|
28
|
+
failedEmbeddings = {};
|
|
29
|
+
dirty = false;
|
|
30
|
+
/**
|
|
31
|
+
* @param indexPath - File path for the persisted JSON vector index.
|
|
32
|
+
* @param modelId - Identifier of the embedding model producing the vectors.
|
|
33
|
+
* @param dimensions - Expected dimensionality of embedding vectors.
|
|
34
|
+
* @param logger - Pino logger instance.
|
|
35
|
+
*/
|
|
36
|
+
constructor(indexPath, modelId, dimensions, logger) {
|
|
37
|
+
this.indexPath = indexPath;
|
|
38
|
+
this.modelId = modelId;
|
|
39
|
+
this.dimensions = dimensions;
|
|
40
|
+
this.logger = logger;
|
|
41
|
+
}
|
|
42
|
+
/** Loads the vector index from disk, or starts with an empty index if the file is missing or corrupt. */
|
|
43
|
+
load() {
|
|
44
|
+
if (!existsSync(this.indexPath)) {
|
|
45
|
+
this.entries = [];
|
|
46
|
+
this.storedModelId = null;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const raw = readFileSync(this.indexPath, 'utf-8');
|
|
51
|
+
const parsed = JSON.parse(raw);
|
|
52
|
+
if (typeof parsed !== 'object' || parsed === null || !Array.isArray(parsed.entries)) {
|
|
53
|
+
throw new Error('Invalid vector index structure');
|
|
54
|
+
}
|
|
55
|
+
this.entries = parsed.entries;
|
|
56
|
+
this.storedModelId = parsed.modelId ?? null;
|
|
57
|
+
const rawFailed = parsed.failedEmbeddings;
|
|
58
|
+
this.failedEmbeddings = (rawFailed != null && typeof rawFailed === 'object' && !Array.isArray(rawFailed))
|
|
59
|
+
? rawFailed : {};
|
|
60
|
+
this.dirty = false;
|
|
61
|
+
this.logger.debug({ entries: this.entries.length, modelId: this.storedModelId }, 'Vector index loaded');
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
this.logger.warn({ error: err instanceof Error ? err.message : String(err) }, 'Failed to parse vector index, starting empty');
|
|
65
|
+
this.entries = [];
|
|
66
|
+
this.storedModelId = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Atomically persists the vector index to disk via a temp-file rename.
|
|
71
|
+
* Skips the write if nothing has changed, and refuses to overwrite a
|
|
72
|
+
* non-empty file on disk with an empty in-memory index.
|
|
73
|
+
* @returns True if the file was written, false otherwise.
|
|
74
|
+
*/
|
|
75
|
+
async save() {
|
|
76
|
+
if (!this.dirty)
|
|
77
|
+
return false;
|
|
78
|
+
if (this.entries.length === 0 && existsSync(this.indexPath)) {
|
|
79
|
+
try {
|
|
80
|
+
const diskRaw = readFileSync(this.indexPath, 'utf-8');
|
|
81
|
+
const diskIndex = JSON.parse(diskRaw);
|
|
82
|
+
if (diskIndex && Array.isArray(diskIndex.entries) && diskIndex.entries.length > 0) {
|
|
83
|
+
this.logger.warn('Skipping vector index save: disk has data but in-memory is empty');
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch { /* proceed */ }
|
|
88
|
+
}
|
|
89
|
+
const index = {
|
|
90
|
+
version: VECTOR_INDEX_VERSION,
|
|
91
|
+
modelId: this.modelId,
|
|
92
|
+
dimensions: this.dimensions,
|
|
93
|
+
entries: this.entries,
|
|
94
|
+
updatedAt: Date.now(),
|
|
95
|
+
failedEmbeddings: this.failedEmbeddings,
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
const dir = dirname(this.indexPath);
|
|
99
|
+
try {
|
|
100
|
+
await access(dir);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
await mkdir(dir, { recursive: true });
|
|
104
|
+
}
|
|
105
|
+
const data = JSON.stringify(index);
|
|
106
|
+
const tmpPath = `${this.indexPath}.${process.pid}-${Date.now()}.tmp`;
|
|
107
|
+
await writeFile(tmpPath, data, 'utf-8');
|
|
108
|
+
await rename(tmpPath, this.indexPath);
|
|
109
|
+
this.dirty = false;
|
|
110
|
+
this.storedModelId = this.modelId;
|
|
111
|
+
this.logger.debug({ entries: this.entries.length }, 'Vector index saved');
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.logger.error({ error: err instanceof Error ? err.message : String(err) }, 'Failed to save vector index');
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Inserts or updates a vector entry by id.
|
|
121
|
+
* @param entry - The vector entry to upsert.
|
|
122
|
+
*/
|
|
123
|
+
upsert(entry) {
|
|
124
|
+
const idx = this.entries.findIndex((e) => e.id === entry.id);
|
|
125
|
+
if (idx !== -1) {
|
|
126
|
+
this.entries[idx] = entry;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.entries.push(entry);
|
|
130
|
+
}
|
|
131
|
+
this.dirty = true;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Removes a vector entry by id.
|
|
135
|
+
* @param id - The entry identifier.
|
|
136
|
+
* @returns True if the entry was found and removed.
|
|
137
|
+
*/
|
|
138
|
+
remove(id) {
|
|
139
|
+
const idx = this.entries.findIndex((e) => e.id === id);
|
|
140
|
+
if (idx === -1)
|
|
141
|
+
return false;
|
|
142
|
+
this.entries.splice(idx, 1);
|
|
143
|
+
this.dirty = true;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Replaces all entries in the store with the provided array.
|
|
148
|
+
* @param entries - The new set of vector entries.
|
|
149
|
+
*/
|
|
150
|
+
rebuild(entries) {
|
|
151
|
+
this.entries = entries;
|
|
152
|
+
this.dirty = true;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Searches for the most similar entries using cosine similarity.
|
|
156
|
+
* @param queryVector - The query embedding vector.
|
|
157
|
+
* @param options - Optional filters and limits for the search.
|
|
158
|
+
* @returns Matching results sorted by descending similarity score.
|
|
159
|
+
*/
|
|
160
|
+
query(queryVector, options) {
|
|
161
|
+
const limit = options?.limit ?? DEFAULT_SEARCH_LIMIT;
|
|
162
|
+
const threshold = options?.threshold ?? DEFAULT_SEARCH_THRESHOLD;
|
|
163
|
+
let candidates = this.entries;
|
|
164
|
+
if (options?.source === 'facts')
|
|
165
|
+
candidates = candidates.filter((e) => e.source === 'fact');
|
|
166
|
+
else if (options?.source === 'documents')
|
|
167
|
+
candidates = candidates.filter((e) => e.source === 'document');
|
|
168
|
+
if (options?.namespace !== undefined) {
|
|
169
|
+
candidates = candidates.filter((e) => e.source === 'fact' && e.metadata.namespace === options.namespace);
|
|
170
|
+
}
|
|
171
|
+
if (options?.tag !== undefined) {
|
|
172
|
+
candidates = candidates.filter((e) => e.source === 'document' && e.metadata.tags.includes(options.tag));
|
|
173
|
+
}
|
|
174
|
+
if (options?.topic !== undefined) {
|
|
175
|
+
candidates = candidates.filter((e) => e.source === 'document' && e.metadata.topic === options.topic);
|
|
176
|
+
}
|
|
177
|
+
if (options?.content_type !== undefined) {
|
|
178
|
+
candidates = candidates.filter((e) => e.source === 'document' && e.metadata.contentType === options.content_type);
|
|
179
|
+
}
|
|
180
|
+
const scored = [];
|
|
181
|
+
for (const entry of candidates) {
|
|
182
|
+
if (queryVector.length !== entry.vector.length)
|
|
183
|
+
continue;
|
|
184
|
+
const score = cosineSimilarity(queryVector, entry.vector);
|
|
185
|
+
if (score >= threshold) {
|
|
186
|
+
scored.push({ source: entry.source, id: entry.id, score, metadata: entry.metadata });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
scored.sort((a, b) => b.score - a.score);
|
|
190
|
+
return scored.slice(0, limit);
|
|
191
|
+
}
|
|
192
|
+
/** The number of vector entries currently stored. */
|
|
193
|
+
get entryCount() { return this.entries.length; }
|
|
194
|
+
/** Returns a read-only view of all stored vector entries. */
|
|
195
|
+
allEntries() { return this.entries; }
|
|
196
|
+
/** Updates the expected embedding dimensions (e.g. after auto-detection). */
|
|
197
|
+
setDimensions(n) { this.dimensions = n; }
|
|
198
|
+
/** The embedding model id configured for this store. */
|
|
199
|
+
get currentModelId() { return this.modelId; }
|
|
200
|
+
/** The model id stored in the persisted index, or null if not yet saved. */
|
|
201
|
+
get indexModelId() { return this.storedModelId; }
|
|
202
|
+
/** Returns the current map of failed embedding records. */
|
|
203
|
+
getFailedEmbeddings() { return this.failedEmbeddings; }
|
|
204
|
+
/**
|
|
205
|
+
* Replaces the entire failed-embeddings map (e.g. during reindex reset).
|
|
206
|
+
* @param records - The new failure records to store.
|
|
207
|
+
*/
|
|
208
|
+
setFailedEmbeddings(records) {
|
|
209
|
+
this.failedEmbeddings = records;
|
|
210
|
+
this.dirty = true;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Removes a failure record for the given id, if one exists.
|
|
214
|
+
* @param id - The entry identifier whose failure record should be cleared.
|
|
215
|
+
*/
|
|
216
|
+
clearFailure(id) {
|
|
217
|
+
if (id in this.failedEmbeddings) {
|
|
218
|
+
delete this.failedEmbeddings[id];
|
|
219
|
+
this.dirty = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Records or increments a failure for a given entry. Marks it as permanently
|
|
224
|
+
* "failed" once the retry count reaches maxRetries.
|
|
225
|
+
* @param id - The entry identifier that failed.
|
|
226
|
+
* @param error - The error message from the failed attempt.
|
|
227
|
+
* @param maxRetries - Maximum retries before marking as permanently failed.
|
|
228
|
+
*/
|
|
229
|
+
recordFailure(id, error, maxRetries) {
|
|
230
|
+
const existing = this.failedEmbeddings[id];
|
|
231
|
+
const retries = (existing?.retries ?? 0) + 1;
|
|
232
|
+
this.failedEmbeddings[id] = {
|
|
233
|
+
retries,
|
|
234
|
+
status: retries >= maxRetries ? 'failed' : 'pending',
|
|
235
|
+
lastError: error,
|
|
236
|
+
lastAttempt: Date.now(),
|
|
237
|
+
};
|
|
238
|
+
this.dirty = true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=vector-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-store.js","sourceRoot":"","sources":["../src/vector-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memorandum-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server with memory: facts (short records with LRU expiration) and documents (with metadata and semantic search)",
|
|
5
|
+
"author": "lionsoftware <33127234+lionsoftware@users.noreply.github.com>",
|
|
6
|
+
"license": "GPL-3.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/lionsoftware/memorandum.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"bin": {
|
|
15
|
+
"memorandum": "dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"memory",
|
|
27
|
+
"semantic-search"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@huggingface/transformers": "^3.8.1",
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
38
|
+
"lru-cache": "^11.2.7",
|
|
39
|
+
"pino": "^10.3.1",
|
|
40
|
+
"safe-regex2": "^5.1.0",
|
|
41
|
+
"yaml": "^2.8.2",
|
|
42
|
+
"zod": "^4.3.6"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^25.5.0",
|
|
46
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
48
|
+
"vitest": "^4.1.0"
|
|
49
|
+
}
|
|
50
|
+
}
|