@prmichaelsen/remember-mcp 3.14.18 → 3.14.19
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,48 @@
|
|
|
1
|
+
name: Bump remember-core
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
repository_dispatch:
|
|
5
|
+
types: [dependency-update]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
bump:
|
|
9
|
+
if: github.event.client_payload.package == '@prmichaelsen/remember-core'
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
with:
|
|
14
|
+
ref: mainline
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 20
|
|
19
|
+
registry-url: https://registry.npmjs.org
|
|
20
|
+
|
|
21
|
+
- name: Bump remember-core
|
|
22
|
+
run: npm install @prmichaelsen/remember-core@${{ github.event.client_payload.version }} --save
|
|
23
|
+
|
|
24
|
+
- name: Bump package version
|
|
25
|
+
id: bump
|
|
26
|
+
run: |
|
|
27
|
+
CURRENT=$(node -p "require('./package.json').version")
|
|
28
|
+
NEW=$(echo "$CURRENT" | awk -F. '{print $1"."$2"."$3+1}')
|
|
29
|
+
npm version "$NEW" --no-git-tag-version
|
|
30
|
+
echo "version=$NEW" >> "$GITHUB_OUTPUT"
|
|
31
|
+
|
|
32
|
+
- name: Commit and tag
|
|
33
|
+
run: |
|
|
34
|
+
git config user.name "github-actions[bot]"
|
|
35
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
36
|
+
git add package.json package-lock.json
|
|
37
|
+
git commit -m "bump: remember core"
|
|
38
|
+
git commit --allow-empty -m "${{ steps.bump.outputs.version }}"
|
|
39
|
+
git tag "v${{ steps.bump.outputs.version }}"
|
|
40
|
+
git push --follow-tags
|
|
41
|
+
|
|
42
|
+
- name: Publish to npm
|
|
43
|
+
run: npm publish --access public
|
|
44
|
+
env:
|
|
45
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
46
|
+
|
|
47
|
+
- name: Summary
|
|
48
|
+
run: echo "Bumped remember-core to ${{ github.event.client_payload.version }}, published remember-mcp@${{ steps.bump.outputs.version }}"
|
package/agent/progress.yaml
CHANGED
|
@@ -1070,11 +1070,21 @@ tasks:
|
|
|
1070
1070
|
notes: |
|
|
1071
1071
|
Static imports for ghost-config and access-control
|
|
1072
1072
|
|
|
1073
|
+
unassigned:
|
|
1074
|
+
- id: task-201
|
|
1075
|
+
name: Auto-bump remember-core via GitHub Actions
|
|
1076
|
+
status: not_started
|
|
1077
|
+
file: agent/tasks/unassigned/task-201-auto-bump-remember-core-ci.md
|
|
1078
|
+
estimated_hours: 2
|
|
1079
|
+
notes: |
|
|
1080
|
+
Set up repository_dispatch CI/CD: remember-core publish triggers remember-mcp bump + publish.
|
|
1081
|
+
Draft workflow files already created in both repos (not yet committed).
|
|
1082
|
+
|
|
1073
1083
|
documentation:
|
|
1074
1084
|
design_documents: 31
|
|
1075
1085
|
milestone_documents: 14
|
|
1076
1086
|
pattern_documents: 7
|
|
1077
|
-
task_documents:
|
|
1087
|
+
task_documents: 92
|
|
1078
1088
|
|
|
1079
1089
|
progress:
|
|
1080
1090
|
planning: 100%
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Task 201: Auto-bump remember-core via GitHub Actions
|
|
2
|
+
|
|
3
|
+
**Milestone**: Unassigned
|
|
4
|
+
**Estimated Time**: 1-2 hours
|
|
5
|
+
**Dependencies**: None
|
|
6
|
+
**Status**: Not Started
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Objective
|
|
11
|
+
|
|
12
|
+
Set up GitHub Actions CI/CD so that when remember-core publishes a new version to npm, remember-mcp automatically bumps the dependency, patches its own version, and publishes to npm.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Context
|
|
17
|
+
|
|
18
|
+
Currently, bumping remember-core in remember-mcp is a manual process: update package.json, commit, tag, publish. This happens frequently (almost every remember-core release). Automating this eliminates toil and reduces lag between core changes and MCP availability.
|
|
19
|
+
|
|
20
|
+
The approach uses `repository_dispatch` events: remember-core's publish workflow notifies remember-mcp after a successful npm publish, and remember-mcp's workflow handles the bump + publish.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
### 1. Configure GitHub Secrets
|
|
27
|
+
|
|
28
|
+
Add required secrets to both repositories:
|
|
29
|
+
|
|
30
|
+
- **remember-core**: `REPO_DISPATCH_TOKEN` - a GitHub PAT with `repo` scope (to trigger dispatches on remember-mcp)
|
|
31
|
+
- **remember-mcp**: `NPM_TOKEN` - an npm access token for publishing
|
|
32
|
+
|
|
33
|
+
### 2. Add dispatch step to remember-core publish workflow
|
|
34
|
+
|
|
35
|
+
File: `remember-core/.github/workflows/publish.yml`
|
|
36
|
+
|
|
37
|
+
A "Notify remember-mcp" step has been drafted that sends a `repository_dispatch` event after successful npm publish. Review and merge.
|
|
38
|
+
|
|
39
|
+
### 3. Add bump workflow to remember-mcp
|
|
40
|
+
|
|
41
|
+
File: `remember-mcp/.github/workflows/bump-remember-core.yml`
|
|
42
|
+
|
|
43
|
+
A workflow has been drafted that:
|
|
44
|
+
- Triggers on `repository_dispatch` with `dependency-update` type
|
|
45
|
+
- Filters to `@prmichaelsen/remember-core` events
|
|
46
|
+
- Installs the new version
|
|
47
|
+
- Patch-bumps remember-mcp version
|
|
48
|
+
- Commits (`bump: remember core` then `{version}`)
|
|
49
|
+
- Tags and pushes
|
|
50
|
+
- Publishes to npm
|
|
51
|
+
|
|
52
|
+
### 4. Fix remember-mcp git remote
|
|
53
|
+
|
|
54
|
+
The remember-mcp git remote currently points to `remember-core.git` instead of `remember-mcp.git`. Fix with:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git remote set-url origin git@github.com:prmichaelsen/remember-mcp.git
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 5. Test end-to-end
|
|
61
|
+
|
|
62
|
+
- Push a version bump to remember-core main
|
|
63
|
+
- Verify remember-core publishes to npm
|
|
64
|
+
- Verify dispatch fires
|
|
65
|
+
- Verify remember-mcp bumps, commits, tags, publishes
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Verification
|
|
70
|
+
|
|
71
|
+
- [ ] `REPO_DISPATCH_TOKEN` secret set in remember-core
|
|
72
|
+
- [ ] `NPM_TOKEN` secret set in remember-mcp
|
|
73
|
+
- [ ] remember-core publish.yml includes dispatch step
|
|
74
|
+
- [ ] remember-mcp bump-remember-core.yml exists
|
|
75
|
+
- [ ] remember-mcp git remote points to correct repo
|
|
76
|
+
- [ ] End-to-end test: remember-core publish triggers remember-mcp bump + publish
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Notes
|
|
81
|
+
|
|
82
|
+
- Draft workflow files already created in both repos (not yet committed)
|
|
83
|
+
- remember-core publish.yml already has NPM_TOKEN configured
|
|
84
|
+
- The bump workflow commits in the existing pattern: `bump: remember core` then `{version}`
|
|
85
|
+
- Consider adding error notifications (GitHub Actions failure emails are on by default)
|
package/dist/server-factory.js
CHANGED
|
@@ -803,6 +803,64 @@ function handleToolError(error, context) {
|
|
|
803
803
|
throw new Error(detailedMessage);
|
|
804
804
|
}
|
|
805
805
|
|
|
806
|
+
// node_modules/@prmichaelsen/remember-core/dist/types/trust.types.js
|
|
807
|
+
var TrustLevel = {
|
|
808
|
+
/** Anyone can see this, including strangers */
|
|
809
|
+
PUBLIC: 1,
|
|
810
|
+
/** Friends and known users */
|
|
811
|
+
INTERNAL: 2,
|
|
812
|
+
/** Trusted friends only */
|
|
813
|
+
CONFIDENTIAL: 3,
|
|
814
|
+
/** Close/intimate contacts only */
|
|
815
|
+
RESTRICTED: 4,
|
|
816
|
+
/** Owner only (or explicitly granted) */
|
|
817
|
+
SECRET: 5
|
|
818
|
+
};
|
|
819
|
+
var TRUST_LABELS = {
|
|
820
|
+
[TrustLevel.PUBLIC]: "Public",
|
|
821
|
+
[TrustLevel.INTERNAL]: "Internal",
|
|
822
|
+
[TrustLevel.CONFIDENTIAL]: "Confidential",
|
|
823
|
+
[TrustLevel.RESTRICTED]: "Restricted",
|
|
824
|
+
[TrustLevel.SECRET]: "Secret"
|
|
825
|
+
};
|
|
826
|
+
var ALL_TRUST_LEVELS = [
|
|
827
|
+
TrustLevel.PUBLIC,
|
|
828
|
+
TrustLevel.INTERNAL,
|
|
829
|
+
TrustLevel.CONFIDENTIAL,
|
|
830
|
+
TrustLevel.RESTRICTED,
|
|
831
|
+
TrustLevel.SECRET
|
|
832
|
+
];
|
|
833
|
+
function isValidTrustLevel(value) {
|
|
834
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 5;
|
|
835
|
+
}
|
|
836
|
+
function normalizeTrustScore(value) {
|
|
837
|
+
if (value == null)
|
|
838
|
+
return TrustLevel.INTERNAL;
|
|
839
|
+
if (isValidTrustLevel(value))
|
|
840
|
+
return value;
|
|
841
|
+
const inverted = 1 - value;
|
|
842
|
+
if (inverted >= 0.875)
|
|
843
|
+
return TrustLevel.SECRET;
|
|
844
|
+
if (inverted >= 0.625)
|
|
845
|
+
return TrustLevel.RESTRICTED;
|
|
846
|
+
if (inverted >= 0.375)
|
|
847
|
+
return TrustLevel.CONFIDENTIAL;
|
|
848
|
+
if (inverted >= 0.125)
|
|
849
|
+
return TrustLevel.INTERNAL;
|
|
850
|
+
return TrustLevel.PUBLIC;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// node_modules/@prmichaelsen/remember-core/dist/types/ghost-config.types.js
|
|
854
|
+
var DEFAULT_GHOST_CONFIG = {
|
|
855
|
+
enabled: false,
|
|
856
|
+
public_ghost_enabled: false,
|
|
857
|
+
default_friend_trust: TrustLevel.INTERNAL,
|
|
858
|
+
default_public_trust: TrustLevel.PUBLIC,
|
|
859
|
+
per_user_trust: {},
|
|
860
|
+
blocked_users: [],
|
|
861
|
+
enforcement_mode: "query"
|
|
862
|
+
};
|
|
863
|
+
|
|
806
864
|
// node_modules/@prmichaelsen/remember-core/dist/types/preferences.types.js
|
|
807
865
|
var DEFAULT_PREFERENCES = {
|
|
808
866
|
templates: {
|
|
@@ -1582,6 +1640,9 @@ function buildDocTypeFilters(collection, docType, filters) {
|
|
|
1582
1640
|
if (filters?.tags && filters.tags.length > 0) {
|
|
1583
1641
|
filterList.push(collection.filter.byProperty("tags").containsAny(filters.tags));
|
|
1584
1642
|
}
|
|
1643
|
+
if (filters?.memory_ids && filters.memory_ids.length > 0) {
|
|
1644
|
+
filterList.push(collection.filter.byId().containsAny(filters.memory_ids));
|
|
1645
|
+
}
|
|
1585
1646
|
return combineFiltersWithAnd(filterList);
|
|
1586
1647
|
}
|
|
1587
1648
|
function buildMemoryOnlyFilters(collection, filters) {
|
|
@@ -1988,14 +2049,22 @@ function buildTrustFilter(collection, accessorTrustLevel) {
|
|
|
1988
2049
|
}
|
|
1989
2050
|
|
|
1990
2051
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
2052
|
+
function normalizeDoc(doc) {
|
|
2053
|
+
if ("trust_score" in doc) {
|
|
2054
|
+
doc.trust_score = normalizeTrustScore(doc.trust_score);
|
|
2055
|
+
}
|
|
2056
|
+
return doc;
|
|
2057
|
+
}
|
|
1991
2058
|
var MemoryService = class {
|
|
1992
2059
|
collection;
|
|
1993
2060
|
userId;
|
|
1994
2061
|
logger;
|
|
1995
|
-
|
|
2062
|
+
options;
|
|
2063
|
+
constructor(collection, userId, logger2, options) {
|
|
1996
2064
|
this.collection = collection;
|
|
1997
2065
|
this.userId = userId;
|
|
1998
2066
|
this.logger = logger2;
|
|
2067
|
+
this.options = options;
|
|
1999
2068
|
}
|
|
2000
2069
|
/**
|
|
2001
2070
|
* Execute a search function, retrying without the deleted_at filter if
|
|
@@ -2018,7 +2087,31 @@ var MemoryService = class {
|
|
|
2018
2087
|
throw new Error(`Memory not found: ${memoryId}`);
|
|
2019
2088
|
if (existing.properties.user_id !== this.userId)
|
|
2020
2089
|
throw new Error("Unauthorized");
|
|
2021
|
-
return { memory: { id: existing.uuid, ...existing.properties } };
|
|
2090
|
+
return { memory: normalizeDoc({ id: existing.uuid, ...existing.properties }) };
|
|
2091
|
+
}
|
|
2092
|
+
// ── Resolve by ID (cross-collection) ─────────────────────────────────
|
|
2093
|
+
/**
|
|
2094
|
+
* Resolve any memory by UUID alone using the Firestore index.
|
|
2095
|
+
* Requires `memoryIndex` and `weaviateClient` in constructor options.
|
|
2096
|
+
*/
|
|
2097
|
+
async resolveById(memoryId) {
|
|
2098
|
+
if (!this.options?.weaviateClient) {
|
|
2099
|
+
throw new Error("resolveById requires weaviateClient in options");
|
|
2100
|
+
}
|
|
2101
|
+
if (this.options?.memoryIndex) {
|
|
2102
|
+
const collectionName = await this.options.memoryIndex.lookup(memoryId);
|
|
2103
|
+
if (collectionName) {
|
|
2104
|
+
const col = this.options.weaviateClient.collections.get(collectionName);
|
|
2105
|
+
const memory = await fetchMemoryWithAllProperties(col, memoryId);
|
|
2106
|
+
if (memory?.properties) {
|
|
2107
|
+
return {
|
|
2108
|
+
memory: normalizeDoc({ id: memory.uuid, ...memory.properties }),
|
|
2109
|
+
collectionName
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
return { memory: null, collectionName: null };
|
|
2022
2115
|
}
|
|
2023
2116
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2024
2117
|
async create(input) {
|
|
@@ -2032,7 +2125,7 @@ var MemoryService = class {
|
|
|
2032
2125
|
summary: input.title,
|
|
2033
2126
|
content_type: contentType,
|
|
2034
2127
|
weight: input.weight ?? 0.5,
|
|
2035
|
-
trust_score: input.trust ??
|
|
2128
|
+
trust_score: input.trust ?? TrustLevel.INTERNAL,
|
|
2036
2129
|
confidence: 1,
|
|
2037
2130
|
context_summary: input.context_summary || "Memory created",
|
|
2038
2131
|
context_conversation_id: input.context_conversation_id,
|
|
@@ -2057,6 +2150,14 @@ var MemoryService = class {
|
|
|
2057
2150
|
};
|
|
2058
2151
|
const memoryId = await this.collection.data.insert({ properties });
|
|
2059
2152
|
this.logger.info("Memory created", { memoryId, userId: this.userId });
|
|
2153
|
+
if (this.options?.memoryIndex) {
|
|
2154
|
+
try {
|
|
2155
|
+
const collectionName = this.collection.name;
|
|
2156
|
+
await this.options.memoryIndex.index(memoryId, collectionName);
|
|
2157
|
+
} catch (err2) {
|
|
2158
|
+
this.logger.warn?.(`[MemoryService] Index write failed for ${memoryId}: ${err2}`);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2060
2161
|
return { memory_id: memoryId, created_at: now };
|
|
2061
2162
|
}
|
|
2062
2163
|
// ── Search (hybrid) ─────────────────────────────────────────────────
|
|
@@ -2094,7 +2195,7 @@ var MemoryService = class {
|
|
|
2094
2195
|
const memories = [];
|
|
2095
2196
|
const relationships = [];
|
|
2096
2197
|
for (const obj of paginated) {
|
|
2097
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2198
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2098
2199
|
if (doc.doc_type === "memory")
|
|
2099
2200
|
memories.push(doc);
|
|
2100
2201
|
else if (doc.doc_type === "relationship")
|
|
@@ -2137,7 +2238,7 @@ var MemoryService = class {
|
|
|
2137
2238
|
const paginated = results.objects.slice(offset);
|
|
2138
2239
|
const memories = [];
|
|
2139
2240
|
for (const obj of paginated) {
|
|
2140
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2241
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2141
2242
|
if (doc.doc_type === "memory") {
|
|
2142
2243
|
memories.push(doc);
|
|
2143
2244
|
}
|
|
@@ -2181,7 +2282,7 @@ var MemoryService = class {
|
|
|
2181
2282
|
const paginated = results.objects.slice(offset);
|
|
2182
2283
|
const memories = [];
|
|
2183
2284
|
for (const obj of paginated) {
|
|
2184
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2285
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2185
2286
|
if (doc.doc_type === "memory") {
|
|
2186
2287
|
memories.push(doc);
|
|
2187
2288
|
}
|
|
@@ -2240,7 +2341,7 @@ var MemoryService = class {
|
|
|
2240
2341
|
if (!input.include_relationships) {
|
|
2241
2342
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
2242
2343
|
}
|
|
2243
|
-
const items = results.objects.map((obj) => ({
|
|
2344
|
+
const items = results.objects.map((obj) => normalizeDoc({
|
|
2244
2345
|
id: obj.uuid,
|
|
2245
2346
|
...obj.properties,
|
|
2246
2347
|
similarity: Math.max(0, Math.min(1, 1 - (obj.metadata?.distance ?? 0)))
|
|
@@ -2269,7 +2370,7 @@ var MemoryService = class {
|
|
|
2269
2370
|
opts.filters = combinedFilters;
|
|
2270
2371
|
return this.collection.query.nearText(input.query, opts);
|
|
2271
2372
|
});
|
|
2272
|
-
const items = results.objects.map((obj) => ({
|
|
2373
|
+
const items = results.objects.map((obj) => normalizeDoc({
|
|
2273
2374
|
id: obj.uuid,
|
|
2274
2375
|
...obj.properties,
|
|
2275
2376
|
relevance: Math.max(0, Math.min(1, 1 - (obj.metadata?.distance ?? 0)))
|
|
@@ -2313,8 +2414,8 @@ var MemoryService = class {
|
|
|
2313
2414
|
updatedFields.push("weight");
|
|
2314
2415
|
}
|
|
2315
2416
|
if (input.trust !== void 0) {
|
|
2316
|
-
if (input.trust
|
|
2317
|
-
throw new Error("Trust must be between
|
|
2417
|
+
if (!isValidTrustLevel(input.trust))
|
|
2418
|
+
throw new Error("Trust must be an integer between 1 and 5");
|
|
2318
2419
|
updates.trust_score = input.trust;
|
|
2319
2420
|
updatedFields.push("trust_score");
|
|
2320
2421
|
}
|
package/dist/server.js
CHANGED
|
@@ -807,6 +807,64 @@ function handleToolError(error, context) {
|
|
|
807
807
|
throw new Error(detailedMessage);
|
|
808
808
|
}
|
|
809
809
|
|
|
810
|
+
// node_modules/@prmichaelsen/remember-core/dist/types/trust.types.js
|
|
811
|
+
var TrustLevel = {
|
|
812
|
+
/** Anyone can see this, including strangers */
|
|
813
|
+
PUBLIC: 1,
|
|
814
|
+
/** Friends and known users */
|
|
815
|
+
INTERNAL: 2,
|
|
816
|
+
/** Trusted friends only */
|
|
817
|
+
CONFIDENTIAL: 3,
|
|
818
|
+
/** Close/intimate contacts only */
|
|
819
|
+
RESTRICTED: 4,
|
|
820
|
+
/** Owner only (or explicitly granted) */
|
|
821
|
+
SECRET: 5
|
|
822
|
+
};
|
|
823
|
+
var TRUST_LABELS = {
|
|
824
|
+
[TrustLevel.PUBLIC]: "Public",
|
|
825
|
+
[TrustLevel.INTERNAL]: "Internal",
|
|
826
|
+
[TrustLevel.CONFIDENTIAL]: "Confidential",
|
|
827
|
+
[TrustLevel.RESTRICTED]: "Restricted",
|
|
828
|
+
[TrustLevel.SECRET]: "Secret"
|
|
829
|
+
};
|
|
830
|
+
var ALL_TRUST_LEVELS = [
|
|
831
|
+
TrustLevel.PUBLIC,
|
|
832
|
+
TrustLevel.INTERNAL,
|
|
833
|
+
TrustLevel.CONFIDENTIAL,
|
|
834
|
+
TrustLevel.RESTRICTED,
|
|
835
|
+
TrustLevel.SECRET
|
|
836
|
+
];
|
|
837
|
+
function isValidTrustLevel(value) {
|
|
838
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 5;
|
|
839
|
+
}
|
|
840
|
+
function normalizeTrustScore(value) {
|
|
841
|
+
if (value == null)
|
|
842
|
+
return TrustLevel.INTERNAL;
|
|
843
|
+
if (isValidTrustLevel(value))
|
|
844
|
+
return value;
|
|
845
|
+
const inverted = 1 - value;
|
|
846
|
+
if (inverted >= 0.875)
|
|
847
|
+
return TrustLevel.SECRET;
|
|
848
|
+
if (inverted >= 0.625)
|
|
849
|
+
return TrustLevel.RESTRICTED;
|
|
850
|
+
if (inverted >= 0.375)
|
|
851
|
+
return TrustLevel.CONFIDENTIAL;
|
|
852
|
+
if (inverted >= 0.125)
|
|
853
|
+
return TrustLevel.INTERNAL;
|
|
854
|
+
return TrustLevel.PUBLIC;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// node_modules/@prmichaelsen/remember-core/dist/types/ghost-config.types.js
|
|
858
|
+
var DEFAULT_GHOST_CONFIG = {
|
|
859
|
+
enabled: false,
|
|
860
|
+
public_ghost_enabled: false,
|
|
861
|
+
default_friend_trust: TrustLevel.INTERNAL,
|
|
862
|
+
default_public_trust: TrustLevel.PUBLIC,
|
|
863
|
+
per_user_trust: {},
|
|
864
|
+
blocked_users: [],
|
|
865
|
+
enforcement_mode: "query"
|
|
866
|
+
};
|
|
867
|
+
|
|
810
868
|
// node_modules/@prmichaelsen/remember-core/dist/types/preferences.types.js
|
|
811
869
|
var DEFAULT_PREFERENCES = {
|
|
812
870
|
templates: {
|
|
@@ -1586,6 +1644,9 @@ function buildDocTypeFilters(collection, docType, filters) {
|
|
|
1586
1644
|
if (filters?.tags && filters.tags.length > 0) {
|
|
1587
1645
|
filterList.push(collection.filter.byProperty("tags").containsAny(filters.tags));
|
|
1588
1646
|
}
|
|
1647
|
+
if (filters?.memory_ids && filters.memory_ids.length > 0) {
|
|
1648
|
+
filterList.push(collection.filter.byId().containsAny(filters.memory_ids));
|
|
1649
|
+
}
|
|
1589
1650
|
return combineFiltersWithAnd(filterList);
|
|
1590
1651
|
}
|
|
1591
1652
|
function buildMemoryOnlyFilters(collection, filters) {
|
|
@@ -1992,14 +2053,22 @@ function buildTrustFilter(collection, accessorTrustLevel) {
|
|
|
1992
2053
|
}
|
|
1993
2054
|
|
|
1994
2055
|
// node_modules/@prmichaelsen/remember-core/dist/services/memory.service.js
|
|
2056
|
+
function normalizeDoc(doc) {
|
|
2057
|
+
if ("trust_score" in doc) {
|
|
2058
|
+
doc.trust_score = normalizeTrustScore(doc.trust_score);
|
|
2059
|
+
}
|
|
2060
|
+
return doc;
|
|
2061
|
+
}
|
|
1995
2062
|
var MemoryService = class {
|
|
1996
2063
|
collection;
|
|
1997
2064
|
userId;
|
|
1998
2065
|
logger;
|
|
1999
|
-
|
|
2066
|
+
options;
|
|
2067
|
+
constructor(collection, userId, logger2, options) {
|
|
2000
2068
|
this.collection = collection;
|
|
2001
2069
|
this.userId = userId;
|
|
2002
2070
|
this.logger = logger2;
|
|
2071
|
+
this.options = options;
|
|
2003
2072
|
}
|
|
2004
2073
|
/**
|
|
2005
2074
|
* Execute a search function, retrying without the deleted_at filter if
|
|
@@ -2022,7 +2091,31 @@ var MemoryService = class {
|
|
|
2022
2091
|
throw new Error(`Memory not found: ${memoryId}`);
|
|
2023
2092
|
if (existing.properties.user_id !== this.userId)
|
|
2024
2093
|
throw new Error("Unauthorized");
|
|
2025
|
-
return { memory: { id: existing.uuid, ...existing.properties } };
|
|
2094
|
+
return { memory: normalizeDoc({ id: existing.uuid, ...existing.properties }) };
|
|
2095
|
+
}
|
|
2096
|
+
// ── Resolve by ID (cross-collection) ─────────────────────────────────
|
|
2097
|
+
/**
|
|
2098
|
+
* Resolve any memory by UUID alone using the Firestore index.
|
|
2099
|
+
* Requires `memoryIndex` and `weaviateClient` in constructor options.
|
|
2100
|
+
*/
|
|
2101
|
+
async resolveById(memoryId) {
|
|
2102
|
+
if (!this.options?.weaviateClient) {
|
|
2103
|
+
throw new Error("resolveById requires weaviateClient in options");
|
|
2104
|
+
}
|
|
2105
|
+
if (this.options?.memoryIndex) {
|
|
2106
|
+
const collectionName = await this.options.memoryIndex.lookup(memoryId);
|
|
2107
|
+
if (collectionName) {
|
|
2108
|
+
const col = this.options.weaviateClient.collections.get(collectionName);
|
|
2109
|
+
const memory = await fetchMemoryWithAllProperties(col, memoryId);
|
|
2110
|
+
if (memory?.properties) {
|
|
2111
|
+
return {
|
|
2112
|
+
memory: normalizeDoc({ id: memory.uuid, ...memory.properties }),
|
|
2113
|
+
collectionName
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
return { memory: null, collectionName: null };
|
|
2026
2119
|
}
|
|
2027
2120
|
// ── Create ──────────────────────────────────────────────────────────
|
|
2028
2121
|
async create(input) {
|
|
@@ -2036,7 +2129,7 @@ var MemoryService = class {
|
|
|
2036
2129
|
summary: input.title,
|
|
2037
2130
|
content_type: contentType,
|
|
2038
2131
|
weight: input.weight ?? 0.5,
|
|
2039
|
-
trust_score: input.trust ??
|
|
2132
|
+
trust_score: input.trust ?? TrustLevel.INTERNAL,
|
|
2040
2133
|
confidence: 1,
|
|
2041
2134
|
context_summary: input.context_summary || "Memory created",
|
|
2042
2135
|
context_conversation_id: input.context_conversation_id,
|
|
@@ -2061,6 +2154,14 @@ var MemoryService = class {
|
|
|
2061
2154
|
};
|
|
2062
2155
|
const memoryId = await this.collection.data.insert({ properties });
|
|
2063
2156
|
this.logger.info("Memory created", { memoryId, userId: this.userId });
|
|
2157
|
+
if (this.options?.memoryIndex) {
|
|
2158
|
+
try {
|
|
2159
|
+
const collectionName = this.collection.name;
|
|
2160
|
+
await this.options.memoryIndex.index(memoryId, collectionName);
|
|
2161
|
+
} catch (err2) {
|
|
2162
|
+
this.logger.warn?.(`[MemoryService] Index write failed for ${memoryId}: ${err2}`);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2064
2165
|
return { memory_id: memoryId, created_at: now };
|
|
2065
2166
|
}
|
|
2066
2167
|
// ── Search (hybrid) ─────────────────────────────────────────────────
|
|
@@ -2098,7 +2199,7 @@ var MemoryService = class {
|
|
|
2098
2199
|
const memories = [];
|
|
2099
2200
|
const relationships = [];
|
|
2100
2201
|
for (const obj of paginated) {
|
|
2101
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2202
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2102
2203
|
if (doc.doc_type === "memory")
|
|
2103
2204
|
memories.push(doc);
|
|
2104
2205
|
else if (doc.doc_type === "relationship")
|
|
@@ -2141,7 +2242,7 @@ var MemoryService = class {
|
|
|
2141
2242
|
const paginated = results.objects.slice(offset);
|
|
2142
2243
|
const memories = [];
|
|
2143
2244
|
for (const obj of paginated) {
|
|
2144
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2245
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2145
2246
|
if (doc.doc_type === "memory") {
|
|
2146
2247
|
memories.push(doc);
|
|
2147
2248
|
}
|
|
@@ -2185,7 +2286,7 @@ var MemoryService = class {
|
|
|
2185
2286
|
const paginated = results.objects.slice(offset);
|
|
2186
2287
|
const memories = [];
|
|
2187
2288
|
for (const obj of paginated) {
|
|
2188
|
-
const doc = { id: obj.uuid, ...obj.properties };
|
|
2289
|
+
const doc = normalizeDoc({ id: obj.uuid, ...obj.properties });
|
|
2189
2290
|
if (doc.doc_type === "memory") {
|
|
2190
2291
|
memories.push(doc);
|
|
2191
2292
|
}
|
|
@@ -2244,7 +2345,7 @@ var MemoryService = class {
|
|
|
2244
2345
|
if (!input.include_relationships) {
|
|
2245
2346
|
results.objects = results.objects.filter((o) => o.properties.doc_type === "memory");
|
|
2246
2347
|
}
|
|
2247
|
-
const items = results.objects.map((obj) => ({
|
|
2348
|
+
const items = results.objects.map((obj) => normalizeDoc({
|
|
2248
2349
|
id: obj.uuid,
|
|
2249
2350
|
...obj.properties,
|
|
2250
2351
|
similarity: Math.max(0, Math.min(1, 1 - (obj.metadata?.distance ?? 0)))
|
|
@@ -2273,7 +2374,7 @@ var MemoryService = class {
|
|
|
2273
2374
|
opts.filters = combinedFilters;
|
|
2274
2375
|
return this.collection.query.nearText(input.query, opts);
|
|
2275
2376
|
});
|
|
2276
|
-
const items = results.objects.map((obj) => ({
|
|
2377
|
+
const items = results.objects.map((obj) => normalizeDoc({
|
|
2277
2378
|
id: obj.uuid,
|
|
2278
2379
|
...obj.properties,
|
|
2279
2380
|
relevance: Math.max(0, Math.min(1, 1 - (obj.metadata?.distance ?? 0)))
|
|
@@ -2317,8 +2418,8 @@ var MemoryService = class {
|
|
|
2317
2418
|
updatedFields.push("weight");
|
|
2318
2419
|
}
|
|
2319
2420
|
if (input.trust !== void 0) {
|
|
2320
|
-
if (input.trust
|
|
2321
|
-
throw new Error("Trust must be between
|
|
2421
|
+
if (!isValidTrustLevel(input.trust))
|
|
2422
|
+
throw new Error("Trust must be an integer between 1 and 5");
|
|
2322
2423
|
updates.trust_score = input.trust;
|
|
2323
2424
|
updatedFields.push("trust_score");
|
|
2324
2425
|
}
|
package/esbuild.build.js
CHANGED
|
@@ -13,7 +13,10 @@ await esbuild.build({
|
|
|
13
13
|
external: [
|
|
14
14
|
'weaviate-client',
|
|
15
15
|
'@prmichaelsen/firebase-admin-sdk-v8',
|
|
16
|
-
'@modelcontextprotocol/sdk'
|
|
16
|
+
'@modelcontextprotocol/sdk',
|
|
17
|
+
'unpdf',
|
|
18
|
+
'mammoth',
|
|
19
|
+
'turndown',
|
|
17
20
|
],
|
|
18
21
|
banner: {
|
|
19
22
|
js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
|
|
@@ -35,7 +38,10 @@ await esbuild.build({
|
|
|
35
38
|
external: [
|
|
36
39
|
'weaviate-client',
|
|
37
40
|
'@prmichaelsen/firebase-admin-sdk-v8',
|
|
38
|
-
'@modelcontextprotocol/sdk'
|
|
41
|
+
'@modelcontextprotocol/sdk',
|
|
42
|
+
'unpdf',
|
|
43
|
+
'mammoth',
|
|
44
|
+
'turndown',
|
|
39
45
|
],
|
|
40
46
|
banner: {
|
|
41
47
|
js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prmichaelsen/remember-mcp",
|
|
3
|
-
"version": "3.14.
|
|
3
|
+
"version": "3.14.19",
|
|
4
4
|
"description": "Multi-tenant memory system MCP server with vector search and relationships",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
51
51
|
"@prmichaelsen/firebase-admin-sdk-v8": "^2.2.0",
|
|
52
52
|
"@prmichaelsen/mcp-auth": "^7.0.4",
|
|
53
|
-
"@prmichaelsen/remember-core": "^0.
|
|
53
|
+
"@prmichaelsen/remember-core": "^0.30.0",
|
|
54
54
|
"dotenv": "^16.4.5",
|
|
55
55
|
"uuid": "^13.0.0",
|
|
56
56
|
"weaviate-client": "^3.2.0"
|