@prmichaelsen/remember-mcp 2.6.2 → 2.6.4
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 +61 -0
- package/agent/progress.yaml +163 -13
- package/agent/tasks/task-62-fix-confirmation-response-storage.md +323 -0
- package/agent/tasks/task-63-fix-fetchobjectbyid-missing-properties.md +397 -0
- package/agent/tasks/task-64-prevent-implicit-content-type-filtering.md +289 -0
- package/dist/server-factory.js +67 -6
- package/dist/server.js +67 -6
- package/dist/weaviate/client.d.ts +16 -0
- package/package.json +1 -1
- package/src/tools/confirm.ts +7 -2
- package/src/tools/publish.ts +6 -2
- package/src/tools/query-memory.ts +5 -0
- package/src/tools/query-space.ts +8 -1
- package/src/tools/search-memory.ts +5 -0
- package/src/tools/search-space.ts +8 -1
- package/src/weaviate/client.ts +47 -0
package/dist/server-factory.js
CHANGED
|
@@ -565,6 +565,34 @@ function sanitizeUserId(userId) {
|
|
|
565
565
|
function getMemoryCollectionName(userId) {
|
|
566
566
|
return `Memory_${sanitizeUserId(userId)}`;
|
|
567
567
|
}
|
|
568
|
+
var ALL_MEMORY_PROPERTIES = [
|
|
569
|
+
"user_id",
|
|
570
|
+
"doc_type",
|
|
571
|
+
"type",
|
|
572
|
+
"title",
|
|
573
|
+
"content",
|
|
574
|
+
"tags",
|
|
575
|
+
"weight",
|
|
576
|
+
"base_weight",
|
|
577
|
+
"trust_level",
|
|
578
|
+
"context",
|
|
579
|
+
"location",
|
|
580
|
+
"relationships",
|
|
581
|
+
"created_at",
|
|
582
|
+
"updated_at",
|
|
583
|
+
"version",
|
|
584
|
+
"attribution",
|
|
585
|
+
"source_url",
|
|
586
|
+
"author",
|
|
587
|
+
"parent_id",
|
|
588
|
+
"thread_root_id",
|
|
589
|
+
"moderation_flags"
|
|
590
|
+
];
|
|
591
|
+
async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
592
|
+
return await collection.query.fetchObjectById(memoryId, {
|
|
593
|
+
returnProperties: ALL_MEMORY_PROPERTIES
|
|
594
|
+
});
|
|
595
|
+
}
|
|
568
596
|
|
|
569
597
|
// src/firestore/init.ts
|
|
570
598
|
init_config();
|
|
@@ -1542,6 +1570,11 @@ var searchMemoryTool = {
|
|
|
1542
1570
|
- "Show me notes from last week" \u2192 returns notes + any relationships created that week
|
|
1543
1571
|
|
|
1544
1572
|
**AGENT GUIDANCE**:
|
|
1573
|
+
- \u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
1574
|
+
* \u2705 CORRECT: User says "search for hiking" \u2192 { query: "hiking" }
|
|
1575
|
+
* \u274C WRONG: User says "search for hiking" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
1576
|
+
* \u2705 CORRECT: User says "search for note memories about hiking" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
1577
|
+
* Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
1545
1578
|
- If search results are too narrow or miss relevant content, try remember_query_memory instead - it uses pure semantic search which is better for broader, concept-based queries. You can inform the user: "I didn't find what you're looking for with keyword search. Let me try a broader semantic search using the query tool."
|
|
1546
1579
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
1547
1580
|
* Create a new memory with the information they're looking for
|
|
@@ -2112,6 +2145,11 @@ var queryMemoryTool = {
|
|
|
2112
2145
|
- "What are my project goals?"
|
|
2113
2146
|
|
|
2114
2147
|
**AGENT GUIDANCE**:
|
|
2148
|
+
- \u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
2149
|
+
* \u2705 CORRECT: User says "what do I know about hiking?" \u2192 { query: "hiking" }
|
|
2150
|
+
* \u274C WRONG: User says "what do I know about hiking?" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
2151
|
+
* \u2705 CORRECT: User says "what notes do I have about hiking?" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
2152
|
+
* Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
2115
2153
|
- If query results are too broad or include irrelevant content, try remember_search_memory instead - it uses hybrid search with keyword matching which is better for precise, specific searches. You can inform the user: "The results were too broad. Let me try a more precise keyword search using the search tool."
|
|
2116
2154
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
2117
2155
|
* Create a new memory with the information they're looking for
|
|
@@ -3833,11 +3871,15 @@ async function handlePublish(args, userId) {
|
|
|
3833
3871
|
memoryId: args.memory_id
|
|
3834
3872
|
});
|
|
3835
3873
|
const userCollection = weaviateClient.collections.get(collectionName);
|
|
3836
|
-
const memory = await userCollection
|
|
3874
|
+
const memory = await fetchMemoryWithAllProperties(userCollection, args.memory_id);
|
|
3837
3875
|
logger.debug("Memory fetch result", {
|
|
3838
3876
|
tool: "remember_publish",
|
|
3839
3877
|
found: !!memory,
|
|
3840
|
-
memoryId: args.memory_id
|
|
3878
|
+
memoryId: args.memory_id,
|
|
3879
|
+
hasProperties: !!memory?.properties,
|
|
3880
|
+
propertyCount: memory?.properties ? Object.keys(memory.properties).length : 0,
|
|
3881
|
+
hasTitle: !!memory?.properties?.title,
|
|
3882
|
+
hasContent: !!memory?.properties?.content
|
|
3841
3883
|
});
|
|
3842
3884
|
if (!memory) {
|
|
3843
3885
|
logger.info("Memory not found", {
|
|
@@ -4024,13 +4066,18 @@ async function executePublishMemory(request, userId) {
|
|
|
4024
4066
|
collectionName: getMemoryCollectionName(userId),
|
|
4025
4067
|
memoryId: request.payload.memory_id
|
|
4026
4068
|
});
|
|
4027
|
-
const originalMemory = await
|
|
4069
|
+
const originalMemory = await fetchMemoryWithAllProperties(
|
|
4070
|
+
userCollection,
|
|
4028
4071
|
request.payload.memory_id
|
|
4029
4072
|
);
|
|
4030
4073
|
logger.debug("Original memory fetch result", {
|
|
4031
4074
|
function: "executePublishMemory",
|
|
4032
4075
|
found: !!originalMemory,
|
|
4033
|
-
memoryId: request.payload.memory_id
|
|
4076
|
+
memoryId: request.payload.memory_id,
|
|
4077
|
+
hasProperties: !!originalMemory?.properties,
|
|
4078
|
+
propertyCount: originalMemory?.properties ? Object.keys(originalMemory.properties).length : 0,
|
|
4079
|
+
hasTitle: !!originalMemory?.properties?.title,
|
|
4080
|
+
hasContent: !!originalMemory?.properties?.content
|
|
4034
4081
|
});
|
|
4035
4082
|
if (!originalMemory) {
|
|
4036
4083
|
logger.info("Original memory not found", {
|
|
@@ -4186,7 +4233,14 @@ import { Filters as Filters3 } from "weaviate-client";
|
|
|
4186
4233
|
init_space_memory();
|
|
4187
4234
|
var searchSpaceTool = {
|
|
4188
4235
|
name: "remember_search_space",
|
|
4189
|
-
description:
|
|
4236
|
+
description: `Search one or more shared spaces to discover thoughts, ideas, and memories. By default, excludes comments to keep discovery clean. Set include_comments: true to include threaded discussions. Can search multiple spaces in a single query.
|
|
4237
|
+
|
|
4238
|
+
\u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
4239
|
+
- \u2705 CORRECT: User says "search The Void for hiking" \u2192 { spaces: ["the_void"], query: "hiking" }
|
|
4240
|
+
- \u274C WRONG: User says "search The Void for hiking" \u2192 { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
4241
|
+
- \u2705 CORRECT: User says "search The Void for note memories about hiking" \u2192 { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
4242
|
+
|
|
4243
|
+
Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
4190
4244
|
inputSchema: {
|
|
4191
4245
|
type: "object",
|
|
4192
4246
|
properties: {
|
|
@@ -4345,7 +4399,14 @@ import { Filters as Filters4 } from "weaviate-client";
|
|
|
4345
4399
|
init_space_memory();
|
|
4346
4400
|
var querySpaceTool = {
|
|
4347
4401
|
name: "remember_query_space",
|
|
4348
|
-
description:
|
|
4402
|
+
description: `Ask natural language questions about memories in shared spaces. By default, excludes comments to focus on original content. Set include_comments: true to include discussions in answers.
|
|
4403
|
+
|
|
4404
|
+
\u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
4405
|
+
- \u2705 CORRECT: User says "what's in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking" }
|
|
4406
|
+
- \u274C WRONG: User says "what's in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
4407
|
+
- \u2705 CORRECT: User says "what notes are in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
4408
|
+
|
|
4409
|
+
Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
4349
4410
|
inputSchema: {
|
|
4350
4411
|
type: "object",
|
|
4351
4412
|
properties: {
|
package/dist/server.js
CHANGED
|
@@ -611,6 +611,34 @@ function sanitizeUserId(userId) {
|
|
|
611
611
|
function getMemoryCollectionName(userId) {
|
|
612
612
|
return `Memory_${sanitizeUserId(userId)}`;
|
|
613
613
|
}
|
|
614
|
+
var ALL_MEMORY_PROPERTIES = [
|
|
615
|
+
"user_id",
|
|
616
|
+
"doc_type",
|
|
617
|
+
"type",
|
|
618
|
+
"title",
|
|
619
|
+
"content",
|
|
620
|
+
"tags",
|
|
621
|
+
"weight",
|
|
622
|
+
"base_weight",
|
|
623
|
+
"trust_level",
|
|
624
|
+
"context",
|
|
625
|
+
"location",
|
|
626
|
+
"relationships",
|
|
627
|
+
"created_at",
|
|
628
|
+
"updated_at",
|
|
629
|
+
"version",
|
|
630
|
+
"attribution",
|
|
631
|
+
"source_url",
|
|
632
|
+
"author",
|
|
633
|
+
"parent_id",
|
|
634
|
+
"thread_root_id",
|
|
635
|
+
"moderation_flags"
|
|
636
|
+
];
|
|
637
|
+
async function fetchMemoryWithAllProperties(collection, memoryId) {
|
|
638
|
+
return await collection.query.fetchObjectById(memoryId, {
|
|
639
|
+
returnProperties: ALL_MEMORY_PROPERTIES
|
|
640
|
+
});
|
|
641
|
+
}
|
|
614
642
|
|
|
615
643
|
// src/firestore/init.ts
|
|
616
644
|
init_config();
|
|
@@ -1610,6 +1638,11 @@ var searchMemoryTool = {
|
|
|
1610
1638
|
- "Show me notes from last week" \u2192 returns notes + any relationships created that week
|
|
1611
1639
|
|
|
1612
1640
|
**AGENT GUIDANCE**:
|
|
1641
|
+
- \u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
1642
|
+
* \u2705 CORRECT: User says "search for hiking" \u2192 { query: "hiking" }
|
|
1643
|
+
* \u274C WRONG: User says "search for hiking" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
1644
|
+
* \u2705 CORRECT: User says "search for note memories about hiking" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
1645
|
+
* Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
1613
1646
|
- If search results are too narrow or miss relevant content, try remember_query_memory instead - it uses pure semantic search which is better for broader, concept-based queries. You can inform the user: "I didn't find what you're looking for with keyword search. Let me try a broader semantic search using the query tool."
|
|
1614
1647
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
1615
1648
|
* Create a new memory with the information they're looking for
|
|
@@ -2180,6 +2213,11 @@ var queryMemoryTool = {
|
|
|
2180
2213
|
- "What are my project goals?"
|
|
2181
2214
|
|
|
2182
2215
|
**AGENT GUIDANCE**:
|
|
2216
|
+
- \u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
2217
|
+
* \u2705 CORRECT: User says "what do I know about hiking?" \u2192 { query: "hiking" }
|
|
2218
|
+
* \u274C WRONG: User says "what do I know about hiking?" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
2219
|
+
* \u2705 CORRECT: User says "what notes do I have about hiking?" \u2192 { query: "hiking", filters: { types: ["note"] } }
|
|
2220
|
+
* Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
2183
2221
|
- If query results are too broad or include irrelevant content, try remember_search_memory instead - it uses hybrid search with keyword matching which is better for precise, specific searches. You can inform the user: "The results were too broad. Let me try a more precise keyword search using the search tool."
|
|
2184
2222
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
2185
2223
|
* Create a new memory with the information they're looking for
|
|
@@ -3901,11 +3939,15 @@ async function handlePublish(args, userId) {
|
|
|
3901
3939
|
memoryId: args.memory_id
|
|
3902
3940
|
});
|
|
3903
3941
|
const userCollection = weaviateClient.collections.get(collectionName);
|
|
3904
|
-
const memory = await userCollection
|
|
3942
|
+
const memory = await fetchMemoryWithAllProperties(userCollection, args.memory_id);
|
|
3905
3943
|
logger.debug("Memory fetch result", {
|
|
3906
3944
|
tool: "remember_publish",
|
|
3907
3945
|
found: !!memory,
|
|
3908
|
-
memoryId: args.memory_id
|
|
3946
|
+
memoryId: args.memory_id,
|
|
3947
|
+
hasProperties: !!memory?.properties,
|
|
3948
|
+
propertyCount: memory?.properties ? Object.keys(memory.properties).length : 0,
|
|
3949
|
+
hasTitle: !!memory?.properties?.title,
|
|
3950
|
+
hasContent: !!memory?.properties?.content
|
|
3909
3951
|
});
|
|
3910
3952
|
if (!memory) {
|
|
3911
3953
|
logger.info("Memory not found", {
|
|
@@ -4092,13 +4134,18 @@ async function executePublishMemory(request, userId) {
|
|
|
4092
4134
|
collectionName: getMemoryCollectionName(userId),
|
|
4093
4135
|
memoryId: request.payload.memory_id
|
|
4094
4136
|
});
|
|
4095
|
-
const originalMemory = await
|
|
4137
|
+
const originalMemory = await fetchMemoryWithAllProperties(
|
|
4138
|
+
userCollection,
|
|
4096
4139
|
request.payload.memory_id
|
|
4097
4140
|
);
|
|
4098
4141
|
logger.debug("Original memory fetch result", {
|
|
4099
4142
|
function: "executePublishMemory",
|
|
4100
4143
|
found: !!originalMemory,
|
|
4101
|
-
memoryId: request.payload.memory_id
|
|
4144
|
+
memoryId: request.payload.memory_id,
|
|
4145
|
+
hasProperties: !!originalMemory?.properties,
|
|
4146
|
+
propertyCount: originalMemory?.properties ? Object.keys(originalMemory.properties).length : 0,
|
|
4147
|
+
hasTitle: !!originalMemory?.properties?.title,
|
|
4148
|
+
hasContent: !!originalMemory?.properties?.content
|
|
4102
4149
|
});
|
|
4103
4150
|
if (!originalMemory) {
|
|
4104
4151
|
logger.info("Original memory not found", {
|
|
@@ -4254,7 +4301,14 @@ import { Filters as Filters3 } from "weaviate-client";
|
|
|
4254
4301
|
init_space_memory();
|
|
4255
4302
|
var searchSpaceTool = {
|
|
4256
4303
|
name: "remember_search_space",
|
|
4257
|
-
description:
|
|
4304
|
+
description: `Search one or more shared spaces to discover thoughts, ideas, and memories. By default, excludes comments to keep discovery clean. Set include_comments: true to include threaded discussions. Can search multiple spaces in a single query.
|
|
4305
|
+
|
|
4306
|
+
\u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
4307
|
+
- \u2705 CORRECT: User says "search The Void for hiking" \u2192 { spaces: ["the_void"], query: "hiking" }
|
|
4308
|
+
- \u274C WRONG: User says "search The Void for hiking" \u2192 { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
4309
|
+
- \u2705 CORRECT: User says "search The Void for note memories about hiking" \u2192 { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
4310
|
+
|
|
4311
|
+
Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
4258
4312
|
inputSchema: {
|
|
4259
4313
|
type: "object",
|
|
4260
4314
|
properties: {
|
|
@@ -4413,7 +4467,14 @@ import { Filters as Filters4 } from "weaviate-client";
|
|
|
4413
4467
|
init_space_memory();
|
|
4414
4468
|
var querySpaceTool = {
|
|
4415
4469
|
name: "remember_query_space",
|
|
4416
|
-
description:
|
|
4470
|
+
description: `Ask natural language questions about memories in shared spaces. By default, excludes comments to focus on original content. Set include_comments: true to include discussions in answers.
|
|
4471
|
+
|
|
4472
|
+
\u26A0\uFE0F **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
4473
|
+
- \u2705 CORRECT: User says "what's in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking" }
|
|
4474
|
+
- \u274C WRONG: User says "what's in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
4475
|
+
- \u2705 CORRECT: User says "what notes are in The Void about hiking?" \u2192 { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
4476
|
+
|
|
4477
|
+
Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
4417
4478
|
inputSchema: {
|
|
4418
4479
|
type: "object",
|
|
4419
4480
|
properties: {
|
|
@@ -33,6 +33,22 @@ export declare function getTemplateCollectionName(userId: string): string;
|
|
|
33
33
|
* Get collection name for user's audit logs
|
|
34
34
|
*/
|
|
35
35
|
export declare function getAuditCollectionName(userId: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* List of all memory properties to fetch
|
|
38
|
+
* Centralized to ensure consistency across all tools
|
|
39
|
+
*/
|
|
40
|
+
export declare const ALL_MEMORY_PROPERTIES: readonly ["user_id", "doc_type", "type", "title", "content", "tags", "weight", "base_weight", "trust_level", "context", "location", "relationships", "created_at", "updated_at", "version", "attribution", "source_url", "author", "parent_id", "thread_root_id", "moderation_flags"];
|
|
41
|
+
/**
|
|
42
|
+
* Fetch a memory object by ID with all properties
|
|
43
|
+
*
|
|
44
|
+
* This utility ensures all memory properties are fetched consistently
|
|
45
|
+
* across all tools, preventing bugs where properties are missing.
|
|
46
|
+
*
|
|
47
|
+
* @param collection - Weaviate collection
|
|
48
|
+
* @param memoryId - Memory ID to fetch
|
|
49
|
+
* @returns Memory object with all properties
|
|
50
|
+
*/
|
|
51
|
+
export declare function fetchMemoryWithAllProperties(collection: any, memoryId: string): Promise<any>;
|
|
36
52
|
/**
|
|
37
53
|
* Check if collection exists
|
|
38
54
|
*/
|
package/package.json
CHANGED
package/src/tools/confirm.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
9
9
|
import { confirmationTokenService, type ConfirmationRequest } from '../services/confirmation-token.service.js';
|
|
10
|
-
import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.js';
|
|
10
|
+
import { getWeaviateClient, getMemoryCollectionName, fetchMemoryWithAllProperties } from '../weaviate/client.js';
|
|
11
11
|
import { ensurePublicCollection } from '../weaviate/space-schema.js';
|
|
12
12
|
import { handleToolError } from '../utils/error-handler.js';
|
|
13
13
|
import { logger } from '../utils/logger.js';
|
|
@@ -151,7 +151,8 @@ async function executePublishMemory(
|
|
|
151
151
|
memoryId: request.payload.memory_id,
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
const originalMemory = await
|
|
154
|
+
const originalMemory = await fetchMemoryWithAllProperties(
|
|
155
|
+
userCollection,
|
|
155
156
|
request.payload.memory_id
|
|
156
157
|
);
|
|
157
158
|
|
|
@@ -159,6 +160,10 @@ async function executePublishMemory(
|
|
|
159
160
|
function: 'executePublishMemory',
|
|
160
161
|
found: !!originalMemory,
|
|
161
162
|
memoryId: request.payload.memory_id,
|
|
163
|
+
hasProperties: !!originalMemory?.properties,
|
|
164
|
+
propertyCount: originalMemory?.properties ? Object.keys(originalMemory.properties).length : 0,
|
|
165
|
+
hasTitle: !!originalMemory?.properties?.title,
|
|
166
|
+
hasContent: !!originalMemory?.properties?.content,
|
|
162
167
|
});
|
|
163
168
|
|
|
164
169
|
if (!originalMemory) {
|
package/src/tools/publish.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
9
9
|
import { confirmationTokenService } from '../services/confirmation-token.service.js';
|
|
10
|
-
import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.js';
|
|
10
|
+
import { getWeaviateClient, getMemoryCollectionName, fetchMemoryWithAllProperties } from '../weaviate/client.js';
|
|
11
11
|
import { isValidSpaceId } from '../weaviate/space-schema.js';
|
|
12
12
|
import { handleToolError } from '../utils/error-handler.js';
|
|
13
13
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
@@ -122,12 +122,16 @@ export async function handlePublish(
|
|
|
122
122
|
|
|
123
123
|
const userCollection = weaviateClient.collections.get(collectionName);
|
|
124
124
|
|
|
125
|
-
const memory = await userCollection
|
|
125
|
+
const memory = await fetchMemoryWithAllProperties(userCollection, args.memory_id);
|
|
126
126
|
|
|
127
127
|
logger.debug('Memory fetch result', {
|
|
128
128
|
tool: 'remember_publish',
|
|
129
129
|
found: !!memory,
|
|
130
130
|
memoryId: args.memory_id,
|
|
131
|
+
hasProperties: !!memory?.properties,
|
|
132
|
+
propertyCount: memory?.properties ? Object.keys(memory.properties).length : 0,
|
|
133
|
+
hasTitle: !!memory?.properties?.title,
|
|
134
|
+
hasContent: !!memory?.properties?.content,
|
|
131
135
|
});
|
|
132
136
|
|
|
133
137
|
if (!memory) {
|
|
@@ -35,6 +35,11 @@ export const queryMemoryTool = {
|
|
|
35
35
|
- "What are my project goals?"
|
|
36
36
|
|
|
37
37
|
**AGENT GUIDANCE**:
|
|
38
|
+
- ⚠️ **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
39
|
+
* ✅ CORRECT: User says "what do I know about hiking?" → { query: "hiking" }
|
|
40
|
+
* ❌ WRONG: User says "what do I know about hiking?" → { query: "hiking", filters: { types: ["note"] } }
|
|
41
|
+
* ✅ CORRECT: User says "what notes do I have about hiking?" → { query: "hiking", filters: { types: ["note"] } }
|
|
42
|
+
* Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
38
43
|
- If query results are too broad or include irrelevant content, try remember_search_memory instead - it uses hybrid search with keyword matching which is better for precise, specific searches. You can inform the user: "The results were too broad. Let me try a more precise keyword search using the search tool."
|
|
39
44
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
40
45
|
* Create a new memory with the information they're looking for
|
package/src/tools/query-space.ts
CHANGED
|
@@ -17,7 +17,14 @@ import { handleToolError } from '../utils/error-handler.js';
|
|
|
17
17
|
*/
|
|
18
18
|
export const querySpaceTool: Tool = {
|
|
19
19
|
name: 'remember_query_space',
|
|
20
|
-
description:
|
|
20
|
+
description: `Ask natural language questions about memories in shared spaces. By default, excludes comments to focus on original content. Set include_comments: true to include discussions in answers.
|
|
21
|
+
|
|
22
|
+
⚠️ **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
23
|
+
- ✅ CORRECT: User says "what's in The Void about hiking?" → { spaces: ["the_void"], question: "hiking" }
|
|
24
|
+
- ❌ WRONG: User says "what's in The Void about hiking?" → { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
25
|
+
- ✅ CORRECT: User says "what notes are in The Void about hiking?" → { spaces: ["the_void"], question: "hiking", content_type: "note" }
|
|
26
|
+
|
|
27
|
+
Let the query algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
21
28
|
inputSchema: {
|
|
22
29
|
type: 'object',
|
|
23
30
|
properties: {
|
|
@@ -34,6 +34,11 @@ export const searchMemoryTool = {
|
|
|
34
34
|
- "Show me notes from last week" → returns notes + any relationships created that week
|
|
35
35
|
|
|
36
36
|
**AGENT GUIDANCE**:
|
|
37
|
+
- ⚠️ **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add filters.types unless the user explicitly requests filtering by content type.
|
|
38
|
+
* ✅ CORRECT: User says "search for hiking" → { query: "hiking" }
|
|
39
|
+
* ❌ WRONG: User says "search for hiking" → { query: "hiking", filters: { types: ["note"] } }
|
|
40
|
+
* ✅ CORRECT: User says "search for note memories about hiking" → { query: "hiking", filters: { types: ["note"] } }
|
|
41
|
+
* Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.
|
|
37
42
|
- If search results are too narrow or miss relevant content, try remember_query_memory instead - it uses pure semantic search which is better for broader, concept-based queries. You can inform the user: "I didn't find what you're looking for with keyword search. Let me try a broader semantic search using the query tool."
|
|
38
43
|
- **CRITICAL**: If no results are returned, DO NOT make up or fabricate memories. Only report what was actually found. Tell the user honestly that no matching memories were found and suggest they:
|
|
39
44
|
* Create a new memory with the information they're looking for
|
|
@@ -18,7 +18,14 @@ import type { SearchFilters } from '../types/memory.js';
|
|
|
18
18
|
*/
|
|
19
19
|
export const searchSpaceTool: Tool = {
|
|
20
20
|
name: 'remember_search_space',
|
|
21
|
-
description:
|
|
21
|
+
description: `Search one or more shared spaces to discover thoughts, ideas, and memories. By default, excludes comments to keep discovery clean. Set include_comments: true to include threaded discussions. Can search multiple spaces in a single query.
|
|
22
|
+
|
|
23
|
+
⚠️ **CRITICAL - CONTENT TYPE FILTERING**: Do NOT add content_type filter unless the user explicitly requests filtering by type.
|
|
24
|
+
- ✅ CORRECT: User says "search The Void for hiking" → { spaces: ["the_void"], query: "hiking" }
|
|
25
|
+
- ❌ WRONG: User says "search The Void for hiking" → { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
26
|
+
- ✅ CORRECT: User says "search The Void for note memories about hiking" → { spaces: ["the_void"], query: "hiking", content_type: "note" }
|
|
27
|
+
|
|
28
|
+
Let the search algorithm find ALL relevant memories regardless of type unless explicitly requested.`,
|
|
22
29
|
inputSchema: {
|
|
23
30
|
type: 'object',
|
|
24
31
|
properties: {
|
package/src/weaviate/client.ts
CHANGED
|
@@ -139,6 +139,53 @@ export function getAuditCollectionName(userId: string): string {
|
|
|
139
139
|
return `Audit_${sanitizeUserId(userId)}`;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
* List of all memory properties to fetch
|
|
144
|
+
* Centralized to ensure consistency across all tools
|
|
145
|
+
*/
|
|
146
|
+
export const ALL_MEMORY_PROPERTIES = [
|
|
147
|
+
'user_id',
|
|
148
|
+
'doc_type',
|
|
149
|
+
'type',
|
|
150
|
+
'title',
|
|
151
|
+
'content',
|
|
152
|
+
'tags',
|
|
153
|
+
'weight',
|
|
154
|
+
'base_weight',
|
|
155
|
+
'trust_level',
|
|
156
|
+
'context',
|
|
157
|
+
'location',
|
|
158
|
+
'relationships',
|
|
159
|
+
'created_at',
|
|
160
|
+
'updated_at',
|
|
161
|
+
'version',
|
|
162
|
+
'attribution',
|
|
163
|
+
'source_url',
|
|
164
|
+
'author',
|
|
165
|
+
'parent_id',
|
|
166
|
+
'thread_root_id',
|
|
167
|
+
'moderation_flags',
|
|
168
|
+
] as const;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Fetch a memory object by ID with all properties
|
|
172
|
+
*
|
|
173
|
+
* This utility ensures all memory properties are fetched consistently
|
|
174
|
+
* across all tools, preventing bugs where properties are missing.
|
|
175
|
+
*
|
|
176
|
+
* @param collection - Weaviate collection
|
|
177
|
+
* @param memoryId - Memory ID to fetch
|
|
178
|
+
* @returns Memory object with all properties
|
|
179
|
+
*/
|
|
180
|
+
export async function fetchMemoryWithAllProperties(
|
|
181
|
+
collection: any,
|
|
182
|
+
memoryId: string
|
|
183
|
+
) {
|
|
184
|
+
return await collection.query.fetchObjectById(memoryId, {
|
|
185
|
+
returnProperties: ALL_MEMORY_PROPERTIES,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
142
189
|
/**
|
|
143
190
|
* Check if collection exists
|
|
144
191
|
*/
|