@hasna/mementos 0.10.11 → 0.10.13
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.
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote sync — push/pull memories to/from a remote mementos-serve instance.
|
|
3
|
+
*
|
|
4
|
+
* The remote must be running `mementos-serve`. Point at it via:
|
|
5
|
+
* MEMENTOS_REMOTE_URL=http://apple01:19428
|
|
6
|
+
* or pass the URL directly to push/pull functions.
|
|
7
|
+
*/
|
|
8
|
+
declare const DEFAULT_PORT = 19428;
|
|
9
|
+
export interface RemoteSyncOptions {
|
|
10
|
+
remoteUrl?: string;
|
|
11
|
+
scope?: "global" | "shared" | "private";
|
|
12
|
+
agentId?: string;
|
|
13
|
+
projectId?: string;
|
|
14
|
+
since?: string;
|
|
15
|
+
limit?: number;
|
|
16
|
+
overwrite?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface RemoteSyncResult {
|
|
19
|
+
pushed?: number;
|
|
20
|
+
pulled?: number;
|
|
21
|
+
errors: string[];
|
|
22
|
+
remote_url: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Push local memories to a remote mementos-serve instance.
|
|
26
|
+
* Uses POST /api/memories/import on the remote.
|
|
27
|
+
*/
|
|
28
|
+
export declare function pushToRemote(opts?: RemoteSyncOptions): Promise<RemoteSyncResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Pull memories from a remote mementos-serve instance into local DB.
|
|
31
|
+
* Uses POST /api/memories/export on the remote.
|
|
32
|
+
*/
|
|
33
|
+
export declare function pullFromRemote(opts?: RemoteSyncOptions): Promise<RemoteSyncResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Bidirectional sync: push local then pull remote.
|
|
36
|
+
* On key conflict, newer timestamp wins.
|
|
37
|
+
*/
|
|
38
|
+
export declare function syncWithRemote(opts?: RemoteSyncOptions): Promise<RemoteSyncResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a remote mementos-serve is reachable.
|
|
41
|
+
*/
|
|
42
|
+
export declare function pingRemote(url?: string): Promise<{
|
|
43
|
+
ok: boolean;
|
|
44
|
+
url: string;
|
|
45
|
+
status?: number;
|
|
46
|
+
error?: string;
|
|
47
|
+
}>;
|
|
48
|
+
export { DEFAULT_PORT };
|
|
49
|
+
//# sourceMappingURL=remote-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-sync.d.ts","sourceRoot":"","sources":["../../src/lib/remote-sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,QAAA,MAAM,YAAY,QAAQ,CAAC;AAE3B,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAqBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4B1F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyB5F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU5F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAUrH;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -3461,6 +3461,104 @@ var init_memory_broadcast = __esm(() => {
|
|
|
3461
3461
|
CONVERSATIONS_API = process.env.CONVERSATIONS_API_URL || "http://localhost:7020";
|
|
3462
3462
|
});
|
|
3463
3463
|
|
|
3464
|
+
// src/lib/remote-sync.ts
|
|
3465
|
+
var exports_remote_sync = {};
|
|
3466
|
+
__export(exports_remote_sync, {
|
|
3467
|
+
syncWithRemote: () => syncWithRemote,
|
|
3468
|
+
pushToRemote: () => pushToRemote,
|
|
3469
|
+
pullFromRemote: () => pullFromRemote,
|
|
3470
|
+
pingRemote: () => pingRemote,
|
|
3471
|
+
DEFAULT_PORT: () => DEFAULT_PORT
|
|
3472
|
+
});
|
|
3473
|
+
function resolveUrl(url) {
|
|
3474
|
+
const raw = url ?? process.env["MEMENTOS_REMOTE_URL"] ?? "";
|
|
3475
|
+
if (!raw)
|
|
3476
|
+
throw new Error("No remote URL. Set MEMENTOS_REMOTE_URL or pass url.");
|
|
3477
|
+
return raw.replace(/\/$/, "");
|
|
3478
|
+
}
|
|
3479
|
+
async function fetchJson(url, init) {
|
|
3480
|
+
const res = await fetch(url, {
|
|
3481
|
+
...init,
|
|
3482
|
+
headers: { "Content-Type": "application/json", ...init?.headers },
|
|
3483
|
+
signal: AbortSignal.timeout(15000)
|
|
3484
|
+
});
|
|
3485
|
+
if (!res.ok) {
|
|
3486
|
+
const text = await res.text().catch(() => "");
|
|
3487
|
+
throw new Error(`Remote ${res.status}: ${text.slice(0, 200)}`);
|
|
3488
|
+
}
|
|
3489
|
+
return res.json();
|
|
3490
|
+
}
|
|
3491
|
+
async function pushToRemote(opts = {}) {
|
|
3492
|
+
const baseUrl = resolveUrl(opts.remoteUrl);
|
|
3493
|
+
const errors2 = [];
|
|
3494
|
+
const memories = listMemories({
|
|
3495
|
+
scope: opts.scope,
|
|
3496
|
+
agent_id: opts.agentId,
|
|
3497
|
+
project_id: opts.projectId,
|
|
3498
|
+
limit: opts.limit ?? 1e4
|
|
3499
|
+
});
|
|
3500
|
+
if (!memories.length) {
|
|
3501
|
+
return { pushed: 0, errors: [], remote_url: baseUrl };
|
|
3502
|
+
}
|
|
3503
|
+
const result = await fetchJson(`${baseUrl}/api/memories/import`, {
|
|
3504
|
+
method: "POST",
|
|
3505
|
+
body: JSON.stringify({ memories, overwrite: opts.overwrite ?? true })
|
|
3506
|
+
});
|
|
3507
|
+
return {
|
|
3508
|
+
pushed: result.imported,
|
|
3509
|
+
errors: [...errors2, ...result.errors],
|
|
3510
|
+
remote_url: baseUrl
|
|
3511
|
+
};
|
|
3512
|
+
}
|
|
3513
|
+
async function pullFromRemote(opts = {}) {
|
|
3514
|
+
const baseUrl = resolveUrl(opts.remoteUrl);
|
|
3515
|
+
const errors2 = [];
|
|
3516
|
+
const filter = { limit: opts.limit ?? 1e4 };
|
|
3517
|
+
if (opts.scope)
|
|
3518
|
+
filter.scope = opts.scope;
|
|
3519
|
+
if (opts.agentId)
|
|
3520
|
+
filter.agent_id = opts.agentId;
|
|
3521
|
+
if (opts.projectId)
|
|
3522
|
+
filter.project_id = opts.projectId;
|
|
3523
|
+
const result = await fetchJson(`${baseUrl}/api/memories/export`, { method: "POST", body: JSON.stringify(filter) });
|
|
3524
|
+
let pulled = 0;
|
|
3525
|
+
for (const mem of result.memories) {
|
|
3526
|
+
try {
|
|
3527
|
+
createMemory(mem, opts.overwrite !== false ? "merge" : "create");
|
|
3528
|
+
pulled++;
|
|
3529
|
+
} catch (e) {
|
|
3530
|
+
errors2.push(`Failed to import "${mem.key}": ${e instanceof Error ? e.message : String(e)}`);
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
return { pulled, errors: errors2, remote_url: baseUrl };
|
|
3534
|
+
}
|
|
3535
|
+
async function syncWithRemote(opts = {}) {
|
|
3536
|
+
const baseUrl = resolveUrl(opts.remoteUrl);
|
|
3537
|
+
const pushResult = await pushToRemote({ ...opts, remoteUrl: baseUrl });
|
|
3538
|
+
const pullResult = await pullFromRemote({ ...opts, remoteUrl: baseUrl, overwrite: false });
|
|
3539
|
+
return {
|
|
3540
|
+
pushed: pushResult.pushed,
|
|
3541
|
+
pulled: pullResult.pulled,
|
|
3542
|
+
errors: [...pushResult.errors, ...pullResult.errors],
|
|
3543
|
+
remote_url: baseUrl
|
|
3544
|
+
};
|
|
3545
|
+
}
|
|
3546
|
+
async function pingRemote(url) {
|
|
3547
|
+
const baseUrl = resolveUrl(url);
|
|
3548
|
+
try {
|
|
3549
|
+
const res = await fetch(`${baseUrl}/api/health`, {
|
|
3550
|
+
signal: AbortSignal.timeout(5000)
|
|
3551
|
+
});
|
|
3552
|
+
return { ok: res.ok, url: baseUrl, status: res.status };
|
|
3553
|
+
} catch (e) {
|
|
3554
|
+
return { ok: false, url: baseUrl, error: e instanceof Error ? e.message : String(e) };
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
var DEFAULT_PORT = 19428;
|
|
3558
|
+
var init_remote_sync = __esm(() => {
|
|
3559
|
+
init_memories();
|
|
3560
|
+
});
|
|
3561
|
+
|
|
3464
3562
|
// src/mcp/index.ts
|
|
3465
3563
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3466
3564
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -9733,6 +9831,48 @@ ${lines.join(`
|
|
|
9733
9831
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9734
9832
|
}
|
|
9735
9833
|
});
|
|
9834
|
+
server.tool("memory_sync_push", "Push local memories to a remote mementos-serve instance. Set MEMENTOS_REMOTE_URL or pass url.", {
|
|
9835
|
+
url: exports_external.string().optional().describe("Remote URL (e.g. http://apple01:19428). Defaults to MEMENTOS_REMOTE_URL env var."),
|
|
9836
|
+
scope: exports_external.enum(["global", "shared", "private"]).optional(),
|
|
9837
|
+
agent_id: exports_external.string().optional(),
|
|
9838
|
+
project_id: exports_external.string().optional(),
|
|
9839
|
+
limit: exports_external.coerce.number().optional()
|
|
9840
|
+
}, async (args) => {
|
|
9841
|
+
try {
|
|
9842
|
+
const { pushToRemote: pushToRemote2 } = await Promise.resolve().then(() => (init_remote_sync(), exports_remote_sync));
|
|
9843
|
+
const result = await pushToRemote2({ remoteUrl: args.url, scope: args.scope, agentId: args.agent_id, projectId: args.project_id, limit: args.limit });
|
|
9844
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
9845
|
+
} catch (e) {
|
|
9846
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9847
|
+
}
|
|
9848
|
+
});
|
|
9849
|
+
server.tool("memory_sync_pull", "Pull memories from a remote mementos-serve instance into local DB. Set MEMENTOS_REMOTE_URL or pass url.", {
|
|
9850
|
+
url: exports_external.string().optional().describe("Remote URL. Defaults to MEMENTOS_REMOTE_URL env var."),
|
|
9851
|
+
scope: exports_external.enum(["global", "shared", "private"]).optional(),
|
|
9852
|
+
agent_id: exports_external.string().optional(),
|
|
9853
|
+
project_id: exports_external.string().optional(),
|
|
9854
|
+
limit: exports_external.coerce.number().optional(),
|
|
9855
|
+
overwrite: exports_external.coerce.boolean().optional().describe("Overwrite existing memories with same key (default: false = keep newer)")
|
|
9856
|
+
}, async (args) => {
|
|
9857
|
+
try {
|
|
9858
|
+
const { pullFromRemote: pullFromRemote2 } = await Promise.resolve().then(() => (init_remote_sync(), exports_remote_sync));
|
|
9859
|
+
const result = await pullFromRemote2({ remoteUrl: args.url, scope: args.scope, agentId: args.agent_id, projectId: args.project_id, limit: args.limit, overwrite: args.overwrite });
|
|
9860
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
9861
|
+
} catch (e) {
|
|
9862
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9863
|
+
}
|
|
9864
|
+
});
|
|
9865
|
+
server.tool("memory_sync_status", "Check if a remote mementos-serve is reachable. Set MEMENTOS_REMOTE_URL or pass url.", {
|
|
9866
|
+
url: exports_external.string().optional().describe("Remote URL. Defaults to MEMENTOS_REMOTE_URL env var.")
|
|
9867
|
+
}, async (args) => {
|
|
9868
|
+
try {
|
|
9869
|
+
const { pingRemote: pingRemote2 } = await Promise.resolve().then(() => (init_remote_sync(), exports_remote_sync));
|
|
9870
|
+
const result = await pingRemote2(args.url);
|
|
9871
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
9872
|
+
} catch (e) {
|
|
9873
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9874
|
+
}
|
|
9875
|
+
});
|
|
9736
9876
|
server.tool("memory_stats", "Get aggregate statistics about stored memories", {}, async () => {
|
|
9737
9877
|
try {
|
|
9738
9878
|
const db = getDatabase();
|
|
@@ -10464,6 +10604,9 @@ server.tool("memory_context", "Get memories relevant to current context, filtere
|
|
|
10464
10604
|
if (memories.length === 0) {
|
|
10465
10605
|
return { content: [{ type: "text", text: "No memories in current context." }] };
|
|
10466
10606
|
}
|
|
10607
|
+
for (const m of memories) {
|
|
10608
|
+
touchMemory(m.id);
|
|
10609
|
+
}
|
|
10467
10610
|
const lines = memories.map((m) => `[${m.scope}/${m.category}] ${m.key}: ${m.value} (importance: ${m.importance})`);
|
|
10468
10611
|
return { content: [{ type: "text", text: lines.join(`
|
|
10469
10612
|
`) }] };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAihDH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkI9C"}
|
package/dist/server/index.js
CHANGED
|
@@ -5296,6 +5296,9 @@ function matchRoute(method, pathname) {
|
|
|
5296
5296
|
}
|
|
5297
5297
|
return null;
|
|
5298
5298
|
}
|
|
5299
|
+
addRoute("GET", "/api/health", () => {
|
|
5300
|
+
return json({ ok: true, version: "1", db: getDbPath2() });
|
|
5301
|
+
});
|
|
5299
5302
|
addRoute("GET", "/api/memories", (_req, url) => {
|
|
5300
5303
|
const q = getSearchParams(url);
|
|
5301
5304
|
const filter = {};
|