@jcyamacho/agent-memory 0.0.11 → 0.0.12
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 +33 -4
- package/dist/index.js +93 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
Persistent memory for MCP-powered coding agents.
|
|
4
4
|
|
|
5
5
|
`agent-memory` is a stdio MCP server that gives your LLM durable memory backed
|
|
6
|
-
by SQLite. It exposes
|
|
6
|
+
by SQLite. It exposes four tools:
|
|
7
7
|
|
|
8
8
|
- `remember` -> save facts, decisions, preferences, and project context
|
|
9
9
|
- `recall` -> retrieve the most relevant memories later
|
|
10
|
+
- `revise` -> update an existing memory when it becomes outdated
|
|
11
|
+
- `forget` -> delete a memory that is no longer relevant
|
|
10
12
|
|
|
11
13
|
Use it when your agent should remember preferences, project facts, and prior
|
|
12
14
|
decisions across sessions.
|
|
@@ -66,7 +68,10 @@ Optional LLM instructions to reinforce the MCP's built-in guidance:
|
|
|
66
68
|
Use `recall` at the start of every conversation and again mid-task before
|
|
67
69
|
making design choices or picking conventions. Use `remember` when the user
|
|
68
70
|
corrects your approach, a key decision is established, or you learn project
|
|
69
|
-
context not obvious from the code.
|
|
71
|
+
context not obvious from the code. Before saving, recall to check whether a
|
|
72
|
+
memory about the same fact already exists -- if so, use `revise` to update
|
|
73
|
+
it instead of creating a duplicate. Use `forget` to remove memories that
|
|
74
|
+
are wrong or no longer relevant. Always pass workspace.
|
|
70
75
|
```
|
|
71
76
|
|
|
72
77
|
## What It Stores
|
|
@@ -92,8 +97,7 @@ Opens at `http://localhost:6580`. Use `--port` to change:
|
|
|
92
97
|
npx -y @jcyamacho/agent-memory --ui --port 9090
|
|
93
98
|
```
|
|
94
99
|
|
|
95
|
-
The web UI uses the same database as the MCP server.
|
|
96
|
-
append-only; the web UI is the only way to edit or delete memories.
|
|
100
|
+
The web UI uses the same database as the MCP server.
|
|
97
101
|
|
|
98
102
|
## Tools
|
|
99
103
|
|
|
@@ -127,6 +131,31 @@ Output:
|
|
|
127
131
|
|
|
128
132
|
- `results[]` with `id`, `content`, `score`, `workspace`, and `updated_at`
|
|
129
133
|
|
|
134
|
+
### `revise`
|
|
135
|
+
|
|
136
|
+
Update the content of an existing memory.
|
|
137
|
+
|
|
138
|
+
Inputs:
|
|
139
|
+
|
|
140
|
+
- `id` -> the memory id from a previous recall result
|
|
141
|
+
- `content` -> replacement content for the memory
|
|
142
|
+
|
|
143
|
+
Output:
|
|
144
|
+
|
|
145
|
+
- `id`, `updated_at`
|
|
146
|
+
|
|
147
|
+
### `forget`
|
|
148
|
+
|
|
149
|
+
Permanently delete a memory.
|
|
150
|
+
|
|
151
|
+
Inputs:
|
|
152
|
+
|
|
153
|
+
- `id` -> the memory id from a previous recall result
|
|
154
|
+
|
|
155
|
+
Output:
|
|
156
|
+
|
|
157
|
+
- `id`, `deleted`
|
|
158
|
+
|
|
130
159
|
## How Ranking Works
|
|
131
160
|
|
|
132
161
|
`recall` uses a multi-signal ranking system to surface the most relevant
|
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.12";
|
|
12468
12468
|
|
|
12469
12469
|
// src/config.ts
|
|
12470
12470
|
import { homedir } from "node:os";
|
|
@@ -19895,9 +19895,6 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
19895
19895
|
}
|
|
19896
19896
|
};
|
|
19897
19897
|
|
|
19898
|
-
// src/memory-service.ts
|
|
19899
|
-
import { randomUUID } from "node:crypto";
|
|
19900
|
-
|
|
19901
19898
|
// src/errors.ts
|
|
19902
19899
|
class MemoryError extends Error {
|
|
19903
19900
|
code;
|
|
@@ -19929,6 +19926,55 @@ class PersistenceError extends MemoryError {
|
|
|
19929
19926
|
}
|
|
19930
19927
|
}
|
|
19931
19928
|
|
|
19929
|
+
// src/tools/shared.ts
|
|
19930
|
+
var toMcpError = (error2) => {
|
|
19931
|
+
if (error2 instanceof McpError) {
|
|
19932
|
+
return error2;
|
|
19933
|
+
}
|
|
19934
|
+
if (error2 instanceof MemoryError) {
|
|
19935
|
+
if (error2.code === "VALIDATION_ERROR" || error2.code === "NOT_FOUND") {
|
|
19936
|
+
return new McpError(ErrorCode.InvalidParams, error2.message);
|
|
19937
|
+
}
|
|
19938
|
+
return new McpError(ErrorCode.InternalError, error2.message);
|
|
19939
|
+
}
|
|
19940
|
+
const message = error2 instanceof Error ? error2.message : "Unknown server error.";
|
|
19941
|
+
return new McpError(ErrorCode.InternalError, message);
|
|
19942
|
+
};
|
|
19943
|
+
var escapeXml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
19944
|
+
var parseOptionalDate = (value, fieldName) => {
|
|
19945
|
+
if (!value) {
|
|
19946
|
+
return;
|
|
19947
|
+
}
|
|
19948
|
+
const date4 = new Date(value);
|
|
19949
|
+
if (Number.isNaN(date4.getTime())) {
|
|
19950
|
+
throw new MemoryError("VALIDATION_ERROR", `${fieldName} must be a valid ISO 8601 datetime.`);
|
|
19951
|
+
}
|
|
19952
|
+
return date4;
|
|
19953
|
+
};
|
|
19954
|
+
|
|
19955
|
+
// src/tools/forget.ts
|
|
19956
|
+
var forgetInputSchema = {
|
|
19957
|
+
id: string2().describe("The id of the memory to delete. Use the id returned by a previous recall result.")
|
|
19958
|
+
};
|
|
19959
|
+
var registerForgetTool = (server, memoryService) => {
|
|
19960
|
+
server.registerTool("forget", {
|
|
19961
|
+
description: "Permanently delete a memory that is wrong, obsolete, or no longer relevant. Pass the memory id from a previous recall result.",
|
|
19962
|
+
inputSchema: forgetInputSchema
|
|
19963
|
+
}, async ({ id }) => {
|
|
19964
|
+
try {
|
|
19965
|
+
await memoryService.forget({ id });
|
|
19966
|
+
return {
|
|
19967
|
+
content: [{ type: "text", text: `<memory id="${id.trim()}" deleted="true" />` }]
|
|
19968
|
+
};
|
|
19969
|
+
} catch (error2) {
|
|
19970
|
+
throw toMcpError(error2);
|
|
19971
|
+
}
|
|
19972
|
+
});
|
|
19973
|
+
};
|
|
19974
|
+
|
|
19975
|
+
// src/memory-service.ts
|
|
19976
|
+
import { randomUUID } from "node:crypto";
|
|
19977
|
+
|
|
19932
19978
|
// src/memory.ts
|
|
19933
19979
|
var toNormalizedScore = (value) => value;
|
|
19934
19980
|
|
|
@@ -19963,6 +20009,18 @@ class MemoryService {
|
|
|
19963
20009
|
};
|
|
19964
20010
|
return this.repository.save(memory);
|
|
19965
20011
|
}
|
|
20012
|
+
async revise(input) {
|
|
20013
|
+
const content = input.content.trim();
|
|
20014
|
+
if (!content)
|
|
20015
|
+
throw new ValidationError("Memory content is required.");
|
|
20016
|
+
return this.repository.update(input.id, content);
|
|
20017
|
+
}
|
|
20018
|
+
async forget(input) {
|
|
20019
|
+
const id = input.id.trim();
|
|
20020
|
+
if (!id)
|
|
20021
|
+
throw new ValidationError("Memory id is required.");
|
|
20022
|
+
return this.repository.delete(id);
|
|
20023
|
+
}
|
|
19966
20024
|
async search(input) {
|
|
19967
20025
|
const terms = normalizeTerms(input.terms);
|
|
19968
20026
|
if (terms.length === 0) {
|
|
@@ -20040,32 +20098,6 @@ function rerankSearchResults(results, workspace) {
|
|
|
20040
20098
|
});
|
|
20041
20099
|
}
|
|
20042
20100
|
|
|
20043
|
-
// src/tools/shared.ts
|
|
20044
|
-
var toMcpError = (error2) => {
|
|
20045
|
-
if (error2 instanceof McpError) {
|
|
20046
|
-
return error2;
|
|
20047
|
-
}
|
|
20048
|
-
if (error2 instanceof MemoryError) {
|
|
20049
|
-
if (error2.code === "VALIDATION_ERROR") {
|
|
20050
|
-
return new McpError(ErrorCode.InvalidParams, error2.message);
|
|
20051
|
-
}
|
|
20052
|
-
return new McpError(ErrorCode.InternalError, error2.message);
|
|
20053
|
-
}
|
|
20054
|
-
const message = error2 instanceof Error ? error2.message : "Unknown server error.";
|
|
20055
|
-
return new McpError(ErrorCode.InternalError, message);
|
|
20056
|
-
};
|
|
20057
|
-
var escapeXml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
20058
|
-
var parseOptionalDate = (value, fieldName) => {
|
|
20059
|
-
if (!value) {
|
|
20060
|
-
return;
|
|
20061
|
-
}
|
|
20062
|
-
const date4 = new Date(value);
|
|
20063
|
-
if (Number.isNaN(date4.getTime())) {
|
|
20064
|
-
throw new MemoryError("VALIDATION_ERROR", `${fieldName} must be a valid ISO 8601 datetime.`);
|
|
20065
|
-
}
|
|
20066
|
-
return date4;
|
|
20067
|
-
};
|
|
20068
|
-
|
|
20069
20101
|
// src/tools/recall.ts
|
|
20070
20102
|
var recallInputSchema = {
|
|
20071
20103
|
terms: array(string2()).min(1).describe("Search terms used to find relevant memories. Pass 2-5 short, distinctive items as separate array entries. Be specific: instead of 'preferences' or 'context', name the actual topic -- e.g. 'error handling', 'commit format', 'testing strategy'. Do not repeat the project or workspace name here -- use the workspace parameter for project scoping. Avoid full sentences."),
|
|
@@ -20131,11 +20163,40 @@ var registerRememberTool = (server, memoryService) => {
|
|
|
20131
20163
|
});
|
|
20132
20164
|
};
|
|
20133
20165
|
|
|
20166
|
+
// src/tools/revise.ts
|
|
20167
|
+
var reviseInputSchema = {
|
|
20168
|
+
id: string2().describe("The id of the memory to update. Use the id returned by a previous recall result."),
|
|
20169
|
+
content: string2().describe("The replacement content for the memory. Use a single self-contained sentence or short note. One fact per memory.")
|
|
20170
|
+
};
|
|
20171
|
+
var registerReviseTool = (server, memoryService) => {
|
|
20172
|
+
server.registerTool("revise", {
|
|
20173
|
+
description: "Update the content of an existing memory. Use when a previously saved memory is outdated or inaccurate and needs correction rather than deletion. Pass the memory id from a previous recall result.",
|
|
20174
|
+
inputSchema: reviseInputSchema
|
|
20175
|
+
}, async ({ id, content }) => {
|
|
20176
|
+
try {
|
|
20177
|
+
const memory = await memoryService.revise({ id, content });
|
|
20178
|
+
return {
|
|
20179
|
+
content: [
|
|
20180
|
+
{
|
|
20181
|
+
type: "text",
|
|
20182
|
+
text: `<memory id="${memory.id}" updated_at="${memory.updatedAt.toISOString()}" />`
|
|
20183
|
+
}
|
|
20184
|
+
]
|
|
20185
|
+
};
|
|
20186
|
+
} catch (error2) {
|
|
20187
|
+
throw toMcpError(error2);
|
|
20188
|
+
}
|
|
20189
|
+
});
|
|
20190
|
+
};
|
|
20191
|
+
|
|
20134
20192
|
// src/mcp-server.ts
|
|
20135
20193
|
var SERVER_INSTRUCTIONS = [
|
|
20136
20194
|
"Stores decisions, corrections, and context that cannot be derived from code or git history.",
|
|
20137
20195
|
"Use `recall` at the start of every conversation and again mid-task before making design choices or picking conventions the user may have guided before.",
|
|
20138
20196
|
"Use `remember` when the user corrects your approach, states a preference, a key decision is established, or you learn project context not obvious from the code.",
|
|
20197
|
+
"Before saving a new memory, recall to check whether a memory about the same fact already exists. If so, use `revise` to update it instead of creating a duplicate.",
|
|
20198
|
+
"Use `revise` when a previously saved memory is outdated or inaccurate and needs correction rather than deletion.",
|
|
20199
|
+
"Use `forget` to remove memories that are wrong, obsolete, or no longer relevant.",
|
|
20139
20200
|
"Always pass workspace (the current working directory) to scope results to the active project.",
|
|
20140
20201
|
"Omit workspace only when saving a memory that applies across all projects."
|
|
20141
20202
|
].join(" ");
|
|
@@ -20148,6 +20209,8 @@ var createMcpServer = (memoryService, version3) => {
|
|
|
20148
20209
|
});
|
|
20149
20210
|
registerRememberTool(server, memoryService);
|
|
20150
20211
|
registerRecallTool(server, memoryService);
|
|
20212
|
+
registerReviseTool(server, memoryService);
|
|
20213
|
+
registerForgetTool(server, memoryService);
|
|
20151
20214
|
return server;
|
|
20152
20215
|
};
|
|
20153
20216
|
|