@prmichaelsen/remember-mcp 3.14.7 → 3.14.9
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/.env.cross-migrate.example +9 -0
- package/dist/server-factory.js +100 -19
- package/dist/server.js +100 -19
- package/package.json +2 -2
- package/scripts/migrate-cross-instance-v1-to-v2.ts +992 -0
package/dist/server-factory.js
CHANGED
|
@@ -1619,16 +1619,16 @@ var DebugLevel2;
|
|
|
1619
1619
|
DebugLevel3[DebugLevel3["TRACE"] = 5] = "TRACE";
|
|
1620
1620
|
})(DebugLevel2 || (DebugLevel2 = {}));
|
|
1621
1621
|
|
|
1622
|
-
// node_modules/uuid/dist
|
|
1622
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/regex.js
|
|
1623
1623
|
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
1624
1624
|
|
|
1625
|
-
// node_modules/uuid/dist
|
|
1625
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/validate.js
|
|
1626
1626
|
function validate(uuid) {
|
|
1627
1627
|
return typeof uuid === "string" && regex_default.test(uuid);
|
|
1628
1628
|
}
|
|
1629
1629
|
var validate_default = validate;
|
|
1630
1630
|
|
|
1631
|
-
// node_modules/uuid/dist
|
|
1631
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/parse.js
|
|
1632
1632
|
function parse(uuid) {
|
|
1633
1633
|
if (!validate_default(uuid)) {
|
|
1634
1634
|
throw TypeError("Invalid UUID");
|
|
@@ -1638,7 +1638,7 @@ function parse(uuid) {
|
|
|
1638
1638
|
}
|
|
1639
1639
|
var parse_default = parse;
|
|
1640
1640
|
|
|
1641
|
-
// node_modules/uuid/dist
|
|
1641
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/stringify.js
|
|
1642
1642
|
var byteToHex = [];
|
|
1643
1643
|
for (let i = 0; i < 256; ++i) {
|
|
1644
1644
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
@@ -1647,7 +1647,7 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
1647
1647
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
1648
1648
|
}
|
|
1649
1649
|
|
|
1650
|
-
// node_modules/uuid/dist
|
|
1650
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/v35.js
|
|
1651
1651
|
function stringToBytes(str) {
|
|
1652
1652
|
str = unescape(encodeURIComponent(str));
|
|
1653
1653
|
const bytes = new Uint8Array(str.length);
|
|
@@ -1683,8 +1683,8 @@ function v35(version, hash, value, namespace, buf, offset) {
|
|
|
1683
1683
|
return unsafeStringify(bytes);
|
|
1684
1684
|
}
|
|
1685
1685
|
|
|
1686
|
-
// node_modules/uuid/dist
|
|
1687
|
-
import { createHash } from "
|
|
1686
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/sha1.js
|
|
1687
|
+
import { createHash } from "crypto";
|
|
1688
1688
|
function sha1(bytes) {
|
|
1689
1689
|
if (Array.isArray(bytes)) {
|
|
1690
1690
|
bytes = Buffer.from(bytes);
|
|
@@ -1695,7 +1695,7 @@ function sha1(bytes) {
|
|
|
1695
1695
|
}
|
|
1696
1696
|
var sha1_default = sha1;
|
|
1697
1697
|
|
|
1698
|
-
// node_modules/uuid/dist
|
|
1698
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/v5.js
|
|
1699
1699
|
function v5(value, namespace, buf, offset) {
|
|
1700
1700
|
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
1701
1701
|
}
|
|
@@ -1860,22 +1860,22 @@ function buildDocTypeFilters(collection, docType, filters) {
|
|
|
1860
1860
|
}
|
|
1861
1861
|
}
|
|
1862
1862
|
if (filters?.weight_min !== void 0) {
|
|
1863
|
-
filterList.push(collection.filter.byProperty("weight").
|
|
1863
|
+
filterList.push(collection.filter.byProperty("weight").greaterOrEqual(filters.weight_min));
|
|
1864
1864
|
}
|
|
1865
1865
|
if (filters?.weight_max !== void 0) {
|
|
1866
|
-
filterList.push(collection.filter.byProperty("weight").
|
|
1866
|
+
filterList.push(collection.filter.byProperty("weight").lessOrEqual(filters.weight_max));
|
|
1867
1867
|
}
|
|
1868
1868
|
if (filters?.trust_min !== void 0) {
|
|
1869
|
-
filterList.push(collection.filter.byProperty("trust_score").
|
|
1869
|
+
filterList.push(collection.filter.byProperty("trust_score").greaterOrEqual(filters.trust_min));
|
|
1870
1870
|
}
|
|
1871
1871
|
if (filters?.trust_max !== void 0) {
|
|
1872
|
-
filterList.push(collection.filter.byProperty("trust_score").
|
|
1872
|
+
filterList.push(collection.filter.byProperty("trust_score").lessOrEqual(filters.trust_max));
|
|
1873
1873
|
}
|
|
1874
1874
|
if (filters?.date_from) {
|
|
1875
|
-
filterList.push(collection.filter.byProperty("created_at").
|
|
1875
|
+
filterList.push(collection.filter.byProperty("created_at").greaterOrEqual(new Date(filters.date_from)));
|
|
1876
1876
|
}
|
|
1877
1877
|
if (filters?.date_to) {
|
|
1878
|
-
filterList.push(collection.filter.byProperty("created_at").
|
|
1878
|
+
filterList.push(collection.filter.byProperty("created_at").lessOrEqual(new Date(filters.date_to)));
|
|
1879
1879
|
}
|
|
1880
1880
|
if (filters?.tags && filters.tags.length > 0) {
|
|
1881
1881
|
filterList.push(collection.filter.byProperty("tags").containsAny(filters.tags));
|
|
@@ -2236,6 +2236,7 @@ var ALL_MEMORY_PROPERTIES = [
|
|
|
2236
2236
|
"related_memory_ids",
|
|
2237
2237
|
"relationships",
|
|
2238
2238
|
"memory_ids",
|
|
2239
|
+
"relationship_count",
|
|
2239
2240
|
"relationship_type",
|
|
2240
2241
|
"observation",
|
|
2241
2242
|
"strength",
|
|
@@ -2281,7 +2282,7 @@ async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
|
2281
2282
|
|
|
2282
2283
|
// node_modules/@prmichaelsen/remember-core/dist/services/trust-enforcement.service.js
|
|
2283
2284
|
function buildTrustFilter(collection, accessorTrustLevel) {
|
|
2284
|
-
return collection.filter.byProperty("trust_score").
|
|
2285
|
+
return collection.filter.byProperty("trust_score").lessOrEqual(accessorTrustLevel);
|
|
2285
2286
|
}
|
|
2286
2287
|
|
|
2287
2288
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
@@ -2334,6 +2335,7 @@ var MemoryService = class {
|
|
|
2334
2335
|
context_summary: input.context_summary || "Memory created",
|
|
2335
2336
|
context_conversation_id: input.context_conversation_id,
|
|
2336
2337
|
relationship_ids: [],
|
|
2338
|
+
relationship_count: 0,
|
|
2337
2339
|
access_count: 0,
|
|
2338
2340
|
last_accessed_at: now,
|
|
2339
2341
|
created_at: now,
|
|
@@ -2403,6 +2405,52 @@ var MemoryService = class {
|
|
|
2403
2405
|
limit
|
|
2404
2406
|
};
|
|
2405
2407
|
}
|
|
2408
|
+
// ── By Time (chronological sort) ───────────────────────────────────
|
|
2409
|
+
async byTime(input) {
|
|
2410
|
+
const limit = input.limit ?? 50;
|
|
2411
|
+
const offset = input.offset ?? 0;
|
|
2412
|
+
const direction = input.direction ?? "desc";
|
|
2413
|
+
const memoryFilters = buildMemoryOnlyFilters(this.collection, input.filters);
|
|
2414
|
+
const ghostFilters = [];
|
|
2415
|
+
if (input.ghost_context) {
|
|
2416
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2417
|
+
}
|
|
2418
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2419
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2420
|
+
}
|
|
2421
|
+
const executeQuery = async (useDeletedFilter) => {
|
|
2422
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2423
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, memoryFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2424
|
+
const queryOptions = {
|
|
2425
|
+
limit: limit + offset,
|
|
2426
|
+
sort: [
|
|
2427
|
+
{
|
|
2428
|
+
property: "created_at",
|
|
2429
|
+
order: direction
|
|
2430
|
+
}
|
|
2431
|
+
]
|
|
2432
|
+
};
|
|
2433
|
+
if (combinedFilters) {
|
|
2434
|
+
queryOptions.filters = combinedFilters;
|
|
2435
|
+
}
|
|
2436
|
+
return this.collection.query.fetchObjects(queryOptions);
|
|
2437
|
+
};
|
|
2438
|
+
const results = await this.retryWithoutDeletedFilter(executeQuery);
|
|
2439
|
+
const paginated = results.objects.slice(offset);
|
|
2440
|
+
const memories = [];
|
|
2441
|
+
for (const obj of paginated) {
|
|
2442
|
+
const doc = { id: obj.uuid, ...obj.properties };
|
|
2443
|
+
if (doc.doc_type === "memory") {
|
|
2444
|
+
memories.push(doc);
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
return {
|
|
2448
|
+
memories,
|
|
2449
|
+
total: memories.length,
|
|
2450
|
+
offset,
|
|
2451
|
+
limit
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2406
2454
|
// ── Find Similar (vector) ──────────────────────────────────────────
|
|
2407
2455
|
async findSimilar(input) {
|
|
2408
2456
|
if (!input.memory_id && !input.text)
|
|
@@ -2619,6 +2667,33 @@ var RelationshipService = class {
|
|
|
2619
2667
|
this.userId = userId;
|
|
2620
2668
|
this.logger = logger2;
|
|
2621
2669
|
}
|
|
2670
|
+
// ── Helper Methods ──────────────────────────────────────────────────
|
|
2671
|
+
/**
|
|
2672
|
+
* Update relationship_count for a memory by a delta (+1 or -1).
|
|
2673
|
+
* Ensures count never goes negative.
|
|
2674
|
+
*/
|
|
2675
|
+
async updateRelationshipCount(memoryId, delta) {
|
|
2676
|
+
try {
|
|
2677
|
+
const memory = await this.collection.query.fetchObjectById(memoryId, {
|
|
2678
|
+
returnProperties: ["relationship_count"]
|
|
2679
|
+
});
|
|
2680
|
+
if (!memory) {
|
|
2681
|
+
this.logger.warn(`Memory ${memoryId} not found, skipping relationship_count update`);
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
const currentCount = memory.properties.relationship_count || 0;
|
|
2685
|
+
const newCount = Math.max(0, currentCount + delta);
|
|
2686
|
+
await this.collection.data.update({
|
|
2687
|
+
id: memoryId,
|
|
2688
|
+
properties: {
|
|
2689
|
+
relationship_count: newCount
|
|
2690
|
+
}
|
|
2691
|
+
});
|
|
2692
|
+
this.logger.debug(`Updated relationship_count for ${memoryId}: ${currentCount} -> ${newCount}`);
|
|
2693
|
+
} catch (error) {
|
|
2694
|
+
this.logger.error(`Failed to update relationship_count for ${memoryId}:`, { error: error?.message || String(error) });
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2622
2697
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2623
2698
|
async create(input) {
|
|
2624
2699
|
if (input.memory_ids.length < 2) {
|
|
@@ -2658,6 +2733,7 @@ var RelationshipService = class {
|
|
|
2658
2733
|
tags: input.tags || []
|
|
2659
2734
|
};
|
|
2660
2735
|
const relationshipId = await this.collection.data.insert({ properties });
|
|
2736
|
+
await Promise.all(input.memory_ids.map((memoryId) => this.updateRelationshipCount(memoryId, 1)));
|
|
2661
2737
|
await Promise.all(checks.filter((c) => !c.error && c.memory).map(async (c) => {
|
|
2662
2738
|
try {
|
|
2663
2739
|
await this.collection.data.update({
|
|
@@ -2814,6 +2890,7 @@ var RelationshipService = class {
|
|
|
2814
2890
|
throw new Error("Not a relationship document");
|
|
2815
2891
|
const memoryIds = existing.properties.related_memory_ids || [];
|
|
2816
2892
|
let memoriesUpdated = 0;
|
|
2893
|
+
await Promise.all(memoryIds.map((memoryId) => this.updateRelationshipCount(memoryId, -1)));
|
|
2817
2894
|
await Promise.all(memoryIds.map(async (memoryId) => {
|
|
2818
2895
|
try {
|
|
2819
2896
|
const memory = await this.collection.query.fetchObjectById(memoryId, {
|
|
@@ -2911,6 +2988,7 @@ var COMMON_MEMORY_PROPERTIES = [
|
|
|
2911
2988
|
// Relationships (v1 compat)
|
|
2912
2989
|
{ name: "relationships", dataType: configure.dataType.TEXT_ARRAY },
|
|
2913
2990
|
{ name: "memory_ids", dataType: configure.dataType.TEXT_ARRAY },
|
|
2991
|
+
{ name: "relationship_count", dataType: configure.dataType.INT },
|
|
2914
2992
|
// Access tracking
|
|
2915
2993
|
{ name: "access_count", dataType: configure.dataType.NUMBER },
|
|
2916
2994
|
{ name: "last_accessed_at", dataType: configure.dataType.DATE },
|
|
@@ -3745,6 +3823,9 @@ var SpaceService = class {
|
|
|
3745
3823
|
// node_modules/@prmichaelsen/remember-core/dist/services/rem.state.js
|
|
3746
3824
|
var REM_STATE_COLLECTION = `${BASE}.rem_state`;
|
|
3747
3825
|
|
|
3826
|
+
// node_modules/@prmichaelsen/remember-core/dist/services/rem.clustering.js
|
|
3827
|
+
import { Filters as Filters5 } from "weaviate-client";
|
|
3828
|
+
|
|
3748
3829
|
// src/weaviate/schema.ts
|
|
3749
3830
|
init_logger();
|
|
3750
3831
|
|
|
@@ -4002,7 +4083,7 @@ async function handleCreateMemory(args, userId, authContext, context) {
|
|
|
4002
4083
|
init_logger();
|
|
4003
4084
|
|
|
4004
4085
|
// src/utils/weaviate-filters.ts
|
|
4005
|
-
import { Filters as
|
|
4086
|
+
import { Filters as Filters6 } from "weaviate-client";
|
|
4006
4087
|
function buildCombinedSearchFilters2(collection, filters) {
|
|
4007
4088
|
const memoryFilters = buildDocTypeFilters2(collection, "memory", filters);
|
|
4008
4089
|
const relationshipFilters = buildDocTypeFilters2(collection, "relationship", filters);
|
|
@@ -4085,7 +4166,7 @@ function combineFiltersWithAnd2(filters) {
|
|
|
4085
4166
|
if (validFilters.length === 1) {
|
|
4086
4167
|
return validFilters[0];
|
|
4087
4168
|
}
|
|
4088
|
-
return
|
|
4169
|
+
return Filters6.and(...validFilters);
|
|
4089
4170
|
}
|
|
4090
4171
|
function combineFiltersWithOr2(filters) {
|
|
4091
4172
|
const validFilters = filters.filter((f) => f !== void 0 && f !== null);
|
|
@@ -4095,7 +4176,7 @@ function combineFiltersWithOr2(filters) {
|
|
|
4095
4176
|
if (validFilters.length === 1) {
|
|
4096
4177
|
return validFilters[0];
|
|
4097
4178
|
}
|
|
4098
|
-
return
|
|
4179
|
+
return Filters6.or(...validFilters);
|
|
4099
4180
|
}
|
|
4100
4181
|
function buildDeletedFilter2(collection, deletedFilter = "exclude") {
|
|
4101
4182
|
if (deletedFilter === "exclude") {
|
|
@@ -5823,7 +5904,7 @@ async function handleDeny(args, userId, authContext) {
|
|
|
5823
5904
|
}
|
|
5824
5905
|
|
|
5825
5906
|
// src/tools/search-space.ts
|
|
5826
|
-
import { Filters as
|
|
5907
|
+
import { Filters as Filters7 } from "weaviate-client";
|
|
5827
5908
|
var searchSpaceTool = {
|
|
5828
5909
|
name: "remember_search_space",
|
|
5829
5910
|
description: `Search shared spaces and/or groups to discover memories from other users.
|
package/dist/server.js
CHANGED
|
@@ -1303,16 +1303,16 @@ var DebugLevel2;
|
|
|
1303
1303
|
DebugLevel3[DebugLevel3["TRACE"] = 5] = "TRACE";
|
|
1304
1304
|
})(DebugLevel2 || (DebugLevel2 = {}));
|
|
1305
1305
|
|
|
1306
|
-
// node_modules/uuid/dist
|
|
1306
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/regex.js
|
|
1307
1307
|
var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
1308
1308
|
|
|
1309
|
-
// node_modules/uuid/dist
|
|
1309
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/validate.js
|
|
1310
1310
|
function validate(uuid) {
|
|
1311
1311
|
return typeof uuid === "string" && regex_default.test(uuid);
|
|
1312
1312
|
}
|
|
1313
1313
|
var validate_default = validate;
|
|
1314
1314
|
|
|
1315
|
-
// node_modules/uuid/dist
|
|
1315
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/parse.js
|
|
1316
1316
|
function parse(uuid) {
|
|
1317
1317
|
if (!validate_default(uuid)) {
|
|
1318
1318
|
throw TypeError("Invalid UUID");
|
|
@@ -1322,7 +1322,7 @@ function parse(uuid) {
|
|
|
1322
1322
|
}
|
|
1323
1323
|
var parse_default = parse;
|
|
1324
1324
|
|
|
1325
|
-
// node_modules/uuid/dist
|
|
1325
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/stringify.js
|
|
1326
1326
|
var byteToHex = [];
|
|
1327
1327
|
for (let i = 0; i < 256; ++i) {
|
|
1328
1328
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
@@ -1331,7 +1331,7 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
1331
1331
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
|
-
// node_modules/uuid/dist
|
|
1334
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/v35.js
|
|
1335
1335
|
function stringToBytes(str) {
|
|
1336
1336
|
str = unescape(encodeURIComponent(str));
|
|
1337
1337
|
const bytes = new Uint8Array(str.length);
|
|
@@ -1367,8 +1367,8 @@ function v35(version, hash, value, namespace, buf, offset) {
|
|
|
1367
1367
|
return unsafeStringify(bytes);
|
|
1368
1368
|
}
|
|
1369
1369
|
|
|
1370
|
-
// node_modules/uuid/dist
|
|
1371
|
-
import { createHash } from "
|
|
1370
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/sha1.js
|
|
1371
|
+
import { createHash } from "crypto";
|
|
1372
1372
|
function sha1(bytes) {
|
|
1373
1373
|
if (Array.isArray(bytes)) {
|
|
1374
1374
|
bytes = Buffer.from(bytes);
|
|
@@ -1379,7 +1379,7 @@ function sha1(bytes) {
|
|
|
1379
1379
|
}
|
|
1380
1380
|
var sha1_default = sha1;
|
|
1381
1381
|
|
|
1382
|
-
// node_modules/uuid/dist
|
|
1382
|
+
// node_modules/@prmichaelsen/remember-core/node_modules/uuid/dist/esm/v5.js
|
|
1383
1383
|
function v5(value, namespace, buf, offset) {
|
|
1384
1384
|
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
1385
1385
|
}
|
|
@@ -1544,22 +1544,22 @@ function buildDocTypeFilters(collection, docType, filters) {
|
|
|
1544
1544
|
}
|
|
1545
1545
|
}
|
|
1546
1546
|
if (filters?.weight_min !== void 0) {
|
|
1547
|
-
filterList.push(collection.filter.byProperty("weight").
|
|
1547
|
+
filterList.push(collection.filter.byProperty("weight").greaterOrEqual(filters.weight_min));
|
|
1548
1548
|
}
|
|
1549
1549
|
if (filters?.weight_max !== void 0) {
|
|
1550
|
-
filterList.push(collection.filter.byProperty("weight").
|
|
1550
|
+
filterList.push(collection.filter.byProperty("weight").lessOrEqual(filters.weight_max));
|
|
1551
1551
|
}
|
|
1552
1552
|
if (filters?.trust_min !== void 0) {
|
|
1553
|
-
filterList.push(collection.filter.byProperty("trust_score").
|
|
1553
|
+
filterList.push(collection.filter.byProperty("trust_score").greaterOrEqual(filters.trust_min));
|
|
1554
1554
|
}
|
|
1555
1555
|
if (filters?.trust_max !== void 0) {
|
|
1556
|
-
filterList.push(collection.filter.byProperty("trust_score").
|
|
1556
|
+
filterList.push(collection.filter.byProperty("trust_score").lessOrEqual(filters.trust_max));
|
|
1557
1557
|
}
|
|
1558
1558
|
if (filters?.date_from) {
|
|
1559
|
-
filterList.push(collection.filter.byProperty("created_at").
|
|
1559
|
+
filterList.push(collection.filter.byProperty("created_at").greaterOrEqual(new Date(filters.date_from)));
|
|
1560
1560
|
}
|
|
1561
1561
|
if (filters?.date_to) {
|
|
1562
|
-
filterList.push(collection.filter.byProperty("created_at").
|
|
1562
|
+
filterList.push(collection.filter.byProperty("created_at").lessOrEqual(new Date(filters.date_to)));
|
|
1563
1563
|
}
|
|
1564
1564
|
if (filters?.tags && filters.tags.length > 0) {
|
|
1565
1565
|
filterList.push(collection.filter.byProperty("tags").containsAny(filters.tags));
|
|
@@ -1920,6 +1920,7 @@ var ALL_MEMORY_PROPERTIES = [
|
|
|
1920
1920
|
"related_memory_ids",
|
|
1921
1921
|
"relationships",
|
|
1922
1922
|
"memory_ids",
|
|
1923
|
+
"relationship_count",
|
|
1923
1924
|
"relationship_type",
|
|
1924
1925
|
"observation",
|
|
1925
1926
|
"strength",
|
|
@@ -1965,7 +1966,7 @@ async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
|
1965
1966
|
|
|
1966
1967
|
// node_modules/@prmichaelsen/remember-core/dist/services/trust-enforcement.service.js
|
|
1967
1968
|
function buildTrustFilter(collection, accessorTrustLevel) {
|
|
1968
|
-
return collection.filter.byProperty("trust_score").
|
|
1969
|
+
return collection.filter.byProperty("trust_score").lessOrEqual(accessorTrustLevel);
|
|
1969
1970
|
}
|
|
1970
1971
|
|
|
1971
1972
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
@@ -2018,6 +2019,7 @@ var MemoryService = class {
|
|
|
2018
2019
|
context_summary: input.context_summary || "Memory created",
|
|
2019
2020
|
context_conversation_id: input.context_conversation_id,
|
|
2020
2021
|
relationship_ids: [],
|
|
2022
|
+
relationship_count: 0,
|
|
2021
2023
|
access_count: 0,
|
|
2022
2024
|
last_accessed_at: now,
|
|
2023
2025
|
created_at: now,
|
|
@@ -2087,6 +2089,52 @@ var MemoryService = class {
|
|
|
2087
2089
|
limit
|
|
2088
2090
|
};
|
|
2089
2091
|
}
|
|
2092
|
+
// ── By Time (chronological sort) ───────────────────────────────────
|
|
2093
|
+
async byTime(input) {
|
|
2094
|
+
const limit = input.limit ?? 50;
|
|
2095
|
+
const offset = input.offset ?? 0;
|
|
2096
|
+
const direction = input.direction ?? "desc";
|
|
2097
|
+
const memoryFilters = buildMemoryOnlyFilters(this.collection, input.filters);
|
|
2098
|
+
const ghostFilters = [];
|
|
2099
|
+
if (input.ghost_context) {
|
|
2100
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2101
|
+
}
|
|
2102
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2103
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2104
|
+
}
|
|
2105
|
+
const executeQuery = async (useDeletedFilter) => {
|
|
2106
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2107
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, memoryFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2108
|
+
const queryOptions = {
|
|
2109
|
+
limit: limit + offset,
|
|
2110
|
+
sort: [
|
|
2111
|
+
{
|
|
2112
|
+
property: "created_at",
|
|
2113
|
+
order: direction
|
|
2114
|
+
}
|
|
2115
|
+
]
|
|
2116
|
+
};
|
|
2117
|
+
if (combinedFilters) {
|
|
2118
|
+
queryOptions.filters = combinedFilters;
|
|
2119
|
+
}
|
|
2120
|
+
return this.collection.query.fetchObjects(queryOptions);
|
|
2121
|
+
};
|
|
2122
|
+
const results = await this.retryWithoutDeletedFilter(executeQuery);
|
|
2123
|
+
const paginated = results.objects.slice(offset);
|
|
2124
|
+
const memories = [];
|
|
2125
|
+
for (const obj of paginated) {
|
|
2126
|
+
const doc = { id: obj.uuid, ...obj.properties };
|
|
2127
|
+
if (doc.doc_type === "memory") {
|
|
2128
|
+
memories.push(doc);
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
return {
|
|
2132
|
+
memories,
|
|
2133
|
+
total: memories.length,
|
|
2134
|
+
offset,
|
|
2135
|
+
limit
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2090
2138
|
// ── Find Similar (vector) ──────────────────────────────────────────
|
|
2091
2139
|
async findSimilar(input) {
|
|
2092
2140
|
if (!input.memory_id && !input.text)
|
|
@@ -2303,6 +2351,33 @@ var RelationshipService = class {
|
|
|
2303
2351
|
this.userId = userId;
|
|
2304
2352
|
this.logger = logger2;
|
|
2305
2353
|
}
|
|
2354
|
+
// ── Helper Methods ──────────────────────────────────────────────────
|
|
2355
|
+
/**
|
|
2356
|
+
* Update relationship_count for a memory by a delta (+1 or -1).
|
|
2357
|
+
* Ensures count never goes negative.
|
|
2358
|
+
*/
|
|
2359
|
+
async updateRelationshipCount(memoryId, delta) {
|
|
2360
|
+
try {
|
|
2361
|
+
const memory = await this.collection.query.fetchObjectById(memoryId, {
|
|
2362
|
+
returnProperties: ["relationship_count"]
|
|
2363
|
+
});
|
|
2364
|
+
if (!memory) {
|
|
2365
|
+
this.logger.warn(`Memory ${memoryId} not found, skipping relationship_count update`);
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2368
|
+
const currentCount = memory.properties.relationship_count || 0;
|
|
2369
|
+
const newCount = Math.max(0, currentCount + delta);
|
|
2370
|
+
await this.collection.data.update({
|
|
2371
|
+
id: memoryId,
|
|
2372
|
+
properties: {
|
|
2373
|
+
relationship_count: newCount
|
|
2374
|
+
}
|
|
2375
|
+
});
|
|
2376
|
+
this.logger.debug(`Updated relationship_count for ${memoryId}: ${currentCount} -> ${newCount}`);
|
|
2377
|
+
} catch (error) {
|
|
2378
|
+
this.logger.error(`Failed to update relationship_count for ${memoryId}:`, { error: error?.message || String(error) });
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2306
2381
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2307
2382
|
async create(input) {
|
|
2308
2383
|
if (input.memory_ids.length < 2) {
|
|
@@ -2342,6 +2417,7 @@ var RelationshipService = class {
|
|
|
2342
2417
|
tags: input.tags || []
|
|
2343
2418
|
};
|
|
2344
2419
|
const relationshipId = await this.collection.data.insert({ properties });
|
|
2420
|
+
await Promise.all(input.memory_ids.map((memoryId) => this.updateRelationshipCount(memoryId, 1)));
|
|
2345
2421
|
await Promise.all(checks.filter((c) => !c.error && c.memory).map(async (c) => {
|
|
2346
2422
|
try {
|
|
2347
2423
|
await this.collection.data.update({
|
|
@@ -2498,6 +2574,7 @@ var RelationshipService = class {
|
|
|
2498
2574
|
throw new Error("Not a relationship document");
|
|
2499
2575
|
const memoryIds = existing.properties.related_memory_ids || [];
|
|
2500
2576
|
let memoriesUpdated = 0;
|
|
2577
|
+
await Promise.all(memoryIds.map((memoryId) => this.updateRelationshipCount(memoryId, -1)));
|
|
2501
2578
|
await Promise.all(memoryIds.map(async (memoryId) => {
|
|
2502
2579
|
try {
|
|
2503
2580
|
const memory = await this.collection.query.fetchObjectById(memoryId, {
|
|
@@ -2595,6 +2672,7 @@ var COMMON_MEMORY_PROPERTIES = [
|
|
|
2595
2672
|
// Relationships (v1 compat)
|
|
2596
2673
|
{ name: "relationships", dataType: configure.dataType.TEXT_ARRAY },
|
|
2597
2674
|
{ name: "memory_ids", dataType: configure.dataType.TEXT_ARRAY },
|
|
2675
|
+
{ name: "relationship_count", dataType: configure.dataType.INT },
|
|
2598
2676
|
// Access tracking
|
|
2599
2677
|
{ name: "access_count", dataType: configure.dataType.NUMBER },
|
|
2600
2678
|
{ name: "last_accessed_at", dataType: configure.dataType.DATE },
|
|
@@ -3429,6 +3507,9 @@ var SpaceService = class {
|
|
|
3429
3507
|
// node_modules/@prmichaelsen/remember-core/dist/services/rem.state.js
|
|
3430
3508
|
var REM_STATE_COLLECTION = `${BASE}.rem_state`;
|
|
3431
3509
|
|
|
3510
|
+
// node_modules/@prmichaelsen/remember-core/dist/services/rem.clustering.js
|
|
3511
|
+
import { Filters as Filters5 } from "weaviate-client";
|
|
3512
|
+
|
|
3432
3513
|
// src/weaviate/schema.ts
|
|
3433
3514
|
init_logger();
|
|
3434
3515
|
|
|
@@ -3686,7 +3767,7 @@ async function handleCreateMemory(args, userId, authContext, context) {
|
|
|
3686
3767
|
init_logger();
|
|
3687
3768
|
|
|
3688
3769
|
// src/utils/weaviate-filters.ts
|
|
3689
|
-
import { Filters as
|
|
3770
|
+
import { Filters as Filters6 } from "weaviate-client";
|
|
3690
3771
|
function buildCombinedSearchFilters2(collection, filters) {
|
|
3691
3772
|
const memoryFilters = buildDocTypeFilters2(collection, "memory", filters);
|
|
3692
3773
|
const relationshipFilters = buildDocTypeFilters2(collection, "relationship", filters);
|
|
@@ -3769,7 +3850,7 @@ function combineFiltersWithAnd2(filters) {
|
|
|
3769
3850
|
if (validFilters.length === 1) {
|
|
3770
3851
|
return validFilters[0];
|
|
3771
3852
|
}
|
|
3772
|
-
return
|
|
3853
|
+
return Filters6.and(...validFilters);
|
|
3773
3854
|
}
|
|
3774
3855
|
function combineFiltersWithOr2(filters) {
|
|
3775
3856
|
const validFilters = filters.filter((f) => f !== void 0 && f !== null);
|
|
@@ -3779,7 +3860,7 @@ function combineFiltersWithOr2(filters) {
|
|
|
3779
3860
|
if (validFilters.length === 1) {
|
|
3780
3861
|
return validFilters[0];
|
|
3781
3862
|
}
|
|
3782
|
-
return
|
|
3863
|
+
return Filters6.or(...validFilters);
|
|
3783
3864
|
}
|
|
3784
3865
|
function buildDeletedFilter2(collection, deletedFilter = "exclude") {
|
|
3785
3866
|
if (deletedFilter === "exclude") {
|
|
@@ -5510,7 +5591,7 @@ async function handleDeny(args, userId, authContext) {
|
|
|
5510
5591
|
}
|
|
5511
5592
|
|
|
5512
5593
|
// src/tools/search-space.ts
|
|
5513
|
-
import { Filters as
|
|
5594
|
+
import { Filters as Filters7 } from "weaviate-client";
|
|
5514
5595
|
var searchSpaceTool = {
|
|
5515
5596
|
name: "remember_search_space",
|
|
5516
5597
|
description: `Search shared spaces and/or groups to discover memories from other users.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prmichaelsen/remember-mcp",
|
|
3
|
-
"version": "3.14.
|
|
3
|
+
"version": "3.14.9",
|
|
4
4
|
"description": "Multi-tenant memory system MCP server with vector search and relationships",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
51
51
|
"@prmichaelsen/firebase-admin-sdk-v8": "^2.2.0",
|
|
52
52
|
"@prmichaelsen/mcp-auth": "^7.0.4",
|
|
53
|
-
"@prmichaelsen/remember-core": "^0.
|
|
53
|
+
"@prmichaelsen/remember-core": "^0.22.3",
|
|
54
54
|
"@prmichaelsen/remember-mcp": "^2.7.3",
|
|
55
55
|
"dotenv": "^16.4.5",
|
|
56
56
|
"uuid": "^13.0.0",
|