@prmichaelsen/remember-mcp 3.14.0 → 3.14.2
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/CHANGELOG.md +22 -0
- package/dist/server-factory.js +211 -45
- package/dist/server.js +211 -45
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.14.0] - 2026-02-28
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
**remember-core Migration (M17)**
|
|
13
|
+
|
|
14
|
+
- Migrate 18 tool handlers to `@prmichaelsen/remember-core` service layer — tools are now thin adapters delegating to core services
|
|
15
|
+
- Replace local services (ConfirmationTokenService, PreferencesDatabaseService, SpaceConfigService) with remember-core equivalents
|
|
16
|
+
- Replace local utilities (dot-notation, composite-ids, tracking-arrays, content-types) with remember-core exports
|
|
17
|
+
|
|
18
|
+
### Removed
|
|
19
|
+
|
|
20
|
+
- `src/services/confirmation-token.service.ts` — now provided by remember-core
|
|
21
|
+
- `src/services/preferences-database.service.ts` — now provided by remember-core
|
|
22
|
+
- `src/services/space-config.service.ts` — now provided by remember-core
|
|
23
|
+
- `src/constants/content-types.ts` — now provided by remember-core
|
|
24
|
+
- `src/collections/` directory (dot-notation, composite-ids, tracking-arrays) — now provided by remember-core
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Add `uuid` as direct dependency to resolve esbuild bundling error from remember-core transitive dependency
|
|
29
|
+
|
|
8
30
|
## [3.13.0] - 2026-02-28
|
|
9
31
|
|
|
10
32
|
### Changed
|
package/dist/server-factory.js
CHANGED
|
@@ -117,7 +117,7 @@ var require_main = __commonJS({
|
|
|
117
117
|
var packageJson = require_package();
|
|
118
118
|
var version = packageJson.version;
|
|
119
119
|
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
120
|
-
function
|
|
120
|
+
function parse2(src) {
|
|
121
121
|
const obj = {};
|
|
122
122
|
let lines = src.toString();
|
|
123
123
|
lines = lines.replace(/\r\n?/mg, "\n");
|
|
@@ -383,7 +383,7 @@ var require_main = __commonJS({
|
|
|
383
383
|
_parseVault,
|
|
384
384
|
config: config2,
|
|
385
385
|
decrypt,
|
|
386
|
-
parse,
|
|
386
|
+
parse: parse2,
|
|
387
387
|
populate
|
|
388
388
|
};
|
|
389
389
|
module.exports.configDotenv = DotenvModule.configDotenv;
|
|
@@ -1585,7 +1585,92 @@ var DebugLevel2;
|
|
|
1585
1585
|
DebugLevel3[DebugLevel3["TRACE"] = 5] = "TRACE";
|
|
1586
1586
|
})(DebugLevel2 || (DebugLevel2 = {}));
|
|
1587
1587
|
|
|
1588
|
+
// node_modules/uuid/dist-node/regex.js
|
|
1589
|
+
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;
|
|
1590
|
+
|
|
1591
|
+
// node_modules/uuid/dist-node/validate.js
|
|
1592
|
+
function validate(uuid) {
|
|
1593
|
+
return typeof uuid === "string" && regex_default.test(uuid);
|
|
1594
|
+
}
|
|
1595
|
+
var validate_default = validate;
|
|
1596
|
+
|
|
1597
|
+
// node_modules/uuid/dist-node/parse.js
|
|
1598
|
+
function parse(uuid) {
|
|
1599
|
+
if (!validate_default(uuid)) {
|
|
1600
|
+
throw TypeError("Invalid UUID");
|
|
1601
|
+
}
|
|
1602
|
+
let v;
|
|
1603
|
+
return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
|
|
1604
|
+
}
|
|
1605
|
+
var parse_default = parse;
|
|
1606
|
+
|
|
1607
|
+
// node_modules/uuid/dist-node/stringify.js
|
|
1608
|
+
var byteToHex = [];
|
|
1609
|
+
for (let i = 0; i < 256; ++i) {
|
|
1610
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
1611
|
+
}
|
|
1612
|
+
function unsafeStringify(arr, offset = 0) {
|
|
1613
|
+
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();
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
// node_modules/uuid/dist-node/v35.js
|
|
1617
|
+
function stringToBytes(str) {
|
|
1618
|
+
str = unescape(encodeURIComponent(str));
|
|
1619
|
+
const bytes = new Uint8Array(str.length);
|
|
1620
|
+
for (let i = 0; i < str.length; ++i) {
|
|
1621
|
+
bytes[i] = str.charCodeAt(i);
|
|
1622
|
+
}
|
|
1623
|
+
return bytes;
|
|
1624
|
+
}
|
|
1625
|
+
var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
|
1626
|
+
var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
|
|
1627
|
+
function v35(version, hash, value, namespace, buf, offset) {
|
|
1628
|
+
const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
|
|
1629
|
+
const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
|
|
1630
|
+
if (typeof namespace === "string") {
|
|
1631
|
+
namespace = parse_default(namespace);
|
|
1632
|
+
}
|
|
1633
|
+
if (namespace?.length !== 16) {
|
|
1634
|
+
throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
|
|
1635
|
+
}
|
|
1636
|
+
let bytes = new Uint8Array(16 + valueBytes.length);
|
|
1637
|
+
bytes.set(namespaceBytes);
|
|
1638
|
+
bytes.set(valueBytes, namespaceBytes.length);
|
|
1639
|
+
bytes = hash(bytes);
|
|
1640
|
+
bytes[6] = bytes[6] & 15 | version;
|
|
1641
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
1642
|
+
if (buf) {
|
|
1643
|
+
offset = offset || 0;
|
|
1644
|
+
for (let i = 0; i < 16; ++i) {
|
|
1645
|
+
buf[offset + i] = bytes[i];
|
|
1646
|
+
}
|
|
1647
|
+
return buf;
|
|
1648
|
+
}
|
|
1649
|
+
return unsafeStringify(bytes);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
// node_modules/uuid/dist-node/sha1.js
|
|
1653
|
+
import { createHash } from "node:crypto";
|
|
1654
|
+
function sha1(bytes) {
|
|
1655
|
+
if (Array.isArray(bytes)) {
|
|
1656
|
+
bytes = Buffer.from(bytes);
|
|
1657
|
+
} else if (typeof bytes === "string") {
|
|
1658
|
+
bytes = Buffer.from(bytes, "utf8");
|
|
1659
|
+
}
|
|
1660
|
+
return createHash("sha1").update(bytes).digest();
|
|
1661
|
+
}
|
|
1662
|
+
var sha1_default = sha1;
|
|
1663
|
+
|
|
1664
|
+
// node_modules/uuid/dist-node/v5.js
|
|
1665
|
+
function v5(value, namespace, buf, offset) {
|
|
1666
|
+
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
1667
|
+
}
|
|
1668
|
+
v5.DNS = DNS;
|
|
1669
|
+
v5.URL = URL2;
|
|
1670
|
+
var v5_default = v5;
|
|
1671
|
+
|
|
1588
1672
|
// node_modules/@prmichaelsen/remember-core/dist/collections/composite-ids.js
|
|
1673
|
+
var WEAVIATE_UUID_NAMESPACE = v5_default.DNS;
|
|
1589
1674
|
var InvalidCompositeIdError = class extends Error {
|
|
1590
1675
|
constructor(message) {
|
|
1591
1676
|
super(message);
|
|
@@ -1607,6 +1692,28 @@ function generateCompositeId(userId, memoryId) {
|
|
|
1607
1692
|
}
|
|
1608
1693
|
return `${userId}.${memoryId}`;
|
|
1609
1694
|
}
|
|
1695
|
+
function parseCompositeId(compositeId) {
|
|
1696
|
+
const parts = compositeId.split(".");
|
|
1697
|
+
if (parts.length !== 2) {
|
|
1698
|
+
throw new InvalidCompositeIdError(`Invalid composite ID format: ${compositeId}. Expected format: {userId}.{memoryId}`);
|
|
1699
|
+
}
|
|
1700
|
+
const [userId, memoryId] = parts;
|
|
1701
|
+
if (!userId.trim()) {
|
|
1702
|
+
throw new InvalidCompositeIdError(`Invalid composite ID: ${compositeId}. User ID is empty`);
|
|
1703
|
+
}
|
|
1704
|
+
if (!memoryId.trim()) {
|
|
1705
|
+
throw new InvalidCompositeIdError(`Invalid composite ID: ${compositeId}. Memory ID is empty`);
|
|
1706
|
+
}
|
|
1707
|
+
return { userId, memoryId };
|
|
1708
|
+
}
|
|
1709
|
+
function validateCompositeId(id) {
|
|
1710
|
+
parseCompositeId(id);
|
|
1711
|
+
return true;
|
|
1712
|
+
}
|
|
1713
|
+
function compositeIdToUuid(compositeId) {
|
|
1714
|
+
validateCompositeId(compositeId);
|
|
1715
|
+
return v5_default(compositeId, WEAVIATE_UUID_NAMESPACE);
|
|
1716
|
+
}
|
|
1610
1717
|
|
|
1611
1718
|
// node_modules/@prmichaelsen/remember-core/dist/collections/dot-notation.js
|
|
1612
1719
|
var CollectionType;
|
|
@@ -2134,6 +2241,11 @@ async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
|
2134
2241
|
}
|
|
2135
2242
|
}
|
|
2136
2243
|
|
|
2244
|
+
// node_modules/@prmichaelsen/remember-core/dist/services/trust-enforcement.service.js
|
|
2245
|
+
function buildTrustFilter(collection, accessorTrustLevel) {
|
|
2246
|
+
return collection.filter.byProperty("trust_score").lessThanOrEqual(accessorTrustLevel);
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2137
2249
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
2138
2250
|
var MemoryService = class {
|
|
2139
2251
|
collection;
|
|
@@ -2144,6 +2256,20 @@ var MemoryService = class {
|
|
|
2144
2256
|
this.userId = userId;
|
|
2145
2257
|
this.logger = logger2;
|
|
2146
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
|
+
}
|
|
2147
2273
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2148
2274
|
async create(input) {
|
|
2149
2275
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2189,13 +2315,29 @@ var MemoryService = class {
|
|
|
2189
2315
|
const alpha = input.alpha ?? 0.7;
|
|
2190
2316
|
const limit = input.limit ?? 10;
|
|
2191
2317
|
const offset = input.offset ?? 0;
|
|
2192
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2193
2318
|
const searchFilters = includeRelationships ? buildCombinedSearchFilters(this.collection, input.filters) : buildMemoryOnlyFilters(this.collection, input.filters);
|
|
2194
|
-
const
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2319
|
+
const ghostFilters = [];
|
|
2320
|
+
if (input.ghost_context) {
|
|
2321
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2322
|
+
}
|
|
2323
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2324
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2325
|
+
}
|
|
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);
|
|
2199
2341
|
const paginated = results.objects.slice(offset);
|
|
2200
2342
|
const memories = [];
|
|
2201
2343
|
const relationships = [];
|
|
@@ -2222,29 +2364,42 @@ var MemoryService = class {
|
|
|
2222
2364
|
throw new Error("Provide either memory_id or text, not both");
|
|
2223
2365
|
const limit = input.limit ?? 10;
|
|
2224
2366
|
const minSimilarity = input.min_similarity ?? 0.7;
|
|
2225
|
-
const
|
|
2226
|
-
|
|
2367
|
+
const ghostFilters = [];
|
|
2368
|
+
if (input.ghost_context) {
|
|
2369
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2370
|
+
}
|
|
2371
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2372
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2373
|
+
}
|
|
2374
|
+
let memoryObj = null;
|
|
2227
2375
|
if (input.memory_id) {
|
|
2228
|
-
|
|
2376
|
+
memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
|
|
2229
2377
|
returnProperties: ["user_id", "doc_type", "content"]
|
|
2230
2378
|
});
|
|
2231
|
-
if (!
|
|
2379
|
+
if (!memoryObj)
|
|
2232
2380
|
throw new Error(`Memory not found: ${input.memory_id}`);
|
|
2233
|
-
if (
|
|
2381
|
+
if (memoryObj.properties.user_id !== this.userId)
|
|
2234
2382
|
throw new Error("Unauthorized");
|
|
2235
|
-
if (
|
|
2383
|
+
if (memoryObj.properties.doc_type !== "memory")
|
|
2236
2384
|
throw new Error("Can only find similar for memory documents");
|
|
2237
|
-
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2238
|
-
if (deletedFilter)
|
|
2239
|
-
opts.filters = deletedFilter;
|
|
2240
|
-
results = await this.collection.query.nearObject(input.memory_id, opts);
|
|
2241
|
-
results.objects = results.objects.filter((o) => o.uuid !== input.memory_id);
|
|
2242
|
-
} else {
|
|
2243
|
-
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
2244
|
-
if (deletedFilter)
|
|
2245
|
-
opts.filters = deletedFilter;
|
|
2246
|
-
results = await this.collection.query.nearText(input.text, opts);
|
|
2247
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
|
+
});
|
|
2248
2403
|
if (!input.include_relationships) {
|
|
2249
2404
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
2250
2405
|
}
|
|
@@ -2261,13 +2416,22 @@ var MemoryService = class {
|
|
|
2261
2416
|
throw new Error("Query cannot be empty");
|
|
2262
2417
|
const limit = input.limit ?? 5;
|
|
2263
2418
|
const minRelevance = input.min_relevance ?? 0.6;
|
|
2264
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
2265
2419
|
const searchFilters = buildCombinedSearchFilters(this.collection, input.filters);
|
|
2266
|
-
const
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2420
|
+
const ghostFilters = [];
|
|
2421
|
+
if (input.ghost_context) {
|
|
2422
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2423
|
+
}
|
|
2424
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2425
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2426
|
+
}
|
|
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
|
+
});
|
|
2271
2435
|
const items = results.objects.map((obj) => ({
|
|
2272
2436
|
id: obj.uuid,
|
|
2273
2437
|
...obj.properties,
|
|
@@ -3112,6 +3276,7 @@ var SpaceService = class {
|
|
|
3112
3276
|
if (originalMemory.properties.user_id !== this.userId)
|
|
3113
3277
|
throw new Error("Permission denied");
|
|
3114
3278
|
const compositeId = generateCompositeId(this.userId, request.payload.memory_id);
|
|
3279
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
3115
3280
|
const existingSpaceIds = Array.isArray(originalMemory.properties.space_ids) ? originalMemory.properties.space_ids : [];
|
|
3116
3281
|
const existingGroupIds = Array.isArray(originalMemory.properties.group_ids) ? originalMemory.properties.group_ids : [];
|
|
3117
3282
|
const originalTags = Array.isArray(originalMemory.properties.tags) ? originalMemory.properties.tags : [];
|
|
@@ -3124,7 +3289,7 @@ var SpaceService = class {
|
|
|
3124
3289
|
const publicCollection = await ensurePublicCollection(this.weaviateClient);
|
|
3125
3290
|
let existingSpaceMemory = null;
|
|
3126
3291
|
try {
|
|
3127
|
-
existingSpaceMemory = await fetchMemoryWithAllProperties(publicCollection,
|
|
3292
|
+
existingSpaceMemory = await fetchMemoryWithAllProperties(publicCollection, weaviateId);
|
|
3128
3293
|
} catch {
|
|
3129
3294
|
}
|
|
3130
3295
|
const newSpaceIds = [.../* @__PURE__ */ new Set([...existingSpaceIds, ...spaces])];
|
|
@@ -3138,7 +3303,7 @@ var SpaceService = class {
|
|
|
3138
3303
|
}
|
|
3139
3304
|
const publishedMemory = {
|
|
3140
3305
|
...originalMemory.properties,
|
|
3141
|
-
|
|
3306
|
+
composite_id: compositeId,
|
|
3142
3307
|
space_ids: newSpaceIds,
|
|
3143
3308
|
group_ids: existingGroupIds,
|
|
3144
3309
|
spaces,
|
|
@@ -3151,9 +3316,9 @@ var SpaceService = class {
|
|
|
3151
3316
|
};
|
|
3152
3317
|
delete publishedMemory._additional;
|
|
3153
3318
|
if (existingSpaceMemory) {
|
|
3154
|
-
await publicCollection.data.update({ id:
|
|
3319
|
+
await publicCollection.data.update({ id: weaviateId, properties: publishedMemory });
|
|
3155
3320
|
} else {
|
|
3156
|
-
await publicCollection.data.insert({ id:
|
|
3321
|
+
await publicCollection.data.insert({ id: weaviateId, properties: publishedMemory });
|
|
3157
3322
|
}
|
|
3158
3323
|
successfulPublications.push(`spaces: ${spaces.join(", ")}`);
|
|
3159
3324
|
} catch (err2) {
|
|
@@ -3166,7 +3331,7 @@ var SpaceService = class {
|
|
|
3166
3331
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
3167
3332
|
let existingGroupMemory = null;
|
|
3168
3333
|
try {
|
|
3169
|
-
existingGroupMemory = await fetchMemoryWithAllProperties(groupCollection,
|
|
3334
|
+
existingGroupMemory = await fetchMemoryWithAllProperties(groupCollection, weaviateId);
|
|
3170
3335
|
} catch {
|
|
3171
3336
|
}
|
|
3172
3337
|
const newGroupIds = [.../* @__PURE__ */ new Set([...existingGroupIds, groupId])];
|
|
@@ -3174,7 +3339,7 @@ var SpaceService = class {
|
|
|
3174
3339
|
const groupModerationStatus = groupConfig.require_moderation ? "pending" : "approved";
|
|
3175
3340
|
const groupMemory = {
|
|
3176
3341
|
...originalMemory.properties,
|
|
3177
|
-
|
|
3342
|
+
composite_id: compositeId,
|
|
3178
3343
|
space_ids: existingSpaceIds,
|
|
3179
3344
|
group_ids: newGroupIds,
|
|
3180
3345
|
author_id: this.userId,
|
|
@@ -3186,9 +3351,9 @@ var SpaceService = class {
|
|
|
3186
3351
|
};
|
|
3187
3352
|
delete groupMemory._additional;
|
|
3188
3353
|
if (existingGroupMemory) {
|
|
3189
|
-
await groupCollection.data.update({ id:
|
|
3354
|
+
await groupCollection.data.update({ id: weaviateId, properties: groupMemory });
|
|
3190
3355
|
} else {
|
|
3191
|
-
await groupCollection.data.insert({ id:
|
|
3356
|
+
await groupCollection.data.insert({ id: weaviateId, properties: groupMemory });
|
|
3192
3357
|
}
|
|
3193
3358
|
successfulPublications.push(`group: ${groupId}`);
|
|
3194
3359
|
} catch (err2) {
|
|
@@ -3236,17 +3401,18 @@ var SpaceService = class {
|
|
|
3236
3401
|
const currentSpaceIds = Array.isArray(sourceMemory.properties.space_ids) ? sourceMemory.properties.space_ids : [];
|
|
3237
3402
|
const currentGroupIds = Array.isArray(sourceMemory.properties.group_ids) ? sourceMemory.properties.group_ids : [];
|
|
3238
3403
|
const compositeId = generateCompositeId(this.userId, request.payload.memory_id);
|
|
3404
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
3239
3405
|
const successfulRetractions = [];
|
|
3240
3406
|
const failedRetractions = [];
|
|
3241
3407
|
if (spaces.length > 0) {
|
|
3242
3408
|
try {
|
|
3243
3409
|
const spacesCollectionName = getCollectionName(CollectionType.SPACES);
|
|
3244
3410
|
const publicCollection = this.weaviateClient.collections.get(spacesCollectionName);
|
|
3245
|
-
const publishedMemory = await fetchMemoryWithAllProperties(publicCollection,
|
|
3411
|
+
const publishedMemory = await fetchMemoryWithAllProperties(publicCollection, weaviateId);
|
|
3246
3412
|
if (publishedMemory) {
|
|
3247
3413
|
const newSpaceIds = currentSpaceIds.filter((id) => !spaces.includes(id));
|
|
3248
3414
|
await publicCollection.data.update({
|
|
3249
|
-
id:
|
|
3415
|
+
id: weaviateId,
|
|
3250
3416
|
properties: { space_ids: newSpaceIds, retracted_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
3251
3417
|
});
|
|
3252
3418
|
successfulRetractions.push(`spaces: ${spaces.join(", ")}`);
|
|
@@ -3261,12 +3427,12 @@ var SpaceService = class {
|
|
|
3261
3427
|
const groupCollectionName = getCollectionName(CollectionType.GROUPS, groupId);
|
|
3262
3428
|
try {
|
|
3263
3429
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
3264
|
-
const groupMemory = await fetchMemoryWithAllProperties(groupCollection,
|
|
3430
|
+
const groupMemory = await fetchMemoryWithAllProperties(groupCollection, weaviateId);
|
|
3265
3431
|
if (groupMemory) {
|
|
3266
3432
|
const groupMemoryGroupIds = Array.isArray(groupMemory.properties.group_ids) ? groupMemory.properties.group_ids : [];
|
|
3267
3433
|
const newGroupIds = groupMemoryGroupIds.filter((id) => id !== groupId);
|
|
3268
3434
|
await groupCollection.data.update({
|
|
3269
|
-
id:
|
|
3435
|
+
id: weaviateId,
|
|
3270
3436
|
properties: { group_ids: newGroupIds, retracted_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
3271
3437
|
});
|
|
3272
3438
|
successfulRetractions.push(`group: ${groupId}`);
|
|
@@ -3317,11 +3483,12 @@ var SpaceService = class {
|
|
|
3317
3483
|
const newContent = String(sourceMemory.properties.content ?? "");
|
|
3318
3484
|
const revisedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3319
3485
|
const compositeId = generateCompositeId(this.userId, memory_id);
|
|
3486
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
3320
3487
|
const results = [];
|
|
3321
3488
|
const reviseInCollection = async (collectionName, locationLabel) => {
|
|
3322
3489
|
try {
|
|
3323
3490
|
const collection = this.weaviateClient.collections.get(collectionName);
|
|
3324
|
-
const publishedMemory = await fetchMemoryWithAllProperties(collection,
|
|
3491
|
+
const publishedMemory = await fetchMemoryWithAllProperties(collection, weaviateId);
|
|
3325
3492
|
if (!publishedMemory) {
|
|
3326
3493
|
results.push({ location: locationLabel, status: "skipped", error: "Published copy not found" });
|
|
3327
3494
|
return;
|
|
@@ -3333,7 +3500,7 @@ var SpaceService = class {
|
|
|
3333
3500
|
}
|
|
3334
3501
|
const currentRevisionCount = typeof publishedMemory.properties.revision_count === "number" ? publishedMemory.properties.revision_count : 0;
|
|
3335
3502
|
await collection.data.update({
|
|
3336
|
-
id:
|
|
3503
|
+
id: weaviateId,
|
|
3337
3504
|
properties: {
|
|
3338
3505
|
content: newContent,
|
|
3339
3506
|
revised_at: revisedAt,
|
|
@@ -3373,7 +3540,6 @@ var SpaceService = class {
|
|
|
3373
3540
|
// ── Private: Build Base Filters ─────────────────────────────────────
|
|
3374
3541
|
buildBaseFilters(collection, input) {
|
|
3375
3542
|
const filterList = [];
|
|
3376
|
-
filterList.push(collection.filter.byProperty("deleted_at").isNull(true));
|
|
3377
3543
|
filterList.push(collection.filter.byProperty("doc_type").equal("memory"));
|
|
3378
3544
|
const moderationFilter = buildModerationFilter(collection, input.moderation_filter);
|
|
3379
3545
|
if (moderationFilter)
|
package/dist/server.js
CHANGED
|
@@ -118,7 +118,7 @@ var require_main = __commonJS({
|
|
|
118
118
|
var packageJson = require_package();
|
|
119
119
|
var version = packageJson.version;
|
|
120
120
|
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
121
|
-
function
|
|
121
|
+
function parse2(src) {
|
|
122
122
|
const obj = {};
|
|
123
123
|
let lines = src.toString();
|
|
124
124
|
lines = lines.replace(/\r\n?/mg, "\n");
|
|
@@ -384,7 +384,7 @@ var require_main = __commonJS({
|
|
|
384
384
|
_parseVault,
|
|
385
385
|
config: config3,
|
|
386
386
|
decrypt,
|
|
387
|
-
parse,
|
|
387
|
+
parse: parse2,
|
|
388
388
|
populate
|
|
389
389
|
};
|
|
390
390
|
module.exports.configDotenv = DotenvModule.configDotenv;
|
|
@@ -1269,7 +1269,92 @@ var DebugLevel2;
|
|
|
1269
1269
|
DebugLevel3[DebugLevel3["TRACE"] = 5] = "TRACE";
|
|
1270
1270
|
})(DebugLevel2 || (DebugLevel2 = {}));
|
|
1271
1271
|
|
|
1272
|
+
// node_modules/uuid/dist-node/regex.js
|
|
1273
|
+
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;
|
|
1274
|
+
|
|
1275
|
+
// node_modules/uuid/dist-node/validate.js
|
|
1276
|
+
function validate(uuid) {
|
|
1277
|
+
return typeof uuid === "string" && regex_default.test(uuid);
|
|
1278
|
+
}
|
|
1279
|
+
var validate_default = validate;
|
|
1280
|
+
|
|
1281
|
+
// node_modules/uuid/dist-node/parse.js
|
|
1282
|
+
function parse(uuid) {
|
|
1283
|
+
if (!validate_default(uuid)) {
|
|
1284
|
+
throw TypeError("Invalid UUID");
|
|
1285
|
+
}
|
|
1286
|
+
let v;
|
|
1287
|
+
return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
|
|
1288
|
+
}
|
|
1289
|
+
var parse_default = parse;
|
|
1290
|
+
|
|
1291
|
+
// node_modules/uuid/dist-node/stringify.js
|
|
1292
|
+
var byteToHex = [];
|
|
1293
|
+
for (let i = 0; i < 256; ++i) {
|
|
1294
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
1295
|
+
}
|
|
1296
|
+
function unsafeStringify(arr, offset = 0) {
|
|
1297
|
+
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();
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
// node_modules/uuid/dist-node/v35.js
|
|
1301
|
+
function stringToBytes(str) {
|
|
1302
|
+
str = unescape(encodeURIComponent(str));
|
|
1303
|
+
const bytes = new Uint8Array(str.length);
|
|
1304
|
+
for (let i = 0; i < str.length; ++i) {
|
|
1305
|
+
bytes[i] = str.charCodeAt(i);
|
|
1306
|
+
}
|
|
1307
|
+
return bytes;
|
|
1308
|
+
}
|
|
1309
|
+
var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
|
1310
|
+
var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
|
|
1311
|
+
function v35(version, hash, value, namespace, buf, offset) {
|
|
1312
|
+
const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
|
|
1313
|
+
const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
|
|
1314
|
+
if (typeof namespace === "string") {
|
|
1315
|
+
namespace = parse_default(namespace);
|
|
1316
|
+
}
|
|
1317
|
+
if (namespace?.length !== 16) {
|
|
1318
|
+
throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
|
|
1319
|
+
}
|
|
1320
|
+
let bytes = new Uint8Array(16 + valueBytes.length);
|
|
1321
|
+
bytes.set(namespaceBytes);
|
|
1322
|
+
bytes.set(valueBytes, namespaceBytes.length);
|
|
1323
|
+
bytes = hash(bytes);
|
|
1324
|
+
bytes[6] = bytes[6] & 15 | version;
|
|
1325
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
1326
|
+
if (buf) {
|
|
1327
|
+
offset = offset || 0;
|
|
1328
|
+
for (let i = 0; i < 16; ++i) {
|
|
1329
|
+
buf[offset + i] = bytes[i];
|
|
1330
|
+
}
|
|
1331
|
+
return buf;
|
|
1332
|
+
}
|
|
1333
|
+
return unsafeStringify(bytes);
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
// node_modules/uuid/dist-node/sha1.js
|
|
1337
|
+
import { createHash } from "node:crypto";
|
|
1338
|
+
function sha1(bytes) {
|
|
1339
|
+
if (Array.isArray(bytes)) {
|
|
1340
|
+
bytes = Buffer.from(bytes);
|
|
1341
|
+
} else if (typeof bytes === "string") {
|
|
1342
|
+
bytes = Buffer.from(bytes, "utf8");
|
|
1343
|
+
}
|
|
1344
|
+
return createHash("sha1").update(bytes).digest();
|
|
1345
|
+
}
|
|
1346
|
+
var sha1_default = sha1;
|
|
1347
|
+
|
|
1348
|
+
// node_modules/uuid/dist-node/v5.js
|
|
1349
|
+
function v5(value, namespace, buf, offset) {
|
|
1350
|
+
return v35(80, sha1_default, value, namespace, buf, offset);
|
|
1351
|
+
}
|
|
1352
|
+
v5.DNS = DNS;
|
|
1353
|
+
v5.URL = URL2;
|
|
1354
|
+
var v5_default = v5;
|
|
1355
|
+
|
|
1272
1356
|
// node_modules/@prmichaelsen/remember-core/dist/collections/composite-ids.js
|
|
1357
|
+
var WEAVIATE_UUID_NAMESPACE = v5_default.DNS;
|
|
1273
1358
|
var InvalidCompositeIdError = class extends Error {
|
|
1274
1359
|
constructor(message) {
|
|
1275
1360
|
super(message);
|
|
@@ -1291,6 +1376,28 @@ function generateCompositeId(userId, memoryId) {
|
|
|
1291
1376
|
}
|
|
1292
1377
|
return `${userId}.${memoryId}`;
|
|
1293
1378
|
}
|
|
1379
|
+
function parseCompositeId(compositeId) {
|
|
1380
|
+
const parts = compositeId.split(".");
|
|
1381
|
+
if (parts.length !== 2) {
|
|
1382
|
+
throw new InvalidCompositeIdError(`Invalid composite ID format: ${compositeId}. Expected format: {userId}.{memoryId}`);
|
|
1383
|
+
}
|
|
1384
|
+
const [userId, memoryId] = parts;
|
|
1385
|
+
if (!userId.trim()) {
|
|
1386
|
+
throw new InvalidCompositeIdError(`Invalid composite ID: ${compositeId}. User ID is empty`);
|
|
1387
|
+
}
|
|
1388
|
+
if (!memoryId.trim()) {
|
|
1389
|
+
throw new InvalidCompositeIdError(`Invalid composite ID: ${compositeId}. Memory ID is empty`);
|
|
1390
|
+
}
|
|
1391
|
+
return { userId, memoryId };
|
|
1392
|
+
}
|
|
1393
|
+
function validateCompositeId(id) {
|
|
1394
|
+
parseCompositeId(id);
|
|
1395
|
+
return true;
|
|
1396
|
+
}
|
|
1397
|
+
function compositeIdToUuid(compositeId) {
|
|
1398
|
+
validateCompositeId(compositeId);
|
|
1399
|
+
return v5_default(compositeId, WEAVIATE_UUID_NAMESPACE);
|
|
1400
|
+
}
|
|
1294
1401
|
|
|
1295
1402
|
// node_modules/@prmichaelsen/remember-core/dist/collections/dot-notation.js
|
|
1296
1403
|
var CollectionType;
|
|
@@ -1818,6 +1925,11 @@ async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
|
1818
1925
|
}
|
|
1819
1926
|
}
|
|
1820
1927
|
|
|
1928
|
+
// node_modules/@prmichaelsen/remember-core/dist/services/trust-enforcement.service.js
|
|
1929
|
+
function buildTrustFilter(collection, accessorTrustLevel) {
|
|
1930
|
+
return collection.filter.byProperty("trust_score").lessThanOrEqual(accessorTrustLevel);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1821
1933
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
1822
1934
|
var MemoryService = class {
|
|
1823
1935
|
collection;
|
|
@@ -1828,6 +1940,20 @@ var MemoryService = class {
|
|
|
1828
1940
|
this.userId = userId;
|
|
1829
1941
|
this.logger = logger2;
|
|
1830
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
|
+
}
|
|
1831
1957
|
// ── Create ──────────────────────────────────────────────────────────
|
|
1832
1958
|
async create(input) {
|
|
1833
1959
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1873,13 +1999,29 @@ var MemoryService = class {
|
|
|
1873
1999
|
const alpha = input.alpha ?? 0.7;
|
|
1874
2000
|
const limit = input.limit ?? 10;
|
|
1875
2001
|
const offset = input.offset ?? 0;
|
|
1876
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
1877
2002
|
const searchFilters = includeRelationships ? buildCombinedSearchFilters(this.collection, input.filters) : buildMemoryOnlyFilters(this.collection, input.filters);
|
|
1878
|
-
const
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
2003
|
+
const ghostFilters = [];
|
|
2004
|
+
if (input.ghost_context) {
|
|
2005
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2006
|
+
}
|
|
2007
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2008
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2009
|
+
}
|
|
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);
|
|
1883
2025
|
const paginated = results.objects.slice(offset);
|
|
1884
2026
|
const memories = [];
|
|
1885
2027
|
const relationships = [];
|
|
@@ -1906,29 +2048,42 @@ var MemoryService = class {
|
|
|
1906
2048
|
throw new Error("Provide either memory_id or text, not both");
|
|
1907
2049
|
const limit = input.limit ?? 10;
|
|
1908
2050
|
const minSimilarity = input.min_similarity ?? 0.7;
|
|
1909
|
-
const
|
|
1910
|
-
|
|
2051
|
+
const ghostFilters = [];
|
|
2052
|
+
if (input.ghost_context) {
|
|
2053
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2054
|
+
}
|
|
2055
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2056
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2057
|
+
}
|
|
2058
|
+
let memoryObj = null;
|
|
1911
2059
|
if (input.memory_id) {
|
|
1912
|
-
|
|
2060
|
+
memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
|
|
1913
2061
|
returnProperties: ["user_id", "doc_type", "content"]
|
|
1914
2062
|
});
|
|
1915
|
-
if (!
|
|
2063
|
+
if (!memoryObj)
|
|
1916
2064
|
throw new Error(`Memory not found: ${input.memory_id}`);
|
|
1917
|
-
if (
|
|
2065
|
+
if (memoryObj.properties.user_id !== this.userId)
|
|
1918
2066
|
throw new Error("Unauthorized");
|
|
1919
|
-
if (
|
|
2067
|
+
if (memoryObj.properties.doc_type !== "memory")
|
|
1920
2068
|
throw new Error("Can only find similar for memory documents");
|
|
1921
|
-
const opts = { limit: limit + 1, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
1922
|
-
if (deletedFilter)
|
|
1923
|
-
opts.filters = deletedFilter;
|
|
1924
|
-
results = await this.collection.query.nearObject(input.memory_id, opts);
|
|
1925
|
-
results.objects = results.objects.filter((o) => o.uuid !== input.memory_id);
|
|
1926
|
-
} else {
|
|
1927
|
-
const opts = { limit, distance: 1 - minSimilarity, returnMetadata: ["distance"] };
|
|
1928
|
-
if (deletedFilter)
|
|
1929
|
-
opts.filters = deletedFilter;
|
|
1930
|
-
results = await this.collection.query.nearText(input.text, opts);
|
|
1931
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
|
+
});
|
|
1932
2087
|
if (!input.include_relationships) {
|
|
1933
2088
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
1934
2089
|
}
|
|
@@ -1945,13 +2100,22 @@ var MemoryService = class {
|
|
|
1945
2100
|
throw new Error("Query cannot be empty");
|
|
1946
2101
|
const limit = input.limit ?? 5;
|
|
1947
2102
|
const minRelevance = input.min_relevance ?? 0.6;
|
|
1948
|
-
const deletedFilter = buildDeletedFilter(this.collection, input.deleted_filter || "exclude");
|
|
1949
2103
|
const searchFilters = buildCombinedSearchFilters(this.collection, input.filters);
|
|
1950
|
-
const
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
2104
|
+
const ghostFilters = [];
|
|
2105
|
+
if (input.ghost_context) {
|
|
2106
|
+
ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
|
|
2107
|
+
}
|
|
2108
|
+
if (!input.ghost_context?.include_ghost_content) {
|
|
2109
|
+
ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
|
|
2110
|
+
}
|
|
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
|
+
});
|
|
1955
2119
|
const items = results.objects.map((obj) => ({
|
|
1956
2120
|
id: obj.uuid,
|
|
1957
2121
|
...obj.properties,
|
|
@@ -2796,6 +2960,7 @@ var SpaceService = class {
|
|
|
2796
2960
|
if (originalMemory.properties.user_id !== this.userId)
|
|
2797
2961
|
throw new Error("Permission denied");
|
|
2798
2962
|
const compositeId = generateCompositeId(this.userId, request.payload.memory_id);
|
|
2963
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
2799
2964
|
const existingSpaceIds = Array.isArray(originalMemory.properties.space_ids) ? originalMemory.properties.space_ids : [];
|
|
2800
2965
|
const existingGroupIds = Array.isArray(originalMemory.properties.group_ids) ? originalMemory.properties.group_ids : [];
|
|
2801
2966
|
const originalTags = Array.isArray(originalMemory.properties.tags) ? originalMemory.properties.tags : [];
|
|
@@ -2808,7 +2973,7 @@ var SpaceService = class {
|
|
|
2808
2973
|
const publicCollection = await ensurePublicCollection(this.weaviateClient);
|
|
2809
2974
|
let existingSpaceMemory = null;
|
|
2810
2975
|
try {
|
|
2811
|
-
existingSpaceMemory = await fetchMemoryWithAllProperties(publicCollection,
|
|
2976
|
+
existingSpaceMemory = await fetchMemoryWithAllProperties(publicCollection, weaviateId);
|
|
2812
2977
|
} catch {
|
|
2813
2978
|
}
|
|
2814
2979
|
const newSpaceIds = [.../* @__PURE__ */ new Set([...existingSpaceIds, ...spaces])];
|
|
@@ -2822,7 +2987,7 @@ var SpaceService = class {
|
|
|
2822
2987
|
}
|
|
2823
2988
|
const publishedMemory = {
|
|
2824
2989
|
...originalMemory.properties,
|
|
2825
|
-
|
|
2990
|
+
composite_id: compositeId,
|
|
2826
2991
|
space_ids: newSpaceIds,
|
|
2827
2992
|
group_ids: existingGroupIds,
|
|
2828
2993
|
spaces,
|
|
@@ -2835,9 +3000,9 @@ var SpaceService = class {
|
|
|
2835
3000
|
};
|
|
2836
3001
|
delete publishedMemory._additional;
|
|
2837
3002
|
if (existingSpaceMemory) {
|
|
2838
|
-
await publicCollection.data.update({ id:
|
|
3003
|
+
await publicCollection.data.update({ id: weaviateId, properties: publishedMemory });
|
|
2839
3004
|
} else {
|
|
2840
|
-
await publicCollection.data.insert({ id:
|
|
3005
|
+
await publicCollection.data.insert({ id: weaviateId, properties: publishedMemory });
|
|
2841
3006
|
}
|
|
2842
3007
|
successfulPublications.push(`spaces: ${spaces.join(", ")}`);
|
|
2843
3008
|
} catch (err2) {
|
|
@@ -2850,7 +3015,7 @@ var SpaceService = class {
|
|
|
2850
3015
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
2851
3016
|
let existingGroupMemory = null;
|
|
2852
3017
|
try {
|
|
2853
|
-
existingGroupMemory = await fetchMemoryWithAllProperties(groupCollection,
|
|
3018
|
+
existingGroupMemory = await fetchMemoryWithAllProperties(groupCollection, weaviateId);
|
|
2854
3019
|
} catch {
|
|
2855
3020
|
}
|
|
2856
3021
|
const newGroupIds = [.../* @__PURE__ */ new Set([...existingGroupIds, groupId])];
|
|
@@ -2858,7 +3023,7 @@ var SpaceService = class {
|
|
|
2858
3023
|
const groupModerationStatus = groupConfig.require_moderation ? "pending" : "approved";
|
|
2859
3024
|
const groupMemory = {
|
|
2860
3025
|
...originalMemory.properties,
|
|
2861
|
-
|
|
3026
|
+
composite_id: compositeId,
|
|
2862
3027
|
space_ids: existingSpaceIds,
|
|
2863
3028
|
group_ids: newGroupIds,
|
|
2864
3029
|
author_id: this.userId,
|
|
@@ -2870,9 +3035,9 @@ var SpaceService = class {
|
|
|
2870
3035
|
};
|
|
2871
3036
|
delete groupMemory._additional;
|
|
2872
3037
|
if (existingGroupMemory) {
|
|
2873
|
-
await groupCollection.data.update({ id:
|
|
3038
|
+
await groupCollection.data.update({ id: weaviateId, properties: groupMemory });
|
|
2874
3039
|
} else {
|
|
2875
|
-
await groupCollection.data.insert({ id:
|
|
3040
|
+
await groupCollection.data.insert({ id: weaviateId, properties: groupMemory });
|
|
2876
3041
|
}
|
|
2877
3042
|
successfulPublications.push(`group: ${groupId}`);
|
|
2878
3043
|
} catch (err2) {
|
|
@@ -2920,17 +3085,18 @@ var SpaceService = class {
|
|
|
2920
3085
|
const currentSpaceIds = Array.isArray(sourceMemory.properties.space_ids) ? sourceMemory.properties.space_ids : [];
|
|
2921
3086
|
const currentGroupIds = Array.isArray(sourceMemory.properties.group_ids) ? sourceMemory.properties.group_ids : [];
|
|
2922
3087
|
const compositeId = generateCompositeId(this.userId, request.payload.memory_id);
|
|
3088
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
2923
3089
|
const successfulRetractions = [];
|
|
2924
3090
|
const failedRetractions = [];
|
|
2925
3091
|
if (spaces.length > 0) {
|
|
2926
3092
|
try {
|
|
2927
3093
|
const spacesCollectionName = getCollectionName(CollectionType.SPACES);
|
|
2928
3094
|
const publicCollection = this.weaviateClient.collections.get(spacesCollectionName);
|
|
2929
|
-
const publishedMemory = await fetchMemoryWithAllProperties(publicCollection,
|
|
3095
|
+
const publishedMemory = await fetchMemoryWithAllProperties(publicCollection, weaviateId);
|
|
2930
3096
|
if (publishedMemory) {
|
|
2931
3097
|
const newSpaceIds = currentSpaceIds.filter((id) => !spaces.includes(id));
|
|
2932
3098
|
await publicCollection.data.update({
|
|
2933
|
-
id:
|
|
3099
|
+
id: weaviateId,
|
|
2934
3100
|
properties: { space_ids: newSpaceIds, retracted_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2935
3101
|
});
|
|
2936
3102
|
successfulRetractions.push(`spaces: ${spaces.join(", ")}`);
|
|
@@ -2945,12 +3111,12 @@ var SpaceService = class {
|
|
|
2945
3111
|
const groupCollectionName = getCollectionName(CollectionType.GROUPS, groupId);
|
|
2946
3112
|
try {
|
|
2947
3113
|
const groupCollection = this.weaviateClient.collections.get(groupCollectionName);
|
|
2948
|
-
const groupMemory = await fetchMemoryWithAllProperties(groupCollection,
|
|
3114
|
+
const groupMemory = await fetchMemoryWithAllProperties(groupCollection, weaviateId);
|
|
2949
3115
|
if (groupMemory) {
|
|
2950
3116
|
const groupMemoryGroupIds = Array.isArray(groupMemory.properties.group_ids) ? groupMemory.properties.group_ids : [];
|
|
2951
3117
|
const newGroupIds = groupMemoryGroupIds.filter((id) => id !== groupId);
|
|
2952
3118
|
await groupCollection.data.update({
|
|
2953
|
-
id:
|
|
3119
|
+
id: weaviateId,
|
|
2954
3120
|
properties: { group_ids: newGroupIds, retracted_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2955
3121
|
});
|
|
2956
3122
|
successfulRetractions.push(`group: ${groupId}`);
|
|
@@ -3001,11 +3167,12 @@ var SpaceService = class {
|
|
|
3001
3167
|
const newContent = String(sourceMemory.properties.content ?? "");
|
|
3002
3168
|
const revisedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3003
3169
|
const compositeId = generateCompositeId(this.userId, memory_id);
|
|
3170
|
+
const weaviateId = compositeIdToUuid(compositeId);
|
|
3004
3171
|
const results = [];
|
|
3005
3172
|
const reviseInCollection = async (collectionName, locationLabel) => {
|
|
3006
3173
|
try {
|
|
3007
3174
|
const collection = this.weaviateClient.collections.get(collectionName);
|
|
3008
|
-
const publishedMemory = await fetchMemoryWithAllProperties(collection,
|
|
3175
|
+
const publishedMemory = await fetchMemoryWithAllProperties(collection, weaviateId);
|
|
3009
3176
|
if (!publishedMemory) {
|
|
3010
3177
|
results.push({ location: locationLabel, status: "skipped", error: "Published copy not found" });
|
|
3011
3178
|
return;
|
|
@@ -3017,7 +3184,7 @@ var SpaceService = class {
|
|
|
3017
3184
|
}
|
|
3018
3185
|
const currentRevisionCount = typeof publishedMemory.properties.revision_count === "number" ? publishedMemory.properties.revision_count : 0;
|
|
3019
3186
|
await collection.data.update({
|
|
3020
|
-
id:
|
|
3187
|
+
id: weaviateId,
|
|
3021
3188
|
properties: {
|
|
3022
3189
|
content: newContent,
|
|
3023
3190
|
revised_at: revisedAt,
|
|
@@ -3057,7 +3224,6 @@ var SpaceService = class {
|
|
|
3057
3224
|
// ── Private: Build Base Filters ─────────────────────────────────────
|
|
3058
3225
|
buildBaseFilters(collection, input) {
|
|
3059
3226
|
const filterList = [];
|
|
3060
|
-
filterList.push(collection.filter.byProperty("deleted_at").isNull(true));
|
|
3061
3227
|
filterList.push(collection.filter.byProperty("doc_type").equal("memory"));
|
|
3062
3228
|
const moderationFilter = buildModerationFilter(collection, input.moderation_filter);
|
|
3063
3229
|
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.2",
|
|
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,9 +50,10 @@
|
|
|
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.16.0",
|
|
54
54
|
"@prmichaelsen/remember-mcp": "^2.7.3",
|
|
55
55
|
"dotenv": "^16.4.5",
|
|
56
|
+
"uuid": "^13.0.0",
|
|
56
57
|
"weaviate-client": "^3.2.0"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|