@jcyamacho/agent-memory 0.0.18 → 0.0.20
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/README.md +15 -9
- package/dist/index.js +98 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,10 +6,11 @@ Persistent memory for MCP-powered coding agents.
|
|
|
6
6
|
by SQLite. It helps your agent remember preferences, project context, and prior
|
|
7
7
|
decisions across sessions.
|
|
8
8
|
|
|
9
|
-
It exposes
|
|
9
|
+
It exposes five tools:
|
|
10
10
|
|
|
11
11
|
- `remember` -> save facts, decisions, preferences, and project context
|
|
12
12
|
- `recall` -> retrieve the most relevant memories later
|
|
13
|
+
- `review` -> browse all memories for a workspace
|
|
13
14
|
- `revise` -> update an existing memory when it becomes outdated
|
|
14
15
|
- `forget` -> delete a memory that is no longer relevant
|
|
15
16
|
|
|
@@ -49,10 +50,13 @@ Optional LLM instructions to reinforce the MCP's built-in guidance:
|
|
|
49
50
|
## Agent Memory
|
|
50
51
|
|
|
51
52
|
- Use `memory_recall` at conversation start and before design choices,
|
|
52
|
-
conventions, or
|
|
53
|
+
conventions, edge cases, or saving memory.
|
|
53
54
|
- Query `memory_recall` with 2-5 short anchor-heavy terms or exact phrases,
|
|
54
55
|
not full questions or sentences.
|
|
55
|
-
-
|
|
56
|
+
- Use `memory_review` to browse all memories for a workspace before bulk review
|
|
57
|
+
or cleanup.
|
|
58
|
+
- Pass `workspace` for project-scoped memory. Omit it only for facts that
|
|
59
|
+
apply across projects.
|
|
56
60
|
- Use `memory_remember` to save one durable fact when the user states a stable
|
|
57
61
|
preference, correction, or reusable project decision.
|
|
58
62
|
- If the fact already exists, use `memory_revise` instead of creating a duplicate.
|
|
@@ -83,15 +87,15 @@ memories:
|
|
|
83
87
|
|
|
84
88
|
1. **Text relevance** is the primary signal -- memories whose content best
|
|
85
89
|
matches your search terms rank highest.
|
|
86
|
-
2. **
|
|
87
|
-
|
|
90
|
+
2. **Workspace match** is the next strongest signal. When you pass
|
|
91
|
+
`workspace`, exact matches rank highest and all other scoped workspaces rank
|
|
92
|
+
below exact matches.
|
|
93
|
+
3. **Embedding similarity** is a secondary signal. Recall builds an embedding
|
|
94
|
+
from your normalized search terms and boosts memories whose stored
|
|
88
95
|
embeddings are most semantically similar.
|
|
89
|
-
3. **Workspace match** is a strong secondary signal. When you pass
|
|
90
|
-
`workspace`, exact matches rank highest, sibling repositories get a small
|
|
91
|
-
boost, and unrelated workspaces rank lowest.
|
|
92
96
|
4. **Global memories** (saved without a workspace) are treated as relevant
|
|
93
97
|
everywhere. When you pass `workspace`, they rank below exact workspace
|
|
94
|
-
matches and above
|
|
98
|
+
matches and above memories from other workspaces.
|
|
95
99
|
5. **Recency** is a minor tiebreaker -- newer memories rank slightly above older
|
|
96
100
|
ones when other signals are equal.
|
|
97
101
|
|
|
@@ -102,6 +106,8 @@ memories without a workspace only when they apply across all projects.
|
|
|
102
106
|
When you save a memory from a git worktree, `agent-memory` stores the main repo
|
|
103
107
|
root as the workspace. `recall` applies the same normalization to incoming
|
|
104
108
|
workspace queries so linked worktrees still match repo-scoped memories exactly.
|
|
109
|
+
When that happens, recall returns the queried workspace value so callers can
|
|
110
|
+
treat the match as belonging to their current worktree context.
|
|
105
111
|
|
|
106
112
|
## Configuration
|
|
107
113
|
|
package/dist/index.js
CHANGED
|
@@ -12464,7 +12464,7 @@ class StdioServerTransport {
|
|
|
12464
12464
|
}
|
|
12465
12465
|
}
|
|
12466
12466
|
// package.json
|
|
12467
|
-
var version2 = "0.0.
|
|
12467
|
+
var version2 = "0.0.20";
|
|
12468
12468
|
|
|
12469
12469
|
// src/config.ts
|
|
12470
12470
|
import { homedir } from "node:os";
|
|
@@ -12533,14 +12533,20 @@ class PersistenceError extends MemoryError {
|
|
|
12533
12533
|
|
|
12534
12534
|
// src/embedding/service.ts
|
|
12535
12535
|
var DEFAULT_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
12536
|
+
function configureModelsCache(modelsCachePath) {
|
|
12537
|
+
mkdirSync(modelsCachePath, { recursive: true });
|
|
12538
|
+
transformersEnv.useFSCache = true;
|
|
12539
|
+
transformersEnv.cacheDir = modelsCachePath;
|
|
12540
|
+
}
|
|
12536
12541
|
|
|
12537
12542
|
class EmbeddingService {
|
|
12538
12543
|
options;
|
|
12539
12544
|
extractorPromise;
|
|
12540
|
-
modelsCachePath;
|
|
12541
12545
|
constructor(options = {}) {
|
|
12542
12546
|
this.options = options;
|
|
12543
|
-
|
|
12547
|
+
}
|
|
12548
|
+
async warmup() {
|
|
12549
|
+
await this.getExtractor();
|
|
12544
12550
|
}
|
|
12545
12551
|
async createVector(text) {
|
|
12546
12552
|
const normalizedText = text.trim();
|
|
@@ -12553,17 +12559,11 @@ class EmbeddingService {
|
|
|
12553
12559
|
}
|
|
12554
12560
|
getExtractor() {
|
|
12555
12561
|
if (!this.extractorPromise) {
|
|
12556
|
-
configureModelsCache(this.modelsCachePath);
|
|
12557
12562
|
this.extractorPromise = (this.options.createExtractor ?? createDefaultExtractor)();
|
|
12558
12563
|
}
|
|
12559
12564
|
return this.extractorPromise;
|
|
12560
12565
|
}
|
|
12561
12566
|
}
|
|
12562
|
-
function configureModelsCache(modelsCachePath) {
|
|
12563
|
-
mkdirSync(modelsCachePath, { recursive: true });
|
|
12564
|
-
transformersEnv.useFSCache = true;
|
|
12565
|
-
transformersEnv.cacheDir = modelsCachePath;
|
|
12566
|
-
}
|
|
12567
12567
|
async function createDefaultExtractor() {
|
|
12568
12568
|
const extractor = await pipeline("feature-extraction", DEFAULT_EMBEDDING_MODEL);
|
|
12569
12569
|
return (text) => extractor(text, {
|
|
@@ -20086,15 +20086,14 @@ function registerForgetTool(server, memory) {
|
|
|
20086
20086
|
var toNormalizedScore = (value) => value;
|
|
20087
20087
|
|
|
20088
20088
|
// src/ranking.ts
|
|
20089
|
-
var RETRIEVAL_SCORE_WEIGHT =
|
|
20090
|
-
var EMBEDDING_SIMILARITY_WEIGHT =
|
|
20091
|
-
var WORKSPACE_MATCH_WEIGHT =
|
|
20092
|
-
var RECENCY_WEIGHT =
|
|
20089
|
+
var RETRIEVAL_SCORE_WEIGHT = 9;
|
|
20090
|
+
var EMBEDDING_SIMILARITY_WEIGHT = 4;
|
|
20091
|
+
var WORKSPACE_MATCH_WEIGHT = 5;
|
|
20092
|
+
var RECENCY_WEIGHT = 1;
|
|
20093
20093
|
var MAX_COMPOSITE_SCORE = RETRIEVAL_SCORE_WEIGHT + EMBEDDING_SIMILARITY_WEIGHT + WORKSPACE_MATCH_WEIGHT + RECENCY_WEIGHT;
|
|
20094
20094
|
var GLOBAL_WORKSPACE_SCORE = 0.5;
|
|
20095
|
-
var SIBLING_WORKSPACE_SCORE = 0.25;
|
|
20096
20095
|
function rerankSearchResults(results, workspace, queryEmbedding) {
|
|
20097
|
-
if (results.length
|
|
20096
|
+
if (results.length === 0) {
|
|
20098
20097
|
return results;
|
|
20099
20098
|
}
|
|
20100
20099
|
const normalizedQueryWs = workspace ? normalizeWorkspacePath(workspace) : undefined;
|
|
@@ -20132,14 +20131,7 @@ function computeWorkspaceScore(memoryWs, queryWs) {
|
|
|
20132
20131
|
if (normalizedMemoryWs === queryWs) {
|
|
20133
20132
|
return 1;
|
|
20134
20133
|
}
|
|
20135
|
-
|
|
20136
|
-
const memoryLastSlashIndex = normalizedMemoryWs.lastIndexOf("/");
|
|
20137
|
-
if (queryLastSlashIndex <= 0 || memoryLastSlashIndex <= 0) {
|
|
20138
|
-
return 0;
|
|
20139
|
-
}
|
|
20140
|
-
const queryParent = queryWs.slice(0, queryLastSlashIndex);
|
|
20141
|
-
const memoryParent = normalizedMemoryWs.slice(0, memoryLastSlashIndex);
|
|
20142
|
-
return memoryParent === queryParent ? SIBLING_WORKSPACE_SCORE : 0;
|
|
20134
|
+
return 0;
|
|
20143
20135
|
}
|
|
20144
20136
|
|
|
20145
20137
|
// src/memory-service.ts
|
|
@@ -20193,6 +20185,7 @@ class MemoryService {
|
|
|
20193
20185
|
return memory ? toPublicMemoryRecord(memory) : undefined;
|
|
20194
20186
|
}
|
|
20195
20187
|
async list(input) {
|
|
20188
|
+
const queryWorkspace = normalizeOptionalString(input.workspace);
|
|
20196
20189
|
const workspace = await this.workspaceResolver.resolve(input.workspace);
|
|
20197
20190
|
const page = await this.repository.list({
|
|
20198
20191
|
workspace,
|
|
@@ -20200,7 +20193,10 @@ class MemoryService {
|
|
|
20200
20193
|
offset: normalizeOffset(input.offset),
|
|
20201
20194
|
limit: normalizeListLimit(input.limit)
|
|
20202
20195
|
});
|
|
20203
|
-
return
|
|
20196
|
+
return {
|
|
20197
|
+
items: page.items.map((item) => toPublicMemoryRecord(remapWorkspace(item, workspace, queryWorkspace))),
|
|
20198
|
+
hasMore: page.hasMore
|
|
20199
|
+
};
|
|
20204
20200
|
}
|
|
20205
20201
|
async listWorkspaces() {
|
|
20206
20202
|
return this.repository.listWorkspaces();
|
|
@@ -20211,6 +20207,7 @@ class MemoryService {
|
|
|
20211
20207
|
throw new ValidationError("At least one search term is required.");
|
|
20212
20208
|
}
|
|
20213
20209
|
const requestedLimit = normalizeLimit(input.limit);
|
|
20210
|
+
const queryWorkspace = normalizeOptionalString(input.workspace);
|
|
20214
20211
|
const workspace = await this.workspaceResolver.resolve(input.workspace);
|
|
20215
20212
|
const normalizedQuery = {
|
|
20216
20213
|
terms,
|
|
@@ -20222,7 +20219,7 @@ class MemoryService {
|
|
|
20222
20219
|
this.repository.search(normalizedQuery),
|
|
20223
20220
|
this.embeddingService.createVector(terms.join(" "))
|
|
20224
20221
|
]);
|
|
20225
|
-
return rerankSearchResults(results, workspace, queryEmbedding).slice(0, requestedLimit).map(toPublicSearchResult);
|
|
20222
|
+
return rerankSearchResults(results, workspace, queryEmbedding).slice(0, requestedLimit).map((result) => toPublicSearchResult(remapWorkspace(result, workspace, queryWorkspace)));
|
|
20226
20223
|
}
|
|
20227
20224
|
}
|
|
20228
20225
|
function toPublicMemoryRecord(memory) {
|
|
@@ -20244,12 +20241,6 @@ function toPublicSearchResult(result) {
|
|
|
20244
20241
|
updatedAt: result.updatedAt
|
|
20245
20242
|
};
|
|
20246
20243
|
}
|
|
20247
|
-
function toPublicMemoryPage(page) {
|
|
20248
|
-
return {
|
|
20249
|
-
items: page.items.map(toPublicMemoryRecord),
|
|
20250
|
-
hasMore: page.hasMore
|
|
20251
|
-
};
|
|
20252
|
-
}
|
|
20253
20244
|
function normalizeLimit(value) {
|
|
20254
20245
|
if (value === undefined) {
|
|
20255
20246
|
return DEFAULT_RECALL_LIMIT;
|
|
@@ -20272,12 +20263,22 @@ function normalizeTerms(terms) {
|
|
|
20272
20263
|
const normalizedTerms = terms.map((term) => term.trim()).filter(Boolean);
|
|
20273
20264
|
return [...new Set(normalizedTerms)];
|
|
20274
20265
|
}
|
|
20266
|
+
function normalizeOptionalString(value) {
|
|
20267
|
+
const trimmed = value?.trim();
|
|
20268
|
+
return trimmed ? trimmed : undefined;
|
|
20269
|
+
}
|
|
20270
|
+
function remapWorkspace(record3, canonicalWorkspace, queryWorkspace) {
|
|
20271
|
+
if (record3.workspace !== canonicalWorkspace) {
|
|
20272
|
+
return record3;
|
|
20273
|
+
}
|
|
20274
|
+
return { ...record3, workspace: queryWorkspace };
|
|
20275
|
+
}
|
|
20275
20276
|
|
|
20276
20277
|
// src/mcp/tools/recall.ts
|
|
20277
20278
|
var recallInputSchema = {
|
|
20278
|
-
terms: array(string2()).min(1).describe("
|
|
20279
|
+
terms: array(string2()).min(1).describe("2-5 short anchor-heavy terms or exact phrases. Prefer identifiers, commands, file paths, and exact wording likely to appear in the memory."),
|
|
20279
20280
|
limit: number2().int().min(1).max(MAX_RECALL_LIMIT).optional().describe("Maximum matches to return. Keep this small when you only need the strongest hits."),
|
|
20280
|
-
workspace: string2().optional().describe("
|
|
20281
|
+
workspace: string2().optional().describe("Current working directory for project-scoped recall. Omit for cross-project recall."),
|
|
20281
20282
|
updated_after: string2().optional().describe("Only return memories updated on or after this ISO 8601 timestamp."),
|
|
20282
20283
|
updated_before: string2().optional().describe("Only return memories updated on or before this ISO 8601 timestamp.")
|
|
20283
20284
|
};
|
|
@@ -20296,7 +20297,7 @@ function registerRecallTool(server, memory) {
|
|
|
20296
20297
|
readOnlyHint: true,
|
|
20297
20298
|
openWorldHint: false
|
|
20298
20299
|
},
|
|
20299
|
-
description: "
|
|
20300
|
+
description: "Retrieve memories relevant to the current task or check whether a fact already exists before saving. Use at conversation start and before design choices. Pass short anchor-heavy `terms` and `workspace` when available. Results reflect the queried workspace context when applicable. Returns `<memories>...</memories>` or a no-match hint.",
|
|
20300
20301
|
inputSchema: recallInputSchema
|
|
20301
20302
|
}, async ({ terms, limit, workspace, updated_after, updated_before }) => {
|
|
20302
20303
|
try {
|
|
@@ -20323,7 +20324,7 @@ ${results.map(toMemoryXml).join(`
|
|
|
20323
20324
|
// src/mcp/tools/remember.ts
|
|
20324
20325
|
var rememberInputSchema = {
|
|
20325
20326
|
content: string2().describe("One new durable fact to save. Use a self-contained sentence or short note."),
|
|
20326
|
-
workspace: string2().optional().describe("
|
|
20327
|
+
workspace: string2().optional().describe("Current working directory for project-scoped memory. Omit for facts that apply across projects.")
|
|
20327
20328
|
};
|
|
20328
20329
|
function registerRememberTool(server, memory) {
|
|
20329
20330
|
server.registerTool("remember", {
|
|
@@ -20333,7 +20334,7 @@ function registerRememberTool(server, memory) {
|
|
|
20333
20334
|
idempotentHint: false,
|
|
20334
20335
|
openWorldHint: false
|
|
20335
20336
|
},
|
|
20336
|
-
description: 'Save one new durable fact for later recall. Use for stable preferences,
|
|
20337
|
+
description: 'Save one new durable fact for later recall. Use for stable preferences, reusable decisions, and project context not obvious from code or git history. If the fact already exists, use `revise` instead. Returns `<memory id="..." />`.',
|
|
20337
20338
|
inputSchema: rememberInputSchema
|
|
20338
20339
|
}, async ({ content, workspace }) => {
|
|
20339
20340
|
try {
|
|
@@ -20350,10 +20351,57 @@ function registerRememberTool(server, memory) {
|
|
|
20350
20351
|
});
|
|
20351
20352
|
}
|
|
20352
20353
|
|
|
20354
|
+
// src/mcp/tools/review.ts
|
|
20355
|
+
var REVIEW_PAGE_SIZE = 25;
|
|
20356
|
+
var reviewInputSchema = {
|
|
20357
|
+
workspace: string2().describe("Current working directory for project-scoped listing."),
|
|
20358
|
+
page: number2().int().min(0).optional().describe("Zero-based page number. Defaults to 0.")
|
|
20359
|
+
};
|
|
20360
|
+
function toMemoryXml2(record3) {
|
|
20361
|
+
const content = escapeXml(record3.content);
|
|
20362
|
+
return `<memory id="${record3.id}" updated_at="${record3.updatedAt.toISOString()}">
|
|
20363
|
+
${content}
|
|
20364
|
+
</memory>`;
|
|
20365
|
+
}
|
|
20366
|
+
function registerReviewTool(server, memory) {
|
|
20367
|
+
server.registerTool("review", {
|
|
20368
|
+
annotations: {
|
|
20369
|
+
title: "Review",
|
|
20370
|
+
readOnlyHint: true,
|
|
20371
|
+
openWorldHint: false
|
|
20372
|
+
},
|
|
20373
|
+
description: 'Browse all memories for a workspace in creation order. Use before bulk review, cleanup, or when you need to scan memories without specific search terms. For targeted retrieval by topic, use `recall` instead. Returns `<memories workspace="..." has_more="true|false">...</memories>` with pagination support.',
|
|
20374
|
+
inputSchema: reviewInputSchema
|
|
20375
|
+
}, async ({ workspace, page }) => {
|
|
20376
|
+
try {
|
|
20377
|
+
const pageIndex = page ?? 0;
|
|
20378
|
+
const result = await memory.list({
|
|
20379
|
+
workspace,
|
|
20380
|
+
offset: pageIndex * REVIEW_PAGE_SIZE,
|
|
20381
|
+
limit: REVIEW_PAGE_SIZE
|
|
20382
|
+
});
|
|
20383
|
+
if (result.items.length === 0) {
|
|
20384
|
+
return {
|
|
20385
|
+
content: [{ type: "text", text: "No memories found for this workspace." }]
|
|
20386
|
+
};
|
|
20387
|
+
}
|
|
20388
|
+
const text = `<memories workspace="${escapeXml(workspace)}" has_more="${result.hasMore}">
|
|
20389
|
+
${result.items.map(toMemoryXml2).join(`
|
|
20390
|
+
`)}
|
|
20391
|
+
</memories>`;
|
|
20392
|
+
return {
|
|
20393
|
+
content: [{ type: "text", text }]
|
|
20394
|
+
};
|
|
20395
|
+
} catch (error2) {
|
|
20396
|
+
throw toMcpError(error2);
|
|
20397
|
+
}
|
|
20398
|
+
});
|
|
20399
|
+
}
|
|
20400
|
+
|
|
20353
20401
|
// src/mcp/tools/revise.ts
|
|
20354
20402
|
var reviseInputSchema = {
|
|
20355
20403
|
id: string2().describe("Memory id to update. Use an id returned by `recall`."),
|
|
20356
|
-
content: string2().describe("Corrected replacement text for that memory.
|
|
20404
|
+
content: string2().describe("Corrected replacement text for that memory.")
|
|
20357
20405
|
};
|
|
20358
20406
|
function registerReviseTool(server, memory) {
|
|
20359
20407
|
server.registerTool("revise", {
|
|
@@ -20363,7 +20411,7 @@ function registerReviseTool(server, memory) {
|
|
|
20363
20411
|
idempotentHint: false,
|
|
20364
20412
|
openWorldHint: false
|
|
20365
20413
|
},
|
|
20366
|
-
description: 'Update one existing memory when the same fact still applies but its wording or details changed. Use after `recall` when you already have the memory id.
|
|
20414
|
+
description: 'Update one existing memory when the same fact still applies but its wording or details changed. Use after `recall` when you already have the memory id. Returns `<memory id="..." updated_at="..." />`.',
|
|
20367
20415
|
inputSchema: reviseInputSchema
|
|
20368
20416
|
}, async ({ id, content }) => {
|
|
20369
20417
|
try {
|
|
@@ -20385,11 +20433,12 @@ function registerReviseTool(server, memory) {
|
|
|
20385
20433
|
// src/mcp/server.ts
|
|
20386
20434
|
var SERVER_INSTRUCTIONS = [
|
|
20387
20435
|
"Use this server only for durable memory that should survive across turns: stable preferences, corrections, reusable decisions, and project context not obvious from code or git history.",
|
|
20388
|
-
"Use `recall` at conversation start, before design choices, and before saving memory.",
|
|
20389
|
-
"Use `
|
|
20390
|
-
"Use `
|
|
20391
|
-
"
|
|
20392
|
-
"
|
|
20436
|
+
"Use `recall` at conversation start, before design choices, and before saving or revising memory.",
|
|
20437
|
+
"Use `review` to browse all memories for a workspace before bulk review or cleanup.",
|
|
20438
|
+
"Use `remember` for one new durable fact. Use `revise` when the fact already exists but needs correction.",
|
|
20439
|
+
"Use `forget` only when a memory is wrong or obsolete.",
|
|
20440
|
+
"Pass workspace for project-scoped memory. Omit it only for facts that apply across projects.",
|
|
20441
|
+
"Do not store secrets, temporary task state, or facts obvious from current code or git history."
|
|
20393
20442
|
].join(" ");
|
|
20394
20443
|
function createMcpServer(memory, version3) {
|
|
20395
20444
|
const server = new McpServer({
|
|
@@ -20402,6 +20451,7 @@ function createMcpServer(memory, version3) {
|
|
|
20402
20451
|
registerRecallTool(server, memory);
|
|
20403
20452
|
registerReviseTool(server, memory);
|
|
20404
20453
|
registerForgetTool(server, memory);
|
|
20454
|
+
registerReviewTool(server, memory);
|
|
20405
20455
|
return server;
|
|
20406
20456
|
}
|
|
20407
20457
|
|
|
@@ -24244,7 +24294,7 @@ function createGitWorkspaceResolver(options = {}) {
|
|
|
24244
24294
|
const cache = new Map;
|
|
24245
24295
|
return {
|
|
24246
24296
|
async resolve(workspace) {
|
|
24247
|
-
const trimmed =
|
|
24297
|
+
const trimmed = normalizeOptionalString2(workspace);
|
|
24248
24298
|
if (!trimmed) {
|
|
24249
24299
|
return;
|
|
24250
24300
|
}
|
|
@@ -24275,18 +24325,20 @@ async function defaultGetGitCommonDir(cwd) {
|
|
|
24275
24325
|
});
|
|
24276
24326
|
return stdout.trim();
|
|
24277
24327
|
}
|
|
24278
|
-
function
|
|
24328
|
+
function normalizeOptionalString2(value) {
|
|
24279
24329
|
const trimmed = value?.trim();
|
|
24280
24330
|
return trimmed ? trimmed : undefined;
|
|
24281
24331
|
}
|
|
24282
24332
|
|
|
24283
24333
|
// src/index.ts
|
|
24284
24334
|
var config2 = resolveConfig();
|
|
24285
|
-
|
|
24335
|
+
configureModelsCache(config2.modelsCachePath);
|
|
24336
|
+
var embeddingService = new EmbeddingService;
|
|
24286
24337
|
var workspaceResolver = createGitWorkspaceResolver();
|
|
24287
24338
|
var database = await openMemoryDatabase(config2.databasePath, { embeddingService, workspaceResolver });
|
|
24288
24339
|
var repository2 = new SqliteMemoryRepository(database);
|
|
24289
24340
|
var memoryService = new MemoryService(repository2, embeddingService, workspaceResolver);
|
|
24341
|
+
embeddingService.warmup();
|
|
24290
24342
|
if (config2.uiMode) {
|
|
24291
24343
|
let shutdown = function() {
|
|
24292
24344
|
server.close();
|