@jcyamacho/agent-memory 0.1.0 → 0.2.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/README.md +13 -1
- package/dist/index.js +174 -49
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ It exposes four tools:
|
|
|
10
10
|
|
|
11
11
|
- `remember` -> save facts, decisions, preferences, and project context
|
|
12
12
|
- `review` -> load workspace and global memories sorted by most recently updated
|
|
13
|
-
- `revise` -> update an existing memory when it
|
|
13
|
+
- `revise` -> update an existing memory when its content changes or when it should become global
|
|
14
14
|
- `forget` -> delete a memory that is no longer relevant
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
|
@@ -55,6 +55,11 @@ targets the habits models most commonly miss:
|
|
|
55
55
|
`memory_forget` to keep memories accurate.
|
|
56
56
|
- Pass `workspace` on `memory_remember` for project-scoped memory. Omit it
|
|
57
57
|
only for facts that apply across projects.
|
|
58
|
+
- Remember preferences, confirmed approaches, and decisions with reasoning
|
|
59
|
+
that would be lost after the session.
|
|
60
|
+
- Revise content when a fact changes, promote a project-scoped memory to
|
|
61
|
+
global only when it truly applies across projects, and forget it when it is
|
|
62
|
+
no longer relevant.
|
|
58
63
|
- Do not store secrets, temporary task state, or facts obvious from current
|
|
59
64
|
code or git history.
|
|
60
65
|
```
|
|
@@ -75,6 +80,13 @@ npx -y @jcyamacho/agent-memory@latest --ui --port 9090
|
|
|
75
80
|
|
|
76
81
|
The web UI uses the same database as the MCP server.
|
|
77
82
|
|
|
83
|
+
## Mutating Tool Output
|
|
84
|
+
|
|
85
|
+
`remember`, `revise`, and `forget` return the full affected memory
|
|
86
|
+
as XML with `updated_at` and scope information so clients that hide tool-call
|
|
87
|
+
arguments can still see what changed.
|
|
88
|
+
`forget` includes `deleted="true"` on the returned `<memory>` element.
|
|
89
|
+
|
|
78
90
|
## How Review Works
|
|
79
91
|
|
|
80
92
|
`review` requires a `workspace` and returns memories saved in that workspace
|
package/dist/index.js
CHANGED
|
@@ -11543,7 +11543,7 @@ var AssertObjectSchema = custom((v) => v !== null && (typeof v === "object" || t
|
|
|
11543
11543
|
var ProgressTokenSchema = union([string2(), number2().int()]);
|
|
11544
11544
|
var CursorSchema = string2();
|
|
11545
11545
|
var TaskCreationParamsSchema = looseObject({
|
|
11546
|
-
ttl:
|
|
11546
|
+
ttl: number2().optional(),
|
|
11547
11547
|
pollInterval: number2().optional()
|
|
11548
11548
|
});
|
|
11549
11549
|
var TaskMetadataSchema = object({
|
|
@@ -11697,7 +11697,8 @@ var ClientCapabilitiesSchema = object({
|
|
|
11697
11697
|
roots: object({
|
|
11698
11698
|
listChanged: boolean2().optional()
|
|
11699
11699
|
}).optional(),
|
|
11700
|
-
tasks: ClientTasksCapabilitySchema.optional()
|
|
11700
|
+
tasks: ClientTasksCapabilitySchema.optional(),
|
|
11701
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
11701
11702
|
});
|
|
11702
11703
|
var InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
|
|
11703
11704
|
protocolVersion: string2(),
|
|
@@ -11722,7 +11723,8 @@ var ServerCapabilitiesSchema = object({
|
|
|
11722
11723
|
tools: object({
|
|
11723
11724
|
listChanged: boolean2().optional()
|
|
11724
11725
|
}).optional(),
|
|
11725
|
-
tasks: ServerTasksCapabilitySchema.optional()
|
|
11726
|
+
tasks: ServerTasksCapabilitySchema.optional(),
|
|
11727
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
11726
11728
|
});
|
|
11727
11729
|
var InitializeResultSchema = ResultSchema.extend({
|
|
11728
11730
|
protocolVersion: string2(),
|
|
@@ -11837,6 +11839,7 @@ var ResourceSchema = object({
|
|
|
11837
11839
|
uri: string2(),
|
|
11838
11840
|
description: optional(string2()),
|
|
11839
11841
|
mimeType: optional(string2()),
|
|
11842
|
+
size: optional(number2()),
|
|
11840
11843
|
annotations: AnnotationsSchema.optional(),
|
|
11841
11844
|
_meta: optional(looseObject({}))
|
|
11842
11845
|
});
|
|
@@ -12464,7 +12467,7 @@ class StdioServerTransport {
|
|
|
12464
12467
|
}
|
|
12465
12468
|
}
|
|
12466
12469
|
// package.json
|
|
12467
|
-
var version2 = "0.
|
|
12470
|
+
var version2 = "0.2.0";
|
|
12468
12471
|
|
|
12469
12472
|
// src/config.ts
|
|
12470
12473
|
import { homedir } from "node:os";
|
|
@@ -17974,6 +17977,10 @@ class Protocol {
|
|
|
17974
17977
|
this._progressHandlers.clear();
|
|
17975
17978
|
this._taskProgressTokens.clear();
|
|
17976
17979
|
this._pendingDebouncedNotifications.clear();
|
|
17980
|
+
for (const info of this._timeoutInfo.values()) {
|
|
17981
|
+
clearTimeout(info.timeoutId);
|
|
17982
|
+
}
|
|
17983
|
+
this._timeoutInfo.clear();
|
|
17977
17984
|
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
17978
17985
|
controller.abort();
|
|
17979
17986
|
}
|
|
@@ -18104,7 +18111,9 @@ class Protocol {
|
|
|
18104
18111
|
await capturedTransport?.send(errorResponse);
|
|
18105
18112
|
}
|
|
18106
18113
|
}).catch((error2) => this._onerror(new Error(`Failed to send response: ${error2}`))).finally(() => {
|
|
18107
|
-
this._requestHandlerAbortControllers.
|
|
18114
|
+
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
18115
|
+
this._requestHandlerAbortControllers.delete(request.id);
|
|
18116
|
+
}
|
|
18108
18117
|
});
|
|
18109
18118
|
}
|
|
18110
18119
|
_onprogress(notification) {
|
|
@@ -19762,6 +19771,9 @@ class McpServer {
|
|
|
19762
19771
|
annotations = rest.shift();
|
|
19763
19772
|
}
|
|
19764
19773
|
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
19774
|
+
if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
|
|
19775
|
+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
|
|
19776
|
+
}
|
|
19765
19777
|
annotations = rest.shift();
|
|
19766
19778
|
}
|
|
19767
19779
|
}
|
|
@@ -19854,6 +19866,9 @@ function getZodSchemaObject(schema) {
|
|
|
19854
19866
|
if (isZodRawShapeCompat(schema)) {
|
|
19855
19867
|
return objectFromShape(schema);
|
|
19856
19868
|
}
|
|
19869
|
+
if (!isZodSchemaInstance(schema)) {
|
|
19870
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
19871
|
+
}
|
|
19857
19872
|
return schema;
|
|
19858
19873
|
}
|
|
19859
19874
|
function promptArgumentsFromSchema(schema) {
|
|
@@ -19944,6 +19959,27 @@ function toMcpError(error2) {
|
|
|
19944
19959
|
return new McpError(ErrorCode.InternalError, message);
|
|
19945
19960
|
}
|
|
19946
19961
|
var escapeXml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
19962
|
+
function toMemoryXml(record3, options) {
|
|
19963
|
+
const scopeAttribute = getMemoryScopeAttribute(record3, options?.skipWorkspaceIfEquals);
|
|
19964
|
+
const attributes = [
|
|
19965
|
+
`id="${escapeXml(record3.id)}"`,
|
|
19966
|
+
`updated_at="${record3.updatedAt.toISOString()}"`,
|
|
19967
|
+
scopeAttribute,
|
|
19968
|
+
options?.deleted ? 'deleted="true"' : undefined
|
|
19969
|
+
].filter((value) => value).join(" ");
|
|
19970
|
+
return `<memory ${attributes}>
|
|
19971
|
+
${escapeXml(record3.content)}
|
|
19972
|
+
</memory>`;
|
|
19973
|
+
}
|
|
19974
|
+
function getMemoryScopeAttribute(record3, skipWorkspaceIfEquals) {
|
|
19975
|
+
if (record3.workspace === undefined) {
|
|
19976
|
+
return 'global="true"';
|
|
19977
|
+
}
|
|
19978
|
+
if (record3.workspace === skipWorkspaceIfEquals) {
|
|
19979
|
+
return;
|
|
19980
|
+
}
|
|
19981
|
+
return `workspace="${escapeXml(record3.workspace)}"`;
|
|
19982
|
+
}
|
|
19947
19983
|
|
|
19948
19984
|
// src/mcp/tools/forget.ts
|
|
19949
19985
|
var forgetInputSchema = {
|
|
@@ -19957,13 +19993,13 @@ function registerForgetTool(server, memory) {
|
|
|
19957
19993
|
idempotentHint: true,
|
|
19958
19994
|
openWorldHint: false
|
|
19959
19995
|
},
|
|
19960
|
-
description: 'Delete a memory that is wrong or obsolete. Use after `review` when you have the memory id. Use `revise` instead if the fact should remain with corrected wording. Returns `<memory
|
|
19996
|
+
description: 'Delete a memory that is wrong or obsolete. Use after `review` when you have the memory id. Use `revise` instead if the fact should remain with corrected wording. Returns the deleted memory as `<memory ... deleted="true">...</memory>`.',
|
|
19961
19997
|
inputSchema: forgetInputSchema
|
|
19962
19998
|
}, async ({ id }) => {
|
|
19963
19999
|
try {
|
|
19964
|
-
await memory.delete({ id });
|
|
20000
|
+
const deletedMemory = await memory.delete({ id });
|
|
19965
20001
|
return {
|
|
19966
|
-
content: [{ type: "text", text:
|
|
20002
|
+
content: [{ type: "text", text: toMemoryXml(deletedMemory, { deleted: true }) }]
|
|
19967
20003
|
};
|
|
19968
20004
|
} catch (error2) {
|
|
19969
20005
|
throw toMcpError(error2);
|
|
@@ -19984,7 +20020,7 @@ function registerRememberTool(server, memory) {
|
|
|
19984
20020
|
idempotentHint: false,
|
|
19985
20021
|
openWorldHint: false
|
|
19986
20022
|
},
|
|
19987
|
-
description:
|
|
20023
|
+
description: "Save one new durable fact. 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 the saved memory as `<memory ...>...</memory>`.",
|
|
19988
20024
|
inputSchema: rememberInputSchema
|
|
19989
20025
|
}, async ({ content, workspace }) => {
|
|
19990
20026
|
try {
|
|
@@ -19993,7 +20029,7 @@ function registerRememberTool(server, memory) {
|
|
|
19993
20029
|
workspace
|
|
19994
20030
|
});
|
|
19995
20031
|
return {
|
|
19996
|
-
content: [{ type: "text", text:
|
|
20032
|
+
content: [{ type: "text", text: toMemoryXml(savedMemory) }]
|
|
19997
20033
|
};
|
|
19998
20034
|
} catch (error2) {
|
|
19999
20035
|
throw toMcpError(error2);
|
|
@@ -20007,13 +20043,6 @@ var reviewInputSchema = {
|
|
|
20007
20043
|
workspace: string2().describe("Current working directory for project-scoped listing."),
|
|
20008
20044
|
page: number2().int().min(0).optional().describe("Zero-based page number. Defaults to 0.")
|
|
20009
20045
|
};
|
|
20010
|
-
function toMemoryXml(record3, workspace) {
|
|
20011
|
-
const global2 = record3.workspace !== workspace ? ' global="true"' : "";
|
|
20012
|
-
const content = escapeXml(record3.content);
|
|
20013
|
-
return `<memory id="${record3.id}"${global2} updated_at="${record3.updatedAt.toISOString()}">
|
|
20014
|
-
${content}
|
|
20015
|
-
</memory>`;
|
|
20016
|
-
}
|
|
20017
20046
|
function registerReviewTool(server, memory) {
|
|
20018
20047
|
server.registerTool("review", {
|
|
20019
20048
|
annotations: {
|
|
@@ -20038,7 +20067,7 @@ function registerReviewTool(server, memory) {
|
|
|
20038
20067
|
};
|
|
20039
20068
|
}
|
|
20040
20069
|
const escapedWorkspace = escapeXml(workspace);
|
|
20041
|
-
const memories = result.items.map((item) => toMemoryXml(item, workspace)).join(`
|
|
20070
|
+
const memories = result.items.map((item) => toMemoryXml(item, { skipWorkspaceIfEquals: workspace })).join(`
|
|
20042
20071
|
`);
|
|
20043
20072
|
const text = `<memories workspace="${escapedWorkspace}" has_more="${result.hasMore}">
|
|
20044
20073
|
${memories}
|
|
@@ -20055,7 +20084,8 @@ ${memories}
|
|
|
20055
20084
|
// src/mcp/tools/revise.ts
|
|
20056
20085
|
var reviseInputSchema = {
|
|
20057
20086
|
id: string2().describe("Memory id to update. Use an id returned by `review`."),
|
|
20058
|
-
content: string2().describe("Corrected replacement text for that memory.")
|
|
20087
|
+
content: string2().optional().describe("Corrected replacement text for that memory. Omit to keep the current content."),
|
|
20088
|
+
global: boolean2().optional().describe("Set to true to move a project-scoped memory to global scope.")
|
|
20059
20089
|
};
|
|
20060
20090
|
function registerReviseTool(server, memory) {
|
|
20061
20091
|
server.registerTool("revise", {
|
|
@@ -20065,16 +20095,23 @@ function registerReviseTool(server, memory) {
|
|
|
20065
20095
|
idempotentHint: false,
|
|
20066
20096
|
openWorldHint: false
|
|
20067
20097
|
},
|
|
20068
|
-
description:
|
|
20098
|
+
description: "Update one existing memory when the same fact still applies but its wording changed, or when a project-scoped memory should become global. Use after `review` when you already have the memory id. Omit fields you do not want to change. Returns the revised memory as `<memory ...>...</memory>`.",
|
|
20069
20099
|
inputSchema: reviseInputSchema
|
|
20070
|
-
}, async ({ id, content }) => {
|
|
20100
|
+
}, async ({ id, content, global: global2 }) => {
|
|
20071
20101
|
try {
|
|
20072
|
-
|
|
20102
|
+
if (content === undefined && global2 !== true) {
|
|
20103
|
+
throw new ValidationError("Provide at least one field to revise.");
|
|
20104
|
+
}
|
|
20105
|
+
const revisedMemory = await memory.update({
|
|
20106
|
+
id,
|
|
20107
|
+
content,
|
|
20108
|
+
workspace: global2 === true ? null : undefined
|
|
20109
|
+
});
|
|
20073
20110
|
return {
|
|
20074
20111
|
content: [
|
|
20075
20112
|
{
|
|
20076
20113
|
type: "text",
|
|
20077
|
-
text:
|
|
20114
|
+
text: toMemoryXml(revisedMemory)
|
|
20078
20115
|
}
|
|
20079
20116
|
]
|
|
20080
20117
|
};
|
|
@@ -20088,7 +20125,7 @@ function registerReviseTool(server, memory) {
|
|
|
20088
20125
|
var SERVER_INSTRUCTIONS = [
|
|
20089
20126
|
"Durable memory for stable preferences, corrections, reusable decisions, and project context not obvious from code or git history.",
|
|
20090
20127
|
"Workflow: (1) Call `review` with the current workspace at conversation start -- this loads workspace and global memories into context.",
|
|
20091
|
-
"(2) During the session, call `remember` to save a new fact, `revise` to correct
|
|
20128
|
+
"(2) During the session, call `remember` to save a new fact, `revise` to correct content or promote a project-scoped memory to global scope, and call `forget` to remove one that is wrong or obsolete.",
|
|
20092
20129
|
"Always check loaded memories before calling `remember` to avoid duplicates -- use `revise` instead when the fact already exists.",
|
|
20093
20130
|
"Pass workspace on `remember` for project-scoped memory. Omit it only for facts that apply across all projects.",
|
|
20094
20131
|
"Never store secrets, temporary task state, or facts obvious from current code or git history."
|
|
@@ -20123,27 +20160,31 @@ class MemoryService {
|
|
|
20123
20160
|
if (!content) {
|
|
20124
20161
|
throw new ValidationError("Memory content is required.");
|
|
20125
20162
|
}
|
|
20126
|
-
const workspace = await this.
|
|
20163
|
+
const workspace = await this.normalizeWorkspaceInput(input.workspace);
|
|
20127
20164
|
return this.repository.create({ content, workspace });
|
|
20128
20165
|
}
|
|
20129
20166
|
async update(input) {
|
|
20130
|
-
const content = input.content
|
|
20131
|
-
|
|
20132
|
-
|
|
20133
|
-
return this.repository.update({ id: input.id, content });
|
|
20167
|
+
const content = this.normalizeUpdateContent(input.content);
|
|
20168
|
+
const workspace = await this.normalizeUpdateWorkspace(input.workspace);
|
|
20169
|
+
return this.repository.update({ id: input.id, content, workspace });
|
|
20134
20170
|
}
|
|
20135
20171
|
async delete(input) {
|
|
20136
20172
|
const id = input.id.trim();
|
|
20137
20173
|
if (!id)
|
|
20138
20174
|
throw new ValidationError("Memory id is required.");
|
|
20139
|
-
|
|
20175
|
+
const existingMemory = await this.repository.get(id);
|
|
20176
|
+
if (!existingMemory) {
|
|
20177
|
+
throw new NotFoundError(`Memory not found: ${id}`);
|
|
20178
|
+
}
|
|
20179
|
+
await this.repository.delete({ id });
|
|
20180
|
+
return existingMemory;
|
|
20140
20181
|
}
|
|
20141
20182
|
async get(id) {
|
|
20142
20183
|
return this.repository.get(id);
|
|
20143
20184
|
}
|
|
20144
20185
|
async list(input) {
|
|
20145
|
-
const queryWorkspace =
|
|
20146
|
-
const workspace = await this.workspaceResolver.resolve(
|
|
20186
|
+
const queryWorkspace = input.workspace?.trim() || undefined;
|
|
20187
|
+
const workspace = queryWorkspace ? await this.workspaceResolver.resolve(queryWorkspace) : undefined;
|
|
20147
20188
|
const page = await this.repository.list({
|
|
20148
20189
|
workspace,
|
|
20149
20190
|
global: input.global,
|
|
@@ -20158,6 +20199,32 @@ class MemoryService {
|
|
|
20158
20199
|
async listWorkspaces() {
|
|
20159
20200
|
return this.repository.listWorkspaces();
|
|
20160
20201
|
}
|
|
20202
|
+
normalizeUpdateContent(value) {
|
|
20203
|
+
if (value === undefined) {
|
|
20204
|
+
return;
|
|
20205
|
+
}
|
|
20206
|
+
const trimmed = value.trim();
|
|
20207
|
+
if (!trimmed) {
|
|
20208
|
+
throw new ValidationError("Memory content is required.");
|
|
20209
|
+
}
|
|
20210
|
+
return trimmed;
|
|
20211
|
+
}
|
|
20212
|
+
async normalizeUpdateWorkspace(value) {
|
|
20213
|
+
if (value === undefined || value === null) {
|
|
20214
|
+
return value;
|
|
20215
|
+
}
|
|
20216
|
+
return this.normalizeWorkspaceInput(value);
|
|
20217
|
+
}
|
|
20218
|
+
async normalizeWorkspaceInput(value) {
|
|
20219
|
+
if (value === undefined) {
|
|
20220
|
+
return;
|
|
20221
|
+
}
|
|
20222
|
+
const trimmed = value.trim();
|
|
20223
|
+
if (!trimmed) {
|
|
20224
|
+
throw new ValidationError("Workspace is required.");
|
|
20225
|
+
}
|
|
20226
|
+
return this.workspaceResolver.resolve(trimmed);
|
|
20227
|
+
}
|
|
20161
20228
|
}
|
|
20162
20229
|
function normalizeOffset(value) {
|
|
20163
20230
|
return Number.isInteger(value) && value && value > 0 ? value : 0;
|
|
@@ -20168,10 +20235,6 @@ function normalizeListLimit(value) {
|
|
|
20168
20235
|
}
|
|
20169
20236
|
return Math.min(Math.max(value, 1), MAX_LIST_LIMIT);
|
|
20170
20237
|
}
|
|
20171
|
-
function normalizeOptionalString(value) {
|
|
20172
|
-
const trimmed = value?.trim();
|
|
20173
|
-
return trimmed ? trimmed : undefined;
|
|
20174
|
-
}
|
|
20175
20238
|
function remapWorkspace(record3, canonicalWorkspace, queryWorkspace) {
|
|
20176
20239
|
if (record3.workspace !== canonicalWorkspace) {
|
|
20177
20240
|
return record3;
|
|
@@ -20425,7 +20488,7 @@ class SqliteMemoryRepository {
|
|
|
20425
20488
|
VALUES (?, ?, ?, ?, ?)
|
|
20426
20489
|
`);
|
|
20427
20490
|
this.getStatement = database.prepare("SELECT id, content, workspace, created_at, updated_at FROM memories WHERE id = ?");
|
|
20428
|
-
this.updateStatement = database.prepare("UPDATE memories SET content = ?, updated_at = ? WHERE id = ?");
|
|
20491
|
+
this.updateStatement = database.prepare("UPDATE memories SET content = ?, workspace = ?, updated_at = ? WHERE id = ?");
|
|
20429
20492
|
this.deleteStatement = database.prepare("DELETE FROM memories WHERE id = ?");
|
|
20430
20493
|
this.listWorkspacesStatement = database.prepare("SELECT DISTINCT workspace FROM memories WHERE workspace IS NOT NULL ORDER BY workspace");
|
|
20431
20494
|
}
|
|
@@ -20488,10 +20551,18 @@ class SqliteMemoryRepository {
|
|
|
20488
20551
|
}
|
|
20489
20552
|
}
|
|
20490
20553
|
async update(input) {
|
|
20554
|
+
const existingMemory = await this.get(input.id);
|
|
20555
|
+
if (!existingMemory) {
|
|
20556
|
+
throw new NotFoundError(`Memory not found: ${input.id}`);
|
|
20557
|
+
}
|
|
20558
|
+
const patch = applyMemoryPatch(existingMemory, input);
|
|
20559
|
+
if (!hasMemoryChanges(existingMemory, patch)) {
|
|
20560
|
+
return existingMemory;
|
|
20561
|
+
}
|
|
20491
20562
|
let result;
|
|
20492
20563
|
try {
|
|
20493
20564
|
const now = Date.now();
|
|
20494
|
-
result = this.updateStatement.run(
|
|
20565
|
+
result = this.updateStatement.run(patch.content, patch.workspace, now, input.id);
|
|
20495
20566
|
} catch (error2) {
|
|
20496
20567
|
throw new PersistenceError("Failed to update memory.", { cause: error2 });
|
|
20497
20568
|
}
|
|
@@ -20531,9 +20602,21 @@ var toMemoryRecord = (row) => ({
|
|
|
20531
20602
|
createdAt: new Date(row.created_at),
|
|
20532
20603
|
updatedAt: new Date(row.updated_at)
|
|
20533
20604
|
});
|
|
20605
|
+
function applyMemoryPatch(memory, input) {
|
|
20606
|
+
return {
|
|
20607
|
+
content: input.content ?? memory.content,
|
|
20608
|
+
workspace: input.workspace === undefined ? toStoredWorkspace(memory.workspace) : input.workspace
|
|
20609
|
+
};
|
|
20610
|
+
}
|
|
20611
|
+
function hasMemoryChanges(memory, patch) {
|
|
20612
|
+
return patch.content !== memory.content || patch.workspace !== toStoredWorkspace(memory.workspace);
|
|
20613
|
+
}
|
|
20614
|
+
function toStoredWorkspace(workspace) {
|
|
20615
|
+
return workspace ?? null;
|
|
20616
|
+
}
|
|
20534
20617
|
// node_modules/@hono/node-server/dist/index.mjs
|
|
20535
20618
|
import { createServer as createServerHTTP } from "http";
|
|
20536
|
-
import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
|
|
20619
|
+
import { Http2ServerRequest as Http2ServerRequest2, constants as h2constants } from "http2";
|
|
20537
20620
|
import { Http2ServerRequest } from "http2";
|
|
20538
20621
|
import { Readable } from "stream";
|
|
20539
20622
|
import crypto from "crypto";
|
|
@@ -20843,6 +20926,48 @@ if (typeof global.crypto === "undefined") {
|
|
|
20843
20926
|
global.crypto = crypto;
|
|
20844
20927
|
}
|
|
20845
20928
|
var outgoingEnded = Symbol("outgoingEnded");
|
|
20929
|
+
var incomingDraining = Symbol("incomingDraining");
|
|
20930
|
+
var DRAIN_TIMEOUT_MS = 500;
|
|
20931
|
+
var MAX_DRAIN_BYTES = 64 * 1024 * 1024;
|
|
20932
|
+
var drainIncoming = (incoming) => {
|
|
20933
|
+
const incomingWithDrainState = incoming;
|
|
20934
|
+
if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
|
|
20935
|
+
return;
|
|
20936
|
+
}
|
|
20937
|
+
incomingWithDrainState[incomingDraining] = true;
|
|
20938
|
+
if (incoming instanceof Http2ServerRequest2) {
|
|
20939
|
+
try {
|
|
20940
|
+
incoming.stream?.close?.(h2constants.NGHTTP2_NO_ERROR);
|
|
20941
|
+
} catch {}
|
|
20942
|
+
return;
|
|
20943
|
+
}
|
|
20944
|
+
let bytesRead = 0;
|
|
20945
|
+
const cleanup = () => {
|
|
20946
|
+
clearTimeout(timer);
|
|
20947
|
+
incoming.off("data", onData);
|
|
20948
|
+
incoming.off("end", cleanup);
|
|
20949
|
+
incoming.off("error", cleanup);
|
|
20950
|
+
};
|
|
20951
|
+
const forceClose = () => {
|
|
20952
|
+
cleanup();
|
|
20953
|
+
const socket = incoming.socket;
|
|
20954
|
+
if (socket && !socket.destroyed) {
|
|
20955
|
+
socket.destroySoon();
|
|
20956
|
+
}
|
|
20957
|
+
};
|
|
20958
|
+
const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
|
|
20959
|
+
timer.unref?.();
|
|
20960
|
+
const onData = (chunk) => {
|
|
20961
|
+
bytesRead += chunk.length;
|
|
20962
|
+
if (bytesRead > MAX_DRAIN_BYTES) {
|
|
20963
|
+
forceClose();
|
|
20964
|
+
}
|
|
20965
|
+
};
|
|
20966
|
+
incoming.on("data", onData);
|
|
20967
|
+
incoming.on("end", cleanup);
|
|
20968
|
+
incoming.on("error", cleanup);
|
|
20969
|
+
incoming.resume();
|
|
20970
|
+
};
|
|
20846
20971
|
var handleRequestError = () => new Response(null, {
|
|
20847
20972
|
status: 400
|
|
20848
20973
|
});
|
|
@@ -21006,14 +21131,18 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
21006
21131
|
setTimeout(() => {
|
|
21007
21132
|
if (!incomingEnded) {
|
|
21008
21133
|
setTimeout(() => {
|
|
21009
|
-
incoming
|
|
21010
|
-
outgoing.destroy();
|
|
21134
|
+
drainIncoming(incoming);
|
|
21011
21135
|
});
|
|
21012
21136
|
}
|
|
21013
21137
|
});
|
|
21014
21138
|
}
|
|
21015
21139
|
};
|
|
21016
21140
|
}
|
|
21141
|
+
outgoing.on("finish", () => {
|
|
21142
|
+
if (!incomingEnded) {
|
|
21143
|
+
drainIncoming(incoming);
|
|
21144
|
+
}
|
|
21145
|
+
});
|
|
21017
21146
|
}
|
|
21018
21147
|
outgoing.on("close", () => {
|
|
21019
21148
|
const abortController = req[abortControllerKey];
|
|
@@ -21028,7 +21157,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
21028
21157
|
setTimeout(() => {
|
|
21029
21158
|
if (!incomingEnded) {
|
|
21030
21159
|
setTimeout(() => {
|
|
21031
|
-
incoming
|
|
21160
|
+
drainIncoming(incoming);
|
|
21032
21161
|
});
|
|
21033
21162
|
}
|
|
21034
21163
|
});
|
|
@@ -21453,7 +21582,7 @@ var HonoRequest = class {
|
|
|
21453
21582
|
return headerData;
|
|
21454
21583
|
}
|
|
21455
21584
|
async parseBody(options) {
|
|
21456
|
-
return
|
|
21585
|
+
return parseBody(this, options);
|
|
21457
21586
|
}
|
|
21458
21587
|
#cachedBody = (key) => {
|
|
21459
21588
|
const { bodyCache, raw } = this;
|
|
@@ -23929,9 +24058,9 @@ function createGitWorkspaceResolver(options = {}) {
|
|
|
23929
24058
|
const cache = new Map;
|
|
23930
24059
|
return {
|
|
23931
24060
|
async resolve(workspace) {
|
|
23932
|
-
const trimmed =
|
|
24061
|
+
const trimmed = workspace.trim();
|
|
23933
24062
|
if (!trimmed) {
|
|
23934
|
-
|
|
24063
|
+
throw new ValidationError("Workspace is required.");
|
|
23935
24064
|
}
|
|
23936
24065
|
const cached2 = cache.get(trimmed);
|
|
23937
24066
|
if (cached2) {
|
|
@@ -23960,10 +24089,6 @@ async function defaultGetGitCommonDir(cwd) {
|
|
|
23960
24089
|
});
|
|
23961
24090
|
return stdout.trim();
|
|
23962
24091
|
}
|
|
23963
|
-
function normalizeOptionalString2(value) {
|
|
23964
|
-
const trimmed = value?.trim();
|
|
23965
|
-
return trimmed ? trimmed : undefined;
|
|
23966
|
-
}
|
|
23967
24092
|
|
|
23968
24093
|
// src/index.ts
|
|
23969
24094
|
var config2 = resolveConfig();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jcyamacho/agent-memory",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-memory": "dist/index.js"
|
|
7
7
|
},
|
|
@@ -29,18 +29,18 @@
|
|
|
29
29
|
"release:major": "npm version major && git push origin main --follow-tags"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@biomejs/biome": "2.4.
|
|
32
|
+
"@biomejs/biome": "2.4.11",
|
|
33
33
|
"@types/better-sqlite3": "^7.6.13",
|
|
34
34
|
"@types/bun": "latest"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"typescript": "^5"
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@hono/node-server": "^1.19.
|
|
41
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
42
|
-
"better-sqlite3": "^12.
|
|
43
|
-
"hono": "^4.12.
|
|
40
|
+
"@hono/node-server": "^1.19.13",
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
|
+
"better-sqlite3": "^12.8.0",
|
|
43
|
+
"hono": "^4.12.12",
|
|
44
44
|
"zod": "^4.3.6"
|
|
45
45
|
}
|
|
46
46
|
}
|