@prmichaelsen/remember-mcp 3.14.1 → 3.14.3
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/dist/server-factory.js +105 -30
- package/dist/server.js +105 -30
- package/package.json +2 -2
package/dist/server-factory.js
CHANGED
|
@@ -2256,6 +2256,20 @@ var MemoryService = class {
|
|
|
2256
2256
|
this.userId = userId;
|
|
2257
2257
|
this.logger = logger2;
|
|
2258
2258
|
}
|
|
2259
|
+
/**
|
|
2260
|
+
* Execute a search function, retrying without the deleted_at filter if
|
|
2261
|
+
* the collection lacks indexNullState (created before soft-delete support).
|
|
2262
|
+
*/
|
|
2263
|
+
async retryWithoutDeletedFilter(fn) {
|
|
2264
|
+
try {
|
|
2265
|
+
return await fn(true);
|
|
2266
|
+
} catch (err2) {
|
|
2267
|
+
if (err2?.message?.includes("Nullstate must be indexed")) {
|
|
2268
|
+
return fn(false);
|
|
2269
|
+
}
|
|
2270
|
+
throw err2;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2259
2273
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2260
2274
|
async create(input) {
|
|
2261
2275
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2301,7 +2315,6 @@ var MemoryService = class {
|
|
|
2301
2315
|
const alpha = input.alpha ?? 0.7;
|
|
2302
2316
|
const limit = input.limit ?? 10;
|
|
2303
2317
|
const offset = input.offset ?? 0;
|
|
2304
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2305
2318
|
const searchFilters = includeRelationships ? buildCombinedSearchFilters(this.collection, input.filters) : buildMemoryOnlyFilters(this.collection, input.filters);
|
|
2306
2319
|
const ghostFilters = [];
|
|
2307
2320
|
if (input.ghost_context) {
|
|
@@ -2310,11 +2323,21 @@ var MemoryService = class {
|
|
|
2310
2323
|
if (!input.ghost_context?.include_ghost_content) {
|
|
2311
2324
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2312
2325
|
}
|
|
2313
|
-
const
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2326
|
+
const isWildcard = input.query === "*";
|
|
2327
|
+
const executeSearch = async (useDeletedFilter) => {
|
|
2328
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2329
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2330
|
+
const searchOptions = { limit: limit + offset };
|
|
2331
|
+
if (combinedFilters)
|
|
2332
|
+
searchOptions.filters = combinedFilters;
|
|
2333
|
+
if (isWildcard) {
|
|
2334
|
+
return this.collection.query.fetchObjects(searchOptions);
|
|
2335
|
+
} else {
|
|
2336
|
+
searchOptions.alpha = alpha;
|
|
2337
|
+
return this.collection.query.hybrid(input.query, searchOptions);
|
|
2338
|
+
}
|
|
2339
|
+
};
|
|
2340
|
+
const results = await this.retryWithoutDeletedFilter(executeSearch);
|
|
2318
2341
|
const paginated = results.objects.slice(offset);
|
|
2319
2342
|
const memories = [];
|
|
2320
2343
|
const relationships = [];
|
|
@@ -2341,7 +2364,6 @@ var MemoryService = class {
|
|
|
2341
2364
|
throw new Error("Provide either memory_id or text, not both");
|
|
2342
2365
|
const limit = input.limit ?? 10;
|
|
2343
2366
|
const minSimilarity = input.min_similarity ?? 0.7;
|
|
2344
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2345
2367
|
const ghostFilters = [];
|
|
2346
2368
|
if (input.ghost_context) {
|
|
2347
2369
|
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
@@ -2349,29 +2371,35 @@ var MemoryService = class {
|
|
|
2349
2371
|
if (!input.ghost_context?.include_ghost_content) {
|
|
2350
2372
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2351
2373
|
}
|
|
2352
|
-
|
|
2353
|
-
let results;
|
|
2374
|
+
let memoryObj = null;
|
|
2354
2375
|
if (input.memory_id) {
|
|
2355
|
-
|
|
2376
|
+
memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
|
|
2356
2377
|
returnProperties: ["user_id", "doc_type", "content"]
|
|
2357
2378
|
});
|
|
2358
|
-
if (!
|
|
2379
|
+
if (!memoryObj)
|
|
2359
2380
|
throw new Error(`Memory not found: ${input.memory_id}`);
|
|
2360
|
-
if (
|
|
2381
|
+
if (memoryObj.properties.user_id !== this.userId)
|
|
2361
2382
|
throw new Error("Unauthorized");
|
|
2362
|
-
if (
|
|
2383
|
+
if (memoryObj.properties.doc_type !== "memory")
|
|
2363
2384
|
throw new Error("Can only find similar for memory documents");
|
|
2364
|
-
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2365
|
-
if (combinedFilter)
|
|
2366
|
-
opts.filters = combinedFilter;
|
|
2367
|
-
results = await this.collection.query.nearObject(input.memory_id, opts);
|
|
2368
|
-
results.objects = results.objects.filter((o) => o.uuid !== input.memory_id);
|
|
2369
|
-
} else {
|
|
2370
|
-
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2371
|
-
if (combinedFilter)
|
|
2372
|
-
opts.filters = combinedFilter;
|
|
2373
|
-
results = await this.collection.query.nearText(input.text, opts);
|
|
2374
2385
|
}
|
|
2386
|
+
const results = await this.retryWithoutDeletedFilter(async (useDeletedFilter) => {
|
|
2387
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2388
|
+
const combinedFilter = combineFiltersWithAnd([deletedFilter, ...ghostFilters].filter((f) => f !== null));
|
|
2389
|
+
if (input.memory_id) {
|
|
2390
|
+
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2391
|
+
if (combinedFilter)
|
|
2392
|
+
opts.filters = combinedFilter;
|
|
2393
|
+
const res = await this.collection.query.nearObject(input.memory_id, opts);
|
|
2394
|
+
res.objects = res.objects.filter((o) => o.uuid !== input.memory_id);
|
|
2395
|
+
return res;
|
|
2396
|
+
} else {
|
|
2397
|
+
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2398
|
+
if (combinedFilter)
|
|
2399
|
+
opts.filters = combinedFilter;
|
|
2400
|
+
return this.collection.query.nearText(input.text, opts);
|
|
2401
|
+
}
|
|
2402
|
+
});
|
|
2375
2403
|
if (!input.include_relationships) {
|
|
2376
2404
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
2377
2405
|
}
|
|
@@ -2388,7 +2416,6 @@ var MemoryService = class {
|
|
|
2388
2416
|
throw new Error("Query cannot be empty");
|
|
2389
2417
|
const limit = input.limit ?? 5;
|
|
2390
2418
|
const minRelevance = input.min_relevance ?? 0.6;
|
|
2391
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2392
2419
|
const searchFilters = buildCombinedSearchFilters(this.collection, input.filters);
|
|
2393
2420
|
const ghostFilters = [];
|
|
2394
2421
|
if (input.ghost_context) {
|
|
@@ -2397,11 +2424,14 @@ var MemoryService = class {
|
|
|
2397
2424
|
if (!input.ghost_context?.include_ghost_content) {
|
|
2398
2425
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2399
2426
|
}
|
|
2400
|
-
const
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
opts
|
|
2404
|
-
|
|
2427
|
+
const results = await this.retryWithoutDeletedFilter(async (useDeletedFilter) => {
|
|
2428
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2429
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2430
|
+
const opts = { limit, distance: 1 - minRelevance, returnMetadata: ["distance"] };
|
|
2431
|
+
if (combinedFilters)
|
|
2432
|
+
opts.filters = combinedFilters;
|
|
2433
|
+
return this.collection.query.nearText(input.query, opts);
|
|
2434
|
+
});
|
|
2405
2435
|
const items = results.objects.map((obj) => ({
|
|
2406
2436
|
id: obj.uuid,
|
|
2407
2437
|
...obj.properties,
|
|
@@ -2848,6 +2878,51 @@ function createSpaceCollectionSchema() {
|
|
|
2848
2878
|
})
|
|
2849
2879
|
};
|
|
2850
2880
|
}
|
|
2881
|
+
function createGroupCollectionSchema(groupId) {
|
|
2882
|
+
const collectionName = `Memory_groups_${groupId}`;
|
|
2883
|
+
return {
|
|
2884
|
+
name: collectionName,
|
|
2885
|
+
description: `Group memory collection for group: ${groupId}`,
|
|
2886
|
+
vectorizers: configure.vectorizer.text2VecOpenAI({
|
|
2887
|
+
model: "text-embedding-3-small",
|
|
2888
|
+
dimensions: 1536,
|
|
2889
|
+
vectorizeCollectionName: false
|
|
2890
|
+
}),
|
|
2891
|
+
properties: [
|
|
2892
|
+
...COMMON_MEMORY_PROPERTIES,
|
|
2893
|
+
...PUBLISHED_MEMORY_PROPERTIES
|
|
2894
|
+
],
|
|
2895
|
+
invertedIndex: configure.invertedIndex({
|
|
2896
|
+
indexNullState: true,
|
|
2897
|
+
indexPropertyLength: true,
|
|
2898
|
+
indexTimestamps: true
|
|
2899
|
+
})
|
|
2900
|
+
};
|
|
2901
|
+
}
|
|
2902
|
+
async function reconcileCollectionProperties(client2, collectionName, expectedProperties) {
|
|
2903
|
+
const collection = client2.collections.get(collectionName);
|
|
2904
|
+
const config2 = await collection.config.get();
|
|
2905
|
+
const existingNames = new Set(config2.properties.map((p) => p.name));
|
|
2906
|
+
let added = 0;
|
|
2907
|
+
for (const prop of expectedProperties) {
|
|
2908
|
+
if (!existingNames.has(prop.name)) {
|
|
2909
|
+
await collection.config.addProperty(prop);
|
|
2910
|
+
added++;
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
return added;
|
|
2914
|
+
}
|
|
2915
|
+
async function ensureGroupCollection(client2, groupId) {
|
|
2916
|
+
const collectionName = `Memory_groups_${groupId}`;
|
|
2917
|
+
const exists = await client2.collections.exists(collectionName);
|
|
2918
|
+
if (exists) {
|
|
2919
|
+
await reconcileCollectionProperties(client2, collectionName, [...COMMON_MEMORY_PROPERTIES, ...PUBLISHED_MEMORY_PROPERTIES]);
|
|
2920
|
+
return false;
|
|
2921
|
+
}
|
|
2922
|
+
const schema = createGroupCollectionSchema(groupId);
|
|
2923
|
+
await client2.collections.create(schema);
|
|
2924
|
+
return true;
|
|
2925
|
+
}
|
|
2851
2926
|
|
|
2852
2927
|
// node_modules/@prmichaelsen/remember-core/dist/database/weaviate/space-schema.js
|
|
2853
2928
|
var PUBLIC_COLLECTION_NAME = "Memory_spaces_public";
|
|
@@ -3298,6 +3373,7 @@ var SpaceService = class {
|
|
|
3298
3373
|
for (const groupId of groups) {
|
|
3299
3374
|
const groupCollectionName = getCollectionName(CollectionType.GROUPS, groupId);
|
|
3300
3375
|
try {
|
|
3376
|
+
await ensureGroupCollection(this.weaviateClient, groupId);
|
|
3301
3377
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
3302
3378
|
let existingGroupMemory = null;
|
|
3303
3379
|
try {
|
|
@@ -3510,7 +3586,6 @@ var SpaceService = class {
|
|
|
3510
3586
|
// ── Private: Build Base Filters ─────────────────────────────────────
|
|
3511
3587
|
buildBaseFilters(collection, input) {
|
|
3512
3588
|
const filterList = [];
|
|
3513
|
-
filterList.push(collection.filter.byProperty("deleted_at").isNull(true));
|
|
3514
3589
|
filterList.push(collection.filter.byProperty("doc_type").equal("memory"));
|
|
3515
3590
|
const moderationFilter = buildModerationFilter(collection, input.moderation_filter);
|
|
3516
3591
|
if (moderationFilter)
|
package/dist/server.js
CHANGED
|
@@ -1940,6 +1940,20 @@ var MemoryService = class {
|
|
|
1940
1940
|
this.userId = userId;
|
|
1941
1941
|
this.logger = logger2;
|
|
1942
1942
|
}
|
|
1943
|
+
/**
|
|
1944
|
+
* Execute a search function, retrying without the deleted_at filter if
|
|
1945
|
+
* the collection lacks indexNullState (created before soft-delete support).
|
|
1946
|
+
*/
|
|
1947
|
+
async retryWithoutDeletedFilter(fn) {
|
|
1948
|
+
try {
|
|
1949
|
+
return await fn(true);
|
|
1950
|
+
} catch (err2) {
|
|
1951
|
+
if (err2?.message?.includes("Nullstate must be indexed")) {
|
|
1952
|
+
return fn(false);
|
|
1953
|
+
}
|
|
1954
|
+
throw err2;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1943
1957
|
// ── Create ──────────────────────────────────────────────────────────
|
|
1944
1958
|
async create(input) {
|
|
1945
1959
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1985,7 +1999,6 @@ var MemoryService = class {
|
|
|
1985
1999
|
const alpha = input.alpha ?? 0.7;
|
|
1986
2000
|
const limit = input.limit ?? 10;
|
|
1987
2001
|
const offset = input.offset ?? 0;
|
|
1988
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
1989
2002
|
const searchFilters = includeRelationships ? buildCombinedSearchFilters(this.collection, input.filters) : buildMemoryOnlyFilters(this.collection, input.filters);
|
|
1990
2003
|
const ghostFilters = [];
|
|
1991
2004
|
if (input.ghost_context) {
|
|
@@ -1994,11 +2007,21 @@ var MemoryService = class {
|
|
|
1994
2007
|
if (!input.ghost_context?.include_ghost_content) {
|
|
1995
2008
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
1996
2009
|
}
|
|
1997
|
-
const
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2010
|
+
const isWildcard = input.query === "*";
|
|
2011
|
+
const executeSearch = async (useDeletedFilter) => {
|
|
2012
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2013
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2014
|
+
const searchOptions = { limit: limit + offset };
|
|
2015
|
+
if (combinedFilters)
|
|
2016
|
+
searchOptions.filters = combinedFilters;
|
|
2017
|
+
if (isWildcard) {
|
|
2018
|
+
return this.collection.query.fetchObjects(searchOptions);
|
|
2019
|
+
} else {
|
|
2020
|
+
searchOptions.alpha = alpha;
|
|
2021
|
+
return this.collection.query.hybrid(input.query, searchOptions);
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
const results = await this.retryWithoutDeletedFilter(executeSearch);
|
|
2002
2025
|
const paginated = results.objects.slice(offset);
|
|
2003
2026
|
const memories = [];
|
|
2004
2027
|
const relationships = [];
|
|
@@ -2025,7 +2048,6 @@ var MemoryService = class {
|
|
|
2025
2048
|
throw new Error("Provide either memory_id or text, not both");
|
|
2026
2049
|
const limit = input.limit ?? 10;
|
|
2027
2050
|
const minSimilarity = input.min_similarity ?? 0.7;
|
|
2028
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2029
2051
|
const ghostFilters = [];
|
|
2030
2052
|
if (input.ghost_context) {
|
|
2031
2053
|
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
@@ -2033,29 +2055,35 @@ var MemoryService = class {
|
|
|
2033
2055
|
if (!input.ghost_context?.include_ghost_content) {
|
|
2034
2056
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2035
2057
|
}
|
|
2036
|
-
|
|
2037
|
-
let results;
|
|
2058
|
+
let memoryObj = null;
|
|
2038
2059
|
if (input.memory_id) {
|
|
2039
|
-
|
|
2060
|
+
memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
|
|
2040
2061
|
returnProperties: ["user_id", "doc_type", "content"]
|
|
2041
2062
|
});
|
|
2042
|
-
if (!
|
|
2063
|
+
if (!memoryObj)
|
|
2043
2064
|
throw new Error(`Memory not found: ${input.memory_id}`);
|
|
2044
|
-
if (
|
|
2065
|
+
if (memoryObj.properties.user_id !== this.userId)
|
|
2045
2066
|
throw new Error("Unauthorized");
|
|
2046
|
-
if (
|
|
2067
|
+
if (memoryObj.properties.doc_type !== "memory")
|
|
2047
2068
|
throw new Error("Can only find similar for memory documents");
|
|
2048
|
-
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2049
|
-
if (combinedFilter)
|
|
2050
|
-
opts.filters = combinedFilter;
|
|
2051
|
-
results = await this.collection.query.nearObject(input.memory_id, opts);
|
|
2052
|
-
results.objects = results.objects.filter((o) => o.uuid !== input.memory_id);
|
|
2053
|
-
} else {
|
|
2054
|
-
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2055
|
-
if (combinedFilter)
|
|
2056
|
-
opts.filters = combinedFilter;
|
|
2057
|
-
results = await this.collection.query.nearText(input.text, opts);
|
|
2058
2069
|
}
|
|
2070
|
+
const results = await this.retryWithoutDeletedFilter(async (useDeletedFilter) => {
|
|
2071
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2072
|
+
const combinedFilter = combineFiltersWithAnd([deletedFilter, ...ghostFilters].filter((f) => f !== null));
|
|
2073
|
+
if (input.memory_id) {
|
|
2074
|
+
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2075
|
+
if (combinedFilter)
|
|
2076
|
+
opts.filters = combinedFilter;
|
|
2077
|
+
const res = await this.collection.query.nearObject(input.memory_id, opts);
|
|
2078
|
+
res.objects = res.objects.filter((o) => o.uuid !== input.memory_id);
|
|
2079
|
+
return res;
|
|
2080
|
+
} else {
|
|
2081
|
+
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2082
|
+
if (combinedFilter)
|
|
2083
|
+
opts.filters = combinedFilter;
|
|
2084
|
+
return this.collection.query.nearText(input.text, opts);
|
|
2085
|
+
}
|
|
2086
|
+
});
|
|
2059
2087
|
if (!input.include_relationships) {
|
|
2060
2088
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
2061
2089
|
}
|
|
@@ -2072,7 +2100,6 @@ var MemoryService = class {
|
|
|
2072
2100
|
throw new Error("Query cannot be empty");
|
|
2073
2101
|
const limit = input.limit ?? 5;
|
|
2074
2102
|
const minRelevance = input.min_relevance ?? 0.6;
|
|
2075
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2076
2103
|
const searchFilters = buildCombinedSearchFilters(this.collection, input.filters);
|
|
2077
2104
|
const ghostFilters = [];
|
|
2078
2105
|
if (input.ghost_context) {
|
|
@@ -2081,11 +2108,14 @@ var MemoryService = class {
|
|
|
2081
2108
|
if (!input.ghost_context?.include_ghost_content) {
|
|
2082
2109
|
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2083
2110
|
}
|
|
2084
|
-
const
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
opts
|
|
2088
|
-
|
|
2111
|
+
const results = await this.retryWithoutDeletedFilter(async (useDeletedFilter) => {
|
|
2112
|
+
const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
|
|
2113
|
+
const combinedFilters = combineFiltersWithAnd([deletedFilter, searchFilters, ...ghostFilters].filter((f) => f !== null));
|
|
2114
|
+
const opts = { limit, distance: 1 - minRelevance, returnMetadata: ["distance"] };
|
|
2115
|
+
if (combinedFilters)
|
|
2116
|
+
opts.filters = combinedFilters;
|
|
2117
|
+
return this.collection.query.nearText(input.query, opts);
|
|
2118
|
+
});
|
|
2089
2119
|
const items = results.objects.map((obj) => ({
|
|
2090
2120
|
id: obj.uuid,
|
|
2091
2121
|
...obj.properties,
|
|
@@ -2532,6 +2562,51 @@ function createSpaceCollectionSchema() {
|
|
|
2532
2562
|
})
|
|
2533
2563
|
};
|
|
2534
2564
|
}
|
|
2565
|
+
function createGroupCollectionSchema(groupId) {
|
|
2566
|
+
const collectionName = `Memory_groups_${groupId}`;
|
|
2567
|
+
return {
|
|
2568
|
+
name: collectionName,
|
|
2569
|
+
description: `Group memory collection for group: ${groupId}`,
|
|
2570
|
+
vectorizers: configure.vectorizer.text2VecOpenAI({
|
|
2571
|
+
model: "text-embedding-3-small",
|
|
2572
|
+
dimensions: 1536,
|
|
2573
|
+
vectorizeCollectionName: false
|
|
2574
|
+
}),
|
|
2575
|
+
properties: [
|
|
2576
|
+
...COMMON_MEMORY_PROPERTIES,
|
|
2577
|
+
...PUBLISHED_MEMORY_PROPERTIES
|
|
2578
|
+
],
|
|
2579
|
+
invertedIndex: configure.invertedIndex({
|
|
2580
|
+
indexNullState: true,
|
|
2581
|
+
indexPropertyLength: true,
|
|
2582
|
+
indexTimestamps: true
|
|
2583
|
+
})
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
async function reconcileCollectionProperties(client2, collectionName, expectedProperties) {
|
|
2587
|
+
const collection = client2.collections.get(collectionName);
|
|
2588
|
+
const config3 = await collection.config.get();
|
|
2589
|
+
const existingNames = new Set(config3.properties.map((p) => p.name));
|
|
2590
|
+
let added = 0;
|
|
2591
|
+
for (const prop of expectedProperties) {
|
|
2592
|
+
if (!existingNames.has(prop.name)) {
|
|
2593
|
+
await collection.config.addProperty(prop);
|
|
2594
|
+
added++;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
return added;
|
|
2598
|
+
}
|
|
2599
|
+
async function ensureGroupCollection(client2, groupId) {
|
|
2600
|
+
const collectionName = `Memory_groups_${groupId}`;
|
|
2601
|
+
const exists = await client2.collections.exists(collectionName);
|
|
2602
|
+
if (exists) {
|
|
2603
|
+
await reconcileCollectionProperties(client2, collectionName, [...COMMON_MEMORY_PROPERTIES, ...PUBLISHED_MEMORY_PROPERTIES]);
|
|
2604
|
+
return false;
|
|
2605
|
+
}
|
|
2606
|
+
const schema = createGroupCollectionSchema(groupId);
|
|
2607
|
+
await client2.collections.create(schema);
|
|
2608
|
+
return true;
|
|
2609
|
+
}
|
|
2535
2610
|
|
|
2536
2611
|
// node_modules/@prmichaelsen/remember-core/dist/database/weaviate/space-schema.js
|
|
2537
2612
|
var PUBLIC_COLLECTION_NAME = "Memory_spaces_public";
|
|
@@ -2982,6 +3057,7 @@ var SpaceService = class {
|
|
|
2982
3057
|
for (const groupId of groups) {
|
|
2983
3058
|
const groupCollectionName = getCollectionName(CollectionType.GROUPS, groupId);
|
|
2984
3059
|
try {
|
|
3060
|
+
await ensureGroupCollection(this.weaviateClient, groupId);
|
|
2985
3061
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
2986
3062
|
let existingGroupMemory = null;
|
|
2987
3063
|
try {
|
|
@@ -3194,7 +3270,6 @@ var SpaceService = class {
|
|
|
3194
3270
|
// ── Private: Build Base Filters ─────────────────────────────────────
|
|
3195
3271
|
buildBaseFilters(collection, input) {
|
|
3196
3272
|
const filterList = [];
|
|
3197
|
-
filterList.push(collection.filter.byProperty("deleted_at").isNull(true));
|
|
3198
3273
|
filterList.push(collection.filter.byProperty("doc_type").equal("memory"));
|
|
3199
3274
|
const moderationFilter = buildModerationFilter(collection, input.moderation_filter);
|
|
3200
3275
|
if (moderationFilter)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prmichaelsen/remember-mcp",
|
|
3
|
-
"version": "3.14.
|
|
3
|
+
"version": "3.14.3",
|
|
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.16.
|
|
53
|
+
"@prmichaelsen/remember-core": "^0.16.6",
|
|
54
54
|
"@prmichaelsen/remember-mcp": "^2.7.3",
|
|
55
55
|
"dotenv": "^16.4.5",
|
|
56
56
|
"uuid": "^13.0.0",
|