@prmichaelsen/remember-mcp 3.16.0 → 3.16.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.
@@ -0,0 +1,55 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ branches: [mainline]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 2
16
+
17
+ - uses: actions/setup-node@v4
18
+ with:
19
+ node-version: 20
20
+ registry-url: https://registry.npmjs.org
21
+
22
+ - name: Install dependencies
23
+ run: npm ci
24
+
25
+ - name: Build
26
+ run: npm run build
27
+
28
+ - name: Test
29
+ run: npm test
30
+
31
+ - name: Check if version changed
32
+ id: version
33
+ run: |
34
+ CURRENT=$(node -p "require('./package.json').version")
35
+ PREVIOUS=$(git show HEAD~1:package.json 2>/dev/null | node -p "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).version" 2>/dev/null || echo "")
36
+ if [ "$CURRENT" != "$PREVIOUS" ]; then
37
+ echo "changed=true" >> "$GITHUB_OUTPUT"
38
+ echo "version=$CURRENT" >> "$GITHUB_OUTPUT"
39
+ else
40
+ echo "changed=false" >> "$GITHUB_OUTPUT"
41
+ fi
42
+
43
+ - name: Publish
44
+ if: steps.version.outputs.changed == 'true'
45
+ run: npm publish --access public
46
+ env:
47
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
48
+
49
+ - name: Summary
50
+ if: steps.version.outputs.changed == 'true'
51
+ run: echo "Published @prmichaelsen/remember-mcp@${{ steps.version.outputs.version }} to npm"
52
+
53
+ - name: Skip
54
+ if: steps.version.outputs.changed != 'true'
55
+ run: echo "Version unchanged, skipping publish"
@@ -1931,7 +1931,13 @@ var COMMON_MEMORY_PROPERTIES = [
1931
1931
  { name: "total_significance", dataType: configure.dataType.NUMBER },
1932
1932
  // REM metadata
1933
1933
  { name: "rem_touched_at", dataType: configure.dataType.TEXT },
1934
- { name: "rem_visits", dataType: configure.dataType.INT }
1934
+ { name: "rem_visits", dataType: configure.dataType.INT },
1935
+ // Curation scoring (M36)
1936
+ { name: "curated_score", dataType: configure.dataType.NUMBER },
1937
+ { name: "editorial_score", dataType: configure.dataType.NUMBER },
1938
+ { name: "click_count", dataType: configure.dataType.INT },
1939
+ { name: "share_count", dataType: configure.dataType.INT },
1940
+ { name: "comment_count", dataType: configure.dataType.INT }
1935
1941
  ];
1936
1942
  var PUBLISHED_MEMORY_PROPERTIES = [
1937
1943
  // Publication metadata
@@ -2582,7 +2588,13 @@ var ALL_MEMORY_PROPERTIES = [
2582
2588
  "functional_significance",
2583
2589
  "total_significance",
2584
2590
  "rem_touched_at",
2585
- "rem_visits"
2591
+ "rem_visits",
2592
+ // Curation scoring (M36)
2593
+ "curated_score",
2594
+ "editorial_score",
2595
+ "click_count",
2596
+ "share_count",
2597
+ "comment_count"
2586
2598
  ];
2587
2599
  async function fetchMemoryWithAllProperties(collection, memoryId) {
2588
2600
  try {
@@ -3358,6 +3370,99 @@ var MemoryService = class {
3358
3370
  total_pool_size: totalPoolSize
3359
3371
  };
3360
3372
  }
3373
+ // ── By Curated (composite quality score) ──────────────────────────
3374
+ async byCurated(input) {
3375
+ const limit = input.limit ?? 50;
3376
+ const offset = input.offset ?? 0;
3377
+ const direction = input.direction ?? "desc";
3378
+ const memoryFilters = buildMemoryOnlyFilters(this.collection, input.filters);
3379
+ const ghostFilters = [];
3380
+ if (input.ghost_context) {
3381
+ ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
3382
+ }
3383
+ if (!input.ghost_context?.include_ghost_content && !input.filters?.types?.includes("ghost")) {
3384
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
3385
+ }
3386
+ if (!input.filters?.types?.includes("rem")) {
3387
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("rem"));
3388
+ }
3389
+ const hasQuery = input.query?.trim();
3390
+ const fetchLimit = (limit + offset) * 2;
3391
+ const executeScoredQuery = async (useDeletedFilter) => {
3392
+ const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
3393
+ const scoredFilter = this.collection.filter.byProperty("curated_score").greaterThan(0);
3394
+ const combined = combineFiltersWithAnd([deletedFilter, memoryFilters, scoredFilter, ...ghostFilters].filter((f) => f !== null));
3395
+ if (hasQuery) {
3396
+ const queryOptions2 = {
3397
+ limit: fetchLimit,
3398
+ alpha: 0.7,
3399
+ query: hasQuery
3400
+ };
3401
+ if (combined)
3402
+ queryOptions2.filters = combined;
3403
+ return this.collection.query.hybrid(hasQuery, queryOptions2);
3404
+ }
3405
+ const queryOptions = {
3406
+ limit: fetchLimit,
3407
+ sort: this.collection.sort.byProperty("curated_score", direction === "asc")
3408
+ };
3409
+ if (combined)
3410
+ queryOptions.filters = combined;
3411
+ return this.collection.query.fetchObjects(queryOptions);
3412
+ };
3413
+ const executeUnscoredQuery = async (useDeletedFilter) => {
3414
+ const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
3415
+ const unscoredFilters = [];
3416
+ const combined = combineFiltersWithAnd([deletedFilter, memoryFilters, ...ghostFilters].filter((f) => f !== null));
3417
+ const queryOptions = {
3418
+ limit: Math.ceil(fetchLimit / 4),
3419
+ sort: this.collection.sort.byProperty("created_at", false)
3420
+ // newest first
3421
+ };
3422
+ if (combined)
3423
+ queryOptions.filters = combined;
3424
+ return this.collection.query.fetchObjects(queryOptions);
3425
+ };
3426
+ const scoredResults = await this.retryWithoutDeletedFilter(executeScoredQuery);
3427
+ const unscoredResults = await this.retryWithoutDeletedFilter(executeUnscoredQuery);
3428
+ const scored = [];
3429
+ for (const obj of scoredResults.objects) {
3430
+ const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
3431
+ if (doc.doc_type === "memory" && doc.curated_score > 0) {
3432
+ scored.push(doc);
3433
+ }
3434
+ }
3435
+ if (hasQuery) {
3436
+ scored.sort((a, b) => {
3437
+ const aScore = a.curated_score ?? 0;
3438
+ const bScore = b.curated_score ?? 0;
3439
+ return direction === "asc" ? aScore - bScore : bScore - aScore;
3440
+ });
3441
+ }
3442
+ const unscored = [];
3443
+ for (const obj of unscoredResults.objects) {
3444
+ const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
3445
+ if (doc.doc_type === "memory" && !doc.curated_score) {
3446
+ unscored.push(doc);
3447
+ }
3448
+ }
3449
+ const interleaved = interleaveDiscovery({
3450
+ rated: scored,
3451
+ discovery: unscored,
3452
+ offset,
3453
+ limit
3454
+ });
3455
+ const memories = interleaved.map((item) => ({
3456
+ ...item.item,
3457
+ ...item.is_discovery ? { is_discovery: true } : {}
3458
+ }));
3459
+ return {
3460
+ memories,
3461
+ total: memories.length,
3462
+ offset,
3463
+ limit
3464
+ };
3465
+ }
3361
3466
  // ── Find Similar (vector) ──────────────────────────────────────────
3362
3467
  async findSimilar(input) {
3363
3468
  if (!input.memory_id && !input.text)
@@ -3374,6 +3479,7 @@ var MemoryService = class {
3374
3479
  ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
3375
3480
  }
3376
3481
  ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("rem"));
3482
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("comment"));
3377
3483
  let memoryObj = null;
3378
3484
  if (input.memory_id) {
3379
3485
  memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
@@ -3565,6 +3671,28 @@ var MemoryService = class {
3565
3671
  orphaned_relationship_ids: orphanedIds
3566
3672
  };
3567
3673
  }
3674
+ // ── Engagement Counters ───────────────────────────────────────────
3675
+ async incrementClick(memoryId) {
3676
+ await this.incrementCounter(memoryId, "click_count");
3677
+ }
3678
+ async incrementShare(memoryId) {
3679
+ await this.incrementCounter(memoryId, "share_count");
3680
+ }
3681
+ async incrementComment(memoryId) {
3682
+ await this.incrementCounter(memoryId, "comment_count");
3683
+ }
3684
+ async incrementCounter(memoryId, field) {
3685
+ const existing = await this.collection.query.fetchObjectById(memoryId, {
3686
+ returnProperties: [field]
3687
+ });
3688
+ if (!existing)
3689
+ throw new Error(`Memory not found: ${memoryId}`);
3690
+ const current = existing.properties?.[field] ?? 0;
3691
+ await this.collection.data.update({
3692
+ id: memoryId,
3693
+ properties: { [field]: current + 1 }
3694
+ });
3695
+ }
3568
3696
  };
3569
3697
 
3570
3698
  // node_modules/@prmichaelsen/remember-core/dist/services/relationship.service.js
@@ -5006,6 +5134,42 @@ var SpaceService = class {
5006
5134
  });
5007
5135
  return { spaces_searched: spacesSearched, groups_searched: groupsSearched, results, total_pool_size: totalPoolSize };
5008
5136
  }
5137
+ // ── By Curated (composite quality score) ──────────────────────────
5138
+ async byCurated(input, authContext) {
5139
+ const spaces = input.spaces || [];
5140
+ const groups = input.groups || [];
5141
+ const limit = input.limit ?? 50;
5142
+ const offset = input.offset ?? 0;
5143
+ const direction = input.direction ?? "desc";
5144
+ this.validateSpaceGroupInput(spaces, groups, input.moderation_filter || "approved", authContext);
5145
+ const fetchLimit = (limit + offset) * 2;
5146
+ const hasQuery = input.query?.trim();
5147
+ const { allResults, spacesSearched, groupsSearched } = await this.fetchAcrossCollections(input, spaces, groups, async (collection, baseFilters) => {
5148
+ const combined = baseFilters.length > 0 ? Filters4.and(...baseFilters) : void 0;
5149
+ if (hasQuery) {
5150
+ const opts2 = { limit: fetchLimit, alpha: 0.7, query: hasQuery };
5151
+ if (combined)
5152
+ opts2.filters = combined;
5153
+ return (await collection.query.hybrid(hasQuery, opts2)).objects;
5154
+ }
5155
+ const opts = {
5156
+ limit: fetchLimit,
5157
+ sort: collection.sort.byProperty("curated_score", direction === "asc")
5158
+ };
5159
+ if (combined)
5160
+ opts.filters = combined;
5161
+ return (await collection.query.fetchObjects(opts)).objects;
5162
+ });
5163
+ const deduped = dedupeBySourceId(allResults, input.dedupe);
5164
+ deduped.sort((a, b) => {
5165
+ const aVal = a.properties?.curated_score ?? 0;
5166
+ const bVal = b.properties?.curated_score ?? 0;
5167
+ return direction === "desc" ? bVal - aVal : aVal - bVal;
5168
+ });
5169
+ const paginated = deduped.slice(offset, offset + limit);
5170
+ const memories = paginated.filter((obj) => obj.properties?.doc_type === "memory").map((obj) => ({ id: obj.uuid, ...obj.properties }));
5171
+ return { spaces_searched: spacesSearched, groups_searched: groupsSearched, memories, total: memories.length, offset, limit };
5172
+ }
5009
5173
  // ── Private: Validate Space/Group Input ───────────────────────────
5010
5174
  validateSpaceGroupInput(spaces, groups, moderationFilter, authContext) {
5011
5175
  if (spaces.length > 0) {
@@ -5150,6 +5314,18 @@ var REM_STATE_COLLECTION = `${BASE}.rem_state`;
5150
5314
  // node_modules/@prmichaelsen/remember-core/dist/services/rem.clustering.js
5151
5315
  import { Filters as Filters5 } from "weaviate-client";
5152
5316
 
5317
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.service.js
5318
+ import { Filters as Filters9 } from "weaviate-client";
5319
+
5320
+ // node_modules/@prmichaelsen/remember-core/dist/services/scoring-context.service.js
5321
+ import { Filters as Filters6 } from "weaviate-client";
5322
+
5323
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.pruning.js
5324
+ import { Filters as Filters7 } from "weaviate-client";
5325
+
5326
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.reconciliation.js
5327
+ import { Filters as Filters8 } from "weaviate-client";
5328
+
5153
5329
  // node_modules/@prmichaelsen/remember-core/dist/services/classification.service.js
5154
5330
  var GENRES = [
5155
5331
  "short_story",
@@ -7437,7 +7613,7 @@ async function handleDeny(args, userId, authContext) {
7437
7613
  }
7438
7614
 
7439
7615
  // src/tools/search-space.ts
7440
- import { Filters as Filters6 } from "weaviate-client";
7616
+ import { Filters as Filters10 } from "weaviate-client";
7441
7617
  var searchSpaceTool = {
7442
7618
  name: "remember_search_space",
7443
7619
  description: `Search shared spaces and/or groups to discover memories from other users.
package/dist/server.js CHANGED
@@ -1935,7 +1935,13 @@ var COMMON_MEMORY_PROPERTIES = [
1935
1935
  { name: "total_significance", dataType: configure.dataType.NUMBER },
1936
1936
  // REM metadata
1937
1937
  { name: "rem_touched_at", dataType: configure.dataType.TEXT },
1938
- { name: "rem_visits", dataType: configure.dataType.INT }
1938
+ { name: "rem_visits", dataType: configure.dataType.INT },
1939
+ // Curation scoring (M36)
1940
+ { name: "curated_score", dataType: configure.dataType.NUMBER },
1941
+ { name: "editorial_score", dataType: configure.dataType.NUMBER },
1942
+ { name: "click_count", dataType: configure.dataType.INT },
1943
+ { name: "share_count", dataType: configure.dataType.INT },
1944
+ { name: "comment_count", dataType: configure.dataType.INT }
1939
1945
  ];
1940
1946
  var PUBLISHED_MEMORY_PROPERTIES = [
1941
1947
  // Publication metadata
@@ -2586,7 +2592,13 @@ var ALL_MEMORY_PROPERTIES = [
2586
2592
  "functional_significance",
2587
2593
  "total_significance",
2588
2594
  "rem_touched_at",
2589
- "rem_visits"
2595
+ "rem_visits",
2596
+ // Curation scoring (M36)
2597
+ "curated_score",
2598
+ "editorial_score",
2599
+ "click_count",
2600
+ "share_count",
2601
+ "comment_count"
2590
2602
  ];
2591
2603
  async function fetchMemoryWithAllProperties(collection, memoryId) {
2592
2604
  try {
@@ -3362,6 +3374,99 @@ var MemoryService = class {
3362
3374
  total_pool_size: totalPoolSize
3363
3375
  };
3364
3376
  }
3377
+ // ── By Curated (composite quality score) ──────────────────────────
3378
+ async byCurated(input) {
3379
+ const limit = input.limit ?? 50;
3380
+ const offset = input.offset ?? 0;
3381
+ const direction = input.direction ?? "desc";
3382
+ const memoryFilters = buildMemoryOnlyFilters(this.collection, input.filters);
3383
+ const ghostFilters = [];
3384
+ if (input.ghost_context) {
3385
+ ghostFilters.push(buildTrustFilter(this.collection, input.ghost_context.accessor_trust_level));
3386
+ }
3387
+ if (!input.ghost_context?.include_ghost_content && !input.filters?.types?.includes("ghost")) {
3388
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
3389
+ }
3390
+ if (!input.filters?.types?.includes("rem")) {
3391
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("rem"));
3392
+ }
3393
+ const hasQuery = input.query?.trim();
3394
+ const fetchLimit = (limit + offset) * 2;
3395
+ const executeScoredQuery = async (useDeletedFilter) => {
3396
+ const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
3397
+ const scoredFilter = this.collection.filter.byProperty("curated_score").greaterThan(0);
3398
+ const combined = combineFiltersWithAnd([deletedFilter, memoryFilters, scoredFilter, ...ghostFilters].filter((f) => f !== null));
3399
+ if (hasQuery) {
3400
+ const queryOptions2 = {
3401
+ limit: fetchLimit,
3402
+ alpha: 0.7,
3403
+ query: hasQuery
3404
+ };
3405
+ if (combined)
3406
+ queryOptions2.filters = combined;
3407
+ return this.collection.query.hybrid(hasQuery, queryOptions2);
3408
+ }
3409
+ const queryOptions = {
3410
+ limit: fetchLimit,
3411
+ sort: this.collection.sort.byProperty("curated_score", direction === "asc")
3412
+ };
3413
+ if (combined)
3414
+ queryOptions.filters = combined;
3415
+ return this.collection.query.fetchObjects(queryOptions);
3416
+ };
3417
+ const executeUnscoredQuery = async (useDeletedFilter) => {
3418
+ const deletedFilter = useDeletedFilter ? buildDeletedFilter(this.collection, input.deleted_filter || "exclude") : null;
3419
+ const unscoredFilters = [];
3420
+ const combined = combineFiltersWithAnd([deletedFilter, memoryFilters, ...ghostFilters].filter((f) => f !== null));
3421
+ const queryOptions = {
3422
+ limit: Math.ceil(fetchLimit / 4),
3423
+ sort: this.collection.sort.byProperty("created_at", false)
3424
+ // newest first
3425
+ };
3426
+ if (combined)
3427
+ queryOptions.filters = combined;
3428
+ return this.collection.query.fetchObjects(queryOptions);
3429
+ };
3430
+ const scoredResults = await this.retryWithoutDeletedFilter(executeScoredQuery);
3431
+ const unscoredResults = await this.retryWithoutDeletedFilter(executeUnscoredQuery);
3432
+ const scored = [];
3433
+ for (const obj of scoredResults.objects) {
3434
+ const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
3435
+ if (doc.doc_type === "memory" && doc.curated_score > 0) {
3436
+ scored.push(doc);
3437
+ }
3438
+ }
3439
+ if (hasQuery) {
3440
+ scored.sort((a, b) => {
3441
+ const aScore = a.curated_score ?? 0;
3442
+ const bScore = b.curated_score ?? 0;
3443
+ return direction === "asc" ? aScore - bScore : bScore - aScore;
3444
+ });
3445
+ }
3446
+ const unscored = [];
3447
+ for (const obj of unscoredResults.objects) {
3448
+ const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
3449
+ if (doc.doc_type === "memory" && !doc.curated_score) {
3450
+ unscored.push(doc);
3451
+ }
3452
+ }
3453
+ const interleaved = interleaveDiscovery({
3454
+ rated: scored,
3455
+ discovery: unscored,
3456
+ offset,
3457
+ limit
3458
+ });
3459
+ const memories = interleaved.map((item) => ({
3460
+ ...item.item,
3461
+ ...item.is_discovery ? { is_discovery: true } : {}
3462
+ }));
3463
+ return {
3464
+ memories,
3465
+ total: memories.length,
3466
+ offset,
3467
+ limit
3468
+ };
3469
+ }
3365
3470
  // ── Find Similar (vector) ──────────────────────────────────────────
3366
3471
  async findSimilar(input) {
3367
3472
  if (!input.memory_id && !input.text)
@@ -3378,6 +3483,7 @@ var MemoryService = class {
3378
3483
  ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("ghost"));
3379
3484
  }
3380
3485
  ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("rem"));
3486
+ ghostFilters.push(this.collection.filter.byProperty("content_type").notEqual("comment"));
3381
3487
  let memoryObj = null;
3382
3488
  if (input.memory_id) {
3383
3489
  memoryObj = await this.collection.query.fetchObjectById(input.memory_id, {
@@ -3569,6 +3675,28 @@ var MemoryService = class {
3569
3675
  orphaned_relationship_ids: orphanedIds
3570
3676
  };
3571
3677
  }
3678
+ // ── Engagement Counters ───────────────────────────────────────────
3679
+ async incrementClick(memoryId) {
3680
+ await this.incrementCounter(memoryId, "click_count");
3681
+ }
3682
+ async incrementShare(memoryId) {
3683
+ await this.incrementCounter(memoryId, "share_count");
3684
+ }
3685
+ async incrementComment(memoryId) {
3686
+ await this.incrementCounter(memoryId, "comment_count");
3687
+ }
3688
+ async incrementCounter(memoryId, field) {
3689
+ const existing = await this.collection.query.fetchObjectById(memoryId, {
3690
+ returnProperties: [field]
3691
+ });
3692
+ if (!existing)
3693
+ throw new Error(`Memory not found: ${memoryId}`);
3694
+ const current = existing.properties?.[field] ?? 0;
3695
+ await this.collection.data.update({
3696
+ id: memoryId,
3697
+ properties: { [field]: current + 1 }
3698
+ });
3699
+ }
3572
3700
  };
3573
3701
 
3574
3702
  // node_modules/@prmichaelsen/remember-core/dist/services/relationship.service.js
@@ -5010,6 +5138,42 @@ var SpaceService = class {
5010
5138
  });
5011
5139
  return { spaces_searched: spacesSearched, groups_searched: groupsSearched, results, total_pool_size: totalPoolSize };
5012
5140
  }
5141
+ // ── By Curated (composite quality score) ──────────────────────────
5142
+ async byCurated(input, authContext) {
5143
+ const spaces = input.spaces || [];
5144
+ const groups = input.groups || [];
5145
+ const limit = input.limit ?? 50;
5146
+ const offset = input.offset ?? 0;
5147
+ const direction = input.direction ?? "desc";
5148
+ this.validateSpaceGroupInput(spaces, groups, input.moderation_filter || "approved", authContext);
5149
+ const fetchLimit = (limit + offset) * 2;
5150
+ const hasQuery = input.query?.trim();
5151
+ const { allResults, spacesSearched, groupsSearched } = await this.fetchAcrossCollections(input, spaces, groups, async (collection, baseFilters) => {
5152
+ const combined = baseFilters.length > 0 ? Filters4.and(...baseFilters) : void 0;
5153
+ if (hasQuery) {
5154
+ const opts2 = { limit: fetchLimit, alpha: 0.7, query: hasQuery };
5155
+ if (combined)
5156
+ opts2.filters = combined;
5157
+ return (await collection.query.hybrid(hasQuery, opts2)).objects;
5158
+ }
5159
+ const opts = {
5160
+ limit: fetchLimit,
5161
+ sort: collection.sort.byProperty("curated_score", direction === "asc")
5162
+ };
5163
+ if (combined)
5164
+ opts.filters = combined;
5165
+ return (await collection.query.fetchObjects(opts)).objects;
5166
+ });
5167
+ const deduped = dedupeBySourceId(allResults, input.dedupe);
5168
+ deduped.sort((a, b) => {
5169
+ const aVal = a.properties?.curated_score ?? 0;
5170
+ const bVal = b.properties?.curated_score ?? 0;
5171
+ return direction === "desc" ? bVal - aVal : aVal - bVal;
5172
+ });
5173
+ const paginated = deduped.slice(offset, offset + limit);
5174
+ const memories = paginated.filter((obj) => obj.properties?.doc_type === "memory").map((obj) => ({ id: obj.uuid, ...obj.properties }));
5175
+ return { spaces_searched: spacesSearched, groups_searched: groupsSearched, memories, total: memories.length, offset, limit };
5176
+ }
5013
5177
  // ── Private: Validate Space/Group Input ───────────────────────────
5014
5178
  validateSpaceGroupInput(spaces, groups, moderationFilter, authContext) {
5015
5179
  if (spaces.length > 0) {
@@ -5154,6 +5318,18 @@ var REM_STATE_COLLECTION = `${BASE}.rem_state`;
5154
5318
  // node_modules/@prmichaelsen/remember-core/dist/services/rem.clustering.js
5155
5319
  import { Filters as Filters5 } from "weaviate-client";
5156
5320
 
5321
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.service.js
5322
+ import { Filters as Filters9 } from "weaviate-client";
5323
+
5324
+ // node_modules/@prmichaelsen/remember-core/dist/services/scoring-context.service.js
5325
+ import { Filters as Filters6 } from "weaviate-client";
5326
+
5327
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.pruning.js
5328
+ import { Filters as Filters7 } from "weaviate-client";
5329
+
5330
+ // node_modules/@prmichaelsen/remember-core/dist/services/rem.reconciliation.js
5331
+ import { Filters as Filters8 } from "weaviate-client";
5332
+
5157
5333
  // node_modules/@prmichaelsen/remember-core/dist/services/classification.service.js
5158
5334
  var GENRES = [
5159
5335
  "short_story",
@@ -7441,7 +7617,7 @@ async function handleDeny(args, userId, authContext) {
7441
7617
  }
7442
7618
 
7443
7619
  // src/tools/search-space.ts
7444
- import { Filters as Filters6 } from "weaviate-client";
7620
+ import { Filters as Filters10 } from "weaviate-client";
7445
7621
  var searchSpaceTool = {
7446
7622
  name: "remember_search_space",
7447
7623
  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.16.0",
3
+ "version": "3.16.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",
@@ -51,7 +51,7 @@
51
51
  "@google-cloud/vision": "^5.3.4",
52
52
  "@modelcontextprotocol/sdk": "^1.0.4",
53
53
  "@prmichaelsen/firebase-admin-sdk-v8": "^2.2.0",
54
- "@prmichaelsen/remember-core": "^0.45.0",
54
+ "@prmichaelsen/remember-core": "^0.49.16",
55
55
  "dotenv": "^16.4.5",
56
56
  "uuid": "^13.0.0",
57
57
  "weaviate-client": "^3.2.0"