@prmichaelsen/remember-mcp 3.13.0 → 3.14.1
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/agent/milestones/milestone-17-remember-core-migration.md +140 -0
- package/agent/progress.yaml +123 -6
- package/agent/tasks/milestone-17-remember-core-migration/task-193-foundation-setup.md +58 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-194-migrate-relationship-tools.md +47 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-195-migrate-preference-tools.md +34 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-196-migrate-memory-tools.md +46 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-197-migrate-space-confirmation-tools.md +49 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-198-migrate-space-search-moderate.md +46 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-199-migrate-delete-memory.md +43 -0
- package/agent/tasks/milestone-17-remember-core-migration/task-200-code-cleanup-verification.md +52 -0
- package/dist/core-services.d.ts +25 -0
- package/dist/server-factory.js +3208 -3978
- package/dist/server.js +3708 -4474
- package/dist/tools/confirm-publish-moderation.spec.d.ts +3 -2
- package/dist/tools/create-memory.d.ts +1 -1
- package/dist/tools/query-space.d.ts +1 -1
- package/dist/tools/search-space.d.ts +10 -14
- package/jest.config.js +11 -0
- package/package.json +3 -1
- package/src/core-services.ts +50 -0
- package/src/tools/confirm-publish-moderation.spec.ts +120 -176
- package/src/tools/confirm.ts +70 -1035
- package/src/tools/create-memory.ts +16 -67
- package/src/tools/create-relationship.ts +13 -181
- package/src/tools/delete-memory.ts +7 -72
- package/src/tools/delete-relationship.ts +7 -91
- package/src/tools/deny.ts +4 -14
- package/src/tools/find-similar.ts +16 -110
- package/src/tools/get-preferences.ts +3 -8
- package/src/tools/moderate.spec.ts +65 -81
- package/src/tools/moderate.ts +18 -121
- package/src/tools/publish.ts +7 -204
- package/src/tools/query-space.ts +28 -140
- package/src/tools/retract.ts +7 -185
- package/src/tools/revise.ts +4 -136
- package/src/tools/search-relationship.ts +17 -116
- package/src/tools/search-space.ts +58 -304
- package/src/tools/set-preference.ts +3 -8
- package/src/tools/update-memory.ts +22 -190
- package/src/tools/update-relationship.ts +16 -90
- package/src/v2-smoke.e2e.ts +3 -2
- package/dist/collections/composite-ids.d.ts +0 -106
- package/dist/collections/core-infrastructure.spec.d.ts +0 -11
- package/dist/collections/dot-notation.d.ts +0 -106
- package/dist/collections/tracking-arrays.d.ts +0 -176
- package/dist/constants/content-types.d.ts +0 -61
- package/dist/services/confirmation-token.service.d.ts +0 -99
- package/dist/services/confirmation-token.service.spec.d.ts +0 -5
- package/dist/services/preferences-database.service.d.ts +0 -22
- package/dist/services/space-config.service.d.ts +0 -23
- package/dist/services/space-config.service.spec.d.ts +0 -2
- package/src/collections/composite-ids.ts +0 -193
- package/src/collections/core-infrastructure.spec.ts +0 -353
- package/src/collections/dot-notation.ts +0 -212
- package/src/collections/tracking-arrays.ts +0 -298
- package/src/constants/content-types.ts +0 -490
- package/src/services/confirmation-token.service.spec.ts +0 -254
- package/src/services/confirmation-token.service.ts +0 -328
- package/src/services/preferences-database.service.ts +0 -120
- package/src/services/space-config.service.spec.ts +0 -102
- package/src/services/space-config.service.ts +0 -79
package/src/tools/publish.ts
CHANGED
|
@@ -12,14 +12,11 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
-
import { confirmationTokenService } from '../services/confirmation-token.service.js';
|
|
16
|
-
import { getWeaviateClient, getMemoryCollectionName, fetchMemoryWithAllProperties } from '../weaviate/client.js';
|
|
17
|
-
import { isValidSpaceId } from '../weaviate/space-schema.js';
|
|
18
15
|
import { handleToolError } from '../utils/error-handler.js';
|
|
19
16
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
20
|
-
import { logger } from '../utils/logger.js';
|
|
21
17
|
import { createDebugLogger } from '../utils/debug.js';
|
|
22
18
|
import type { AuthContext } from '../types/auth.js';
|
|
19
|
+
import { createCoreServices } from '../core-services.js';
|
|
23
20
|
|
|
24
21
|
/**
|
|
25
22
|
* Tool definition for remember_publish
|
|
@@ -92,213 +89,19 @@ export async function handlePublish(
|
|
|
92
89
|
try {
|
|
93
90
|
debug.info('Tool invoked');
|
|
94
91
|
debug.trace('Arguments', { args });
|
|
95
|
-
|
|
96
|
-
// Normalize arrays (handle undefined)
|
|
97
|
-
const spaces = args.spaces || [];
|
|
98
|
-
const groups = args.groups || [];
|
|
99
|
-
|
|
100
|
-
logger.info('Starting publish request', {
|
|
101
|
-
tool: 'remember_publish',
|
|
102
|
-
userId,
|
|
103
|
-
memoryId: args.memory_id,
|
|
104
|
-
spaces,
|
|
105
|
-
groups,
|
|
106
|
-
spaceCount: spaces.length,
|
|
107
|
-
groupCount: groups.length,
|
|
108
|
-
additionalTags: args.additional_tags?.length || 0,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Validate that at least one destination is provided
|
|
112
|
-
if (spaces.length === 0 && groups.length === 0) {
|
|
113
|
-
logger.warn('No destinations provided', {
|
|
114
|
-
tool: 'remember_publish',
|
|
115
|
-
userId,
|
|
116
|
-
});
|
|
117
|
-
return JSON.stringify(
|
|
118
|
-
{
|
|
119
|
-
success: false,
|
|
120
|
-
error: 'No destinations provided',
|
|
121
|
-
message: 'Must specify at least one space or group to publish to',
|
|
122
|
-
},
|
|
123
|
-
null,
|
|
124
|
-
2
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Validate all space IDs
|
|
129
|
-
if (spaces.length > 0) {
|
|
130
|
-
debug.debug('Validating space IDs', { spaces });
|
|
131
|
-
const invalidSpaces = spaces.filter(s => !isValidSpaceId(s));
|
|
132
|
-
if (invalidSpaces.length > 0) {
|
|
133
|
-
debug.warn('Invalid space IDs detected', { invalidSpaces });
|
|
134
|
-
logger.warn('Invalid space IDs provided', {
|
|
135
|
-
tool: 'remember_publish',
|
|
136
|
-
invalidSpaces,
|
|
137
|
-
providedSpaces: spaces,
|
|
138
|
-
});
|
|
139
|
-
return JSON.stringify(
|
|
140
|
-
{
|
|
141
|
-
success: false,
|
|
142
|
-
error: 'Invalid space IDs',
|
|
143
|
-
message: `Invalid spaces: ${invalidSpaces.join(', ')}. Supported spaces: ${SUPPORTED_SPACES.join(', ')}`,
|
|
144
|
-
context: {
|
|
145
|
-
invalid_spaces: invalidSpaces,
|
|
146
|
-
provided_spaces: spaces,
|
|
147
|
-
supported_spaces: SUPPORTED_SPACES,
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
null,
|
|
151
|
-
2
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Validate group IDs format (basic validation - no dots allowed)
|
|
157
|
-
if (groups.length > 0) {
|
|
158
|
-
debug.debug('Validating group IDs', { groups });
|
|
159
|
-
const invalidGroups = groups.filter(g => !g || g.includes('.') || g.trim() === '');
|
|
160
|
-
if (invalidGroups.length > 0) {
|
|
161
|
-
debug.warn('Invalid group IDs detected', { invalidGroups });
|
|
162
|
-
logger.warn('Invalid group IDs provided', {
|
|
163
|
-
tool: 'remember_publish',
|
|
164
|
-
invalidGroups,
|
|
165
|
-
providedGroups: groups,
|
|
166
|
-
});
|
|
167
|
-
return JSON.stringify(
|
|
168
|
-
{
|
|
169
|
-
success: false,
|
|
170
|
-
error: 'Invalid group IDs',
|
|
171
|
-
message: 'Group IDs cannot be empty or contain dots',
|
|
172
|
-
context: {
|
|
173
|
-
invalid_groups: invalidGroups,
|
|
174
|
-
provided_groups: groups,
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
null,
|
|
178
|
-
2
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Verify memory exists and user owns it
|
|
184
|
-
const weaviateClient = getWeaviateClient();
|
|
185
|
-
const collectionName = getMemoryCollectionName(userId);
|
|
186
|
-
logger.debug('Fetching memory from collection', {
|
|
187
|
-
tool: 'remember_publish',
|
|
188
|
-
collectionName,
|
|
189
|
-
memoryId: args.memory_id,
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
const userCollection = weaviateClient.collections.get(collectionName);
|
|
193
|
-
|
|
194
|
-
const memory = await debug.time('Fetch memory from user collection', async () => {
|
|
195
|
-
return await fetchMemoryWithAllProperties(userCollection, args.memory_id);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
logger.debug('Memory fetch result', {
|
|
199
|
-
tool: 'remember_publish',
|
|
200
|
-
found: !!memory,
|
|
201
|
-
memoryId: args.memory_id,
|
|
202
|
-
hasProperties: !!memory?.properties,
|
|
203
|
-
propertyCount: memory?.properties ? Object.keys(memory.properties).length : 0,
|
|
204
|
-
hasTitle: !!memory?.properties?.title,
|
|
205
|
-
hasContent: !!memory?.properties?.content,
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
if (!memory) {
|
|
209
|
-
logger.info('Memory not found', {
|
|
210
|
-
tool: 'remember_publish',
|
|
211
|
-
memoryId: args.memory_id,
|
|
212
|
-
collectionName,
|
|
213
|
-
});
|
|
214
|
-
return JSON.stringify(
|
|
215
|
-
{
|
|
216
|
-
success: false,
|
|
217
|
-
error: 'Memory not found',
|
|
218
|
-
message: `No memory found with ID: ${args.memory_id}`,
|
|
219
|
-
context: {
|
|
220
|
-
collection_name: getMemoryCollectionName(userId),
|
|
221
|
-
memory_id: args.memory_id,
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
null,
|
|
225
|
-
2
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
92
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return JSON.stringify(
|
|
232
|
-
{
|
|
233
|
-
success: false,
|
|
234
|
-
error: 'Permission denied',
|
|
235
|
-
message: 'You can only publish your own memories',
|
|
236
|
-
context: {
|
|
237
|
-
memory_id: args.memory_id,
|
|
238
|
-
memory_owner: memory.properties.user_id,
|
|
239
|
-
requesting_user: userId,
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
null,
|
|
243
|
-
2
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Verify it's a memory (not a relationship)
|
|
248
|
-
if (memory.properties.doc_type !== 'memory') {
|
|
249
|
-
return JSON.stringify(
|
|
250
|
-
{
|
|
251
|
-
success: false,
|
|
252
|
-
error: 'Invalid document type',
|
|
253
|
-
message: 'Only memories can be published (not relationships)',
|
|
254
|
-
context: {
|
|
255
|
-
memory_id: args.memory_id,
|
|
256
|
-
doc_type: memory.properties.doc_type,
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
null,
|
|
260
|
-
2
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Create payload with memory_id, spaces, and groups arrays
|
|
265
|
-
const payload = {
|
|
93
|
+
const { space } = createCoreServices(userId);
|
|
94
|
+
const result = await space.publish({
|
|
266
95
|
memory_id: args.memory_id,
|
|
267
|
-
spaces: spaces,
|
|
268
|
-
groups: groups,
|
|
269
|
-
additional_tags: args.additional_tags
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
logger.info('Generating confirmation token', {
|
|
273
|
-
tool: 'remember_publish',
|
|
274
|
-
userId,
|
|
275
|
-
memoryId: args.memory_id,
|
|
276
|
-
spaces: spaces,
|
|
277
|
-
groups: groups,
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// Generate confirmation token
|
|
281
|
-
const { requestId, token} = await confirmationTokenService.createRequest(
|
|
282
|
-
userId,
|
|
283
|
-
'publish_memory',
|
|
284
|
-
payload,
|
|
285
|
-
undefined // No single target_collection anymore
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
logger.info('Confirmation token generated', {
|
|
289
|
-
tool: 'remember_publish',
|
|
290
|
-
requestId,
|
|
291
|
-
token,
|
|
292
|
-
action: 'publish_memory',
|
|
293
|
-
spaces: spaces,
|
|
294
|
-
groups: groups,
|
|
96
|
+
spaces: args.spaces,
|
|
97
|
+
groups: args.groups,
|
|
98
|
+
additional_tags: args.additional_tags,
|
|
295
99
|
});
|
|
296
100
|
|
|
297
|
-
// Return minimal response - agent already knows memory details
|
|
298
101
|
return JSON.stringify(
|
|
299
102
|
{
|
|
300
103
|
success: true,
|
|
301
|
-
token,
|
|
104
|
+
token: result.token,
|
|
302
105
|
},
|
|
303
106
|
null,
|
|
304
107
|
2
|
package/src/tools/query-space.ts
CHANGED
|
@@ -6,16 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
-
import { Filters } from 'weaviate-client';
|
|
10
|
-
import { getWeaviateClient } from '../weaviate/client.js';
|
|
11
|
-
import { ensurePublicCollection, isValidSpaceId } from '../weaviate/space-schema.js';
|
|
12
9
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
13
10
|
import { handleToolError } from '../utils/error-handler.js';
|
|
14
11
|
import { createDebugLogger } from '../utils/debug.js';
|
|
15
12
|
import type { AuthContext } from '../types/auth.js';
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
import { createCoreServices } from '../core-services.js';
|
|
14
|
+
|
|
15
|
+
export type ModerationFilter = 'approved' | 'pending' | 'rejected' | 'removed' | 'all';
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Tool definition for remember_query_space
|
|
@@ -128,164 +125,55 @@ export async function handleQuerySpace(
|
|
|
128
125
|
try {
|
|
129
126
|
debug.info('Tool invoked');
|
|
130
127
|
debug.trace('Arguments', { args });
|
|
131
|
-
|
|
132
|
-
// Validate all space IDs
|
|
133
|
-
debug.debug('Validating space IDs', { spaces: args.spaces });
|
|
134
|
-
const invalidSpaces = args.spaces.filter(s => !isValidSpaceId(s));
|
|
135
|
-
if (invalidSpaces.length > 0) {
|
|
136
|
-
return JSON.stringify(
|
|
137
|
-
{
|
|
138
|
-
success: false,
|
|
139
|
-
error: 'Invalid space IDs',
|
|
140
|
-
message: `Invalid spaces: ${invalidSpaces.join(', ')}. Supported spaces: ${SUPPORTED_SPACES.join(', ')}`,
|
|
141
|
-
},
|
|
142
|
-
null,
|
|
143
|
-
2
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Validate not empty
|
|
148
|
-
if (args.spaces.length === 0) {
|
|
149
|
-
return JSON.stringify(
|
|
150
|
-
{
|
|
151
|
-
success: false,
|
|
152
|
-
error: 'Empty spaces array',
|
|
153
|
-
message: 'Must specify at least one space to query',
|
|
154
|
-
},
|
|
155
|
-
null,
|
|
156
|
-
2
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Permission check: non-approved moderation filters require moderator access
|
|
161
|
-
const moderationFilterValue = args.moderation_filter || 'approved';
|
|
162
|
-
if (moderationFilterValue !== 'approved' && !canModerateAny(authContext)) {
|
|
163
|
-
return JSON.stringify(
|
|
164
|
-
{
|
|
165
|
-
success: false,
|
|
166
|
-
error: 'Permission denied',
|
|
167
|
-
message: `Moderator access required to view ${moderationFilterValue} memories in spaces`,
|
|
168
|
-
},
|
|
169
|
-
null,
|
|
170
|
-
2
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const weaviateClient = getWeaviateClient();
|
|
175
|
-
const publicCollection = await ensurePublicCollection(weaviateClient);
|
|
176
|
-
|
|
177
|
-
// Build filters
|
|
178
|
-
const filterList: any[] = [];
|
|
179
128
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// Exclude comments and ghost memories by default (unless explicitly included)
|
|
198
|
-
if (!args.include_comments && !args.content_type) {
|
|
199
|
-
// Only exclude comments if not filtering by content_type
|
|
200
|
-
// (if content_type is set, user has explicit control)
|
|
201
|
-
filterList.push(publicCollection.filter.byProperty('content_type').notEqual('comment'));
|
|
202
|
-
}
|
|
203
|
-
if (!args.content_type) {
|
|
204
|
-
filterList.push(publicCollection.filter.byProperty('content_type').notEqual('ghost'));
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Apply tags filter
|
|
208
|
-
if (args.tags && args.tags.length > 0) {
|
|
209
|
-
args.tags.forEach(tag => {
|
|
210
|
-
filterList.push(publicCollection.filter.byProperty('tags').containsAny([tag]));
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Apply weight filter
|
|
215
|
-
if (args.min_weight !== undefined) {
|
|
216
|
-
filterList.push(publicCollection.filter.byProperty('weight').greaterOrEqual(args.min_weight));
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Apply date filters
|
|
220
|
-
if (args.date_from) {
|
|
221
|
-
filterList.push(publicCollection.filter.byProperty('created_at').greaterOrEqual(new Date(args.date_from)));
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (args.date_to) {
|
|
225
|
-
filterList.push(publicCollection.filter.byProperty('created_at').lessOrEqual(new Date(args.date_to)));
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const whereFilter = filterList.length > 0 ? Filters.and(...filterList) : undefined;
|
|
229
|
-
|
|
230
|
-
debug.debug('Executing semantic query', {
|
|
231
|
-
question: args.question,
|
|
232
|
-
filterCount: filterList.length,
|
|
233
|
-
limit: args.limit || 10,
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Execute semantic search using nearText
|
|
237
|
-
const searchResults = await debug.time('Semantic query', async () => {
|
|
238
|
-
return await publicCollection.query.nearText(args.question, {
|
|
239
|
-
limit: args.limit || 10,
|
|
240
|
-
...(whereFilter && { where: whereFilter }),
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
debug.debug('Query completed', {
|
|
245
|
-
resultCount: searchResults.objects.length,
|
|
246
|
-
format: args.format || 'detailed',
|
|
247
|
-
});
|
|
129
|
+
const { space } = createCoreServices(userId);
|
|
130
|
+
const coreResult = await space.query(
|
|
131
|
+
{
|
|
132
|
+
question: args.question,
|
|
133
|
+
spaces: args.spaces,
|
|
134
|
+
content_type: args.content_type,
|
|
135
|
+
tags: args.tags,
|
|
136
|
+
min_weight: args.min_weight,
|
|
137
|
+
date_from: args.date_from,
|
|
138
|
+
date_to: args.date_to,
|
|
139
|
+
moderation_filter: args.moderation_filter as any,
|
|
140
|
+
include_comments: args.include_comments,
|
|
141
|
+
limit: args.limit,
|
|
142
|
+
},
|
|
143
|
+
authContext as any
|
|
144
|
+
);
|
|
248
145
|
|
|
249
146
|
// Format results based on requested format
|
|
250
147
|
const format = args.format || 'detailed';
|
|
251
148
|
|
|
252
149
|
if (format === 'compact') {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const props = obj.properties;
|
|
256
|
-
return `${idx + 1}. ${props.title || props.content?.substring(0, 100) || 'Untitled'}`;
|
|
150
|
+
const summaries = coreResult.memories.map((mem: any, idx: number) => {
|
|
151
|
+
return `${idx + 1}. ${mem.title || mem.content?.substring(0, 100) || 'Untitled'}`;
|
|
257
152
|
});
|
|
258
153
|
|
|
259
154
|
const result = {
|
|
260
155
|
question: args.question,
|
|
261
|
-
spaces_queried:
|
|
156
|
+
spaces_queried: coreResult.spaces_queried,
|
|
262
157
|
format: 'compact',
|
|
263
158
|
summary: summaries.join('\n'),
|
|
264
|
-
count:
|
|
159
|
+
count: coreResult.memories.length,
|
|
265
160
|
};
|
|
266
161
|
|
|
267
162
|
return JSON.stringify(result, null, 2);
|
|
268
163
|
} else {
|
|
269
|
-
// Detailed format: full objects
|
|
270
|
-
const memories = searchResults.objects.map((obj: any) => ({
|
|
271
|
-
id: obj.uuid,
|
|
272
|
-
...obj.properties,
|
|
273
|
-
_distance: obj.metadata?.distance,
|
|
274
|
-
}));
|
|
275
|
-
|
|
276
164
|
const result = {
|
|
277
165
|
question: args.question,
|
|
278
|
-
spaces_queried:
|
|
166
|
+
spaces_queried: coreResult.spaces_queried,
|
|
279
167
|
format: 'detailed',
|
|
280
|
-
memories,
|
|
281
|
-
total:
|
|
168
|
+
memories: coreResult.memories,
|
|
169
|
+
total: coreResult.total,
|
|
282
170
|
};
|
|
283
171
|
|
|
284
172
|
debug.info('Tool completed successfully', {
|
|
285
|
-
resultCount:
|
|
173
|
+
resultCount: coreResult.total,
|
|
286
174
|
format: 'detailed',
|
|
287
175
|
});
|
|
288
|
-
|
|
176
|
+
|
|
289
177
|
return JSON.stringify(result, null, 2);
|
|
290
178
|
}
|
|
291
179
|
} catch (error) {
|
package/src/tools/retract.ts
CHANGED
|
@@ -12,12 +12,10 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
-
import { confirmationTokenService } from '../services/confirmation-token.service.js';
|
|
16
|
-
import { getWeaviateClient, getMemoryCollectionName, fetchMemoryWithAllProperties } from '../weaviate/client.js';
|
|
17
15
|
import { handleToolError } from '../utils/error-handler.js';
|
|
18
|
-
import { logger } from '../utils/logger.js';
|
|
19
16
|
import { createDebugLogger } from '../utils/debug.js';
|
|
20
17
|
import type { AuthContext } from '../types/auth.js';
|
|
18
|
+
import { createCoreServices } from '../core-services.js';
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Tool definition for remember_retract
|
|
@@ -83,195 +81,19 @@ export async function handleRetract(
|
|
|
83
81
|
debug.info('Tool invoked');
|
|
84
82
|
debug.trace('Arguments', { args });
|
|
85
83
|
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
tool: 'remember_retract',
|
|
92
|
-
userId,
|
|
93
|
-
memoryId: args.memory_id,
|
|
94
|
-
spaces,
|
|
95
|
-
groups,
|
|
96
|
-
spaceCount: spaces.length,
|
|
97
|
-
groupCount: groups.length,
|
|
84
|
+
const { space } = createCoreServices(userId);
|
|
85
|
+
const result = await space.retract({
|
|
86
|
+
memory_id: args.memory_id,
|
|
87
|
+
spaces: args.spaces,
|
|
88
|
+
groups: args.groups,
|
|
98
89
|
});
|
|
99
90
|
|
|
100
|
-
// Validate that at least one destination is provided
|
|
101
|
-
if (spaces.length === 0 && groups.length === 0) {
|
|
102
|
-
logger.warn('No destinations provided for retraction', {
|
|
103
|
-
tool: 'remember_retract',
|
|
104
|
-
userId,
|
|
105
|
-
});
|
|
106
|
-
return JSON.stringify(
|
|
107
|
-
{
|
|
108
|
-
success: false,
|
|
109
|
-
error: 'No destinations provided',
|
|
110
|
-
message: 'Must specify at least one space or group to retract from',
|
|
111
|
-
},
|
|
112
|
-
null,
|
|
113
|
-
2
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Validate group IDs (no dots allowed)
|
|
118
|
-
if (groups.length > 0) {
|
|
119
|
-
const invalidGroups = groups.filter(g => g.includes('.'));
|
|
120
|
-
if (invalidGroups.length > 0) {
|
|
121
|
-
logger.warn('Invalid group IDs detected', {
|
|
122
|
-
tool: 'remember_retract',
|
|
123
|
-
invalidGroups,
|
|
124
|
-
});
|
|
125
|
-
return JSON.stringify(
|
|
126
|
-
{
|
|
127
|
-
success: false,
|
|
128
|
-
error: 'Invalid group IDs',
|
|
129
|
-
message: `Group IDs cannot contain dots: ${invalidGroups.join(', ')}`,
|
|
130
|
-
context: {
|
|
131
|
-
invalid_groups: invalidGroups,
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
null,
|
|
135
|
-
2
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Verify the memory exists and belongs to the user
|
|
141
|
-
const weaviateClient = getWeaviateClient();
|
|
142
|
-
const collectionName = getMemoryCollectionName(userId);
|
|
143
|
-
const collection = weaviateClient.collections.get(collectionName);
|
|
144
|
-
|
|
145
|
-
logger.debug('Fetching memory for retraction', {
|
|
146
|
-
tool: 'remember_retract',
|
|
147
|
-
collectionName,
|
|
148
|
-
memoryId: args.memory_id,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const memory = await fetchMemoryWithAllProperties(collection, args.memory_id);
|
|
152
|
-
|
|
153
|
-
if (!memory) {
|
|
154
|
-
logger.info('Memory not found for retraction', {
|
|
155
|
-
tool: 'remember_retract',
|
|
156
|
-
memoryId: args.memory_id,
|
|
157
|
-
});
|
|
158
|
-
return JSON.stringify(
|
|
159
|
-
{
|
|
160
|
-
success: false,
|
|
161
|
-
error: 'Memory not found',
|
|
162
|
-
message: `Memory ${args.memory_id} does not exist`,
|
|
163
|
-
},
|
|
164
|
-
null,
|
|
165
|
-
2
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Verify ownership
|
|
170
|
-
if (memory.properties.user_id !== userId) {
|
|
171
|
-
logger.warn('Permission denied - wrong owner', {
|
|
172
|
-
tool: 'remember_retract',
|
|
173
|
-
memoryId: args.memory_id,
|
|
174
|
-
memoryOwner: memory.properties.user_id,
|
|
175
|
-
requestingUser: userId,
|
|
176
|
-
});
|
|
177
|
-
return JSON.stringify(
|
|
178
|
-
{
|
|
179
|
-
success: false,
|
|
180
|
-
error: 'Permission denied',
|
|
181
|
-
message: 'You can only retract your own memories',
|
|
182
|
-
},
|
|
183
|
-
null,
|
|
184
|
-
2
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Check current publication status
|
|
189
|
-
const currentSpaceIds: string[] = Array.isArray(memory.properties.space_ids)
|
|
190
|
-
? memory.properties.space_ids
|
|
191
|
-
: [];
|
|
192
|
-
const currentGroupIds: string[] = Array.isArray(memory.properties.group_ids)
|
|
193
|
-
? memory.properties.group_ids
|
|
194
|
-
: [];
|
|
195
|
-
|
|
196
|
-
// Validate that memory is actually published to the specified destinations
|
|
197
|
-
const notPublishedSpaces = spaces.filter(s => !currentSpaceIds.includes(s));
|
|
198
|
-
const notPublishedGroups = groups.filter(g => !currentGroupIds.includes(g));
|
|
199
|
-
|
|
200
|
-
if (notPublishedSpaces.length > 0 || notPublishedGroups.length > 0) {
|
|
201
|
-
logger.warn('Memory not published to some destinations', {
|
|
202
|
-
tool: 'remember_retract',
|
|
203
|
-
notPublishedSpaces,
|
|
204
|
-
notPublishedGroups,
|
|
205
|
-
currentSpaceIds,
|
|
206
|
-
currentGroupIds,
|
|
207
|
-
});
|
|
208
|
-
return JSON.stringify(
|
|
209
|
-
{
|
|
210
|
-
success: false,
|
|
211
|
-
error: 'Not published to destinations',
|
|
212
|
-
message: 'Memory is not published to some of the specified destinations',
|
|
213
|
-
context: {
|
|
214
|
-
not_published_spaces: notPublishedSpaces,
|
|
215
|
-
not_published_groups: notPublishedGroups,
|
|
216
|
-
current_spaces: currentSpaceIds,
|
|
217
|
-
current_groups: currentGroupIds,
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
null,
|
|
221
|
-
2
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Create confirmation request
|
|
226
|
-
const { requestId, token } = await confirmationTokenService.createRequest(
|
|
227
|
-
userId,
|
|
228
|
-
'retract_memory',
|
|
229
|
-
{
|
|
230
|
-
memory_id: args.memory_id,
|
|
231
|
-
spaces,
|
|
232
|
-
groups,
|
|
233
|
-
current_space_ids: currentSpaceIds,
|
|
234
|
-
current_group_ids: currentGroupIds,
|
|
235
|
-
}
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
logger.info('Retract confirmation request created', {
|
|
239
|
-
tool: 'remember_retract',
|
|
240
|
-
requestId,
|
|
241
|
-
userId,
|
|
242
|
-
memoryId: args.memory_id,
|
|
243
|
-
spaces,
|
|
244
|
-
groups,
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Build summary for user
|
|
248
|
-
const destinations: string[] = [];
|
|
249
|
-
if (spaces.length > 0) {
|
|
250
|
-
destinations.push(`spaces: ${spaces.join(', ')}`);
|
|
251
|
-
}
|
|
252
|
-
if (groups.length > 0) {
|
|
253
|
-
destinations.push(`groups: ${groups.join(', ')}`);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
91
|
return JSON.stringify(
|
|
257
92
|
{
|
|
258
93
|
success: true,
|
|
259
|
-
|
|
94
|
+
token: result.token,
|
|
260
95
|
action: 'retract_memory',
|
|
261
96
|
memory_id: args.memory_id,
|
|
262
|
-
destinations: destinations.join('; '),
|
|
263
|
-
retraction_details: {
|
|
264
|
-
spaces: spaces.length > 0 ? {
|
|
265
|
-
action: 'orphan',
|
|
266
|
-
description: 'Memory will remain in Memory_spaces_public with updated tracking arrays (removed from space_ids)',
|
|
267
|
-
spaces,
|
|
268
|
-
} : null,
|
|
269
|
-
groups: groups.length > 0 ? {
|
|
270
|
-
action: 'orphan',
|
|
271
|
-
description: 'Memory will remain in Memory_groups_{groupId} with updated tracking arrays (removed from group_ids)',
|
|
272
|
-
groups,
|
|
273
|
-
} : null,
|
|
274
|
-
},
|
|
275
97
|
confirmation_required: true,
|
|
276
98
|
},
|
|
277
99
|
null,
|