@prmichaelsen/remember-mcp 3.12.0 → 3.14.0
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 +20 -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 +3578 -4485
- package/dist/server.js +3070 -3973
- 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 +2 -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
|
@@ -8,15 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
10
10
|
import { Filters } from 'weaviate-client';
|
|
11
|
-
import { getWeaviateClient } from '../weaviate/client.js';
|
|
12
|
-
import { isValidSpaceId } from '../weaviate/space-schema.js';
|
|
13
11
|
import { SUPPORTED_SPACES } from '../types/space-memory.js';
|
|
14
12
|
import { handleToolError } from '../utils/error-handler.js';
|
|
15
13
|
import { createDebugLogger } from '../utils/debug.js';
|
|
16
|
-
import { CollectionType, getCollectionName } from '../collections/dot-notation.js';
|
|
17
|
-
import { logger } from '../utils/logger.js';
|
|
18
14
|
import type { AuthContext } from '../types/auth.js';
|
|
19
|
-
import {
|
|
15
|
+
import { createCoreServices } from '../core-services.js';
|
|
20
16
|
|
|
21
17
|
/**
|
|
22
18
|
* Tool definition for remember_search_space
|
|
@@ -123,130 +119,57 @@ Let the search algorithm find ALL relevant memories regardless of type unless ex
|
|
|
123
119
|
|
|
124
120
|
export type ModerationFilter = 'approved' | 'pending' | 'rejected' | 'removed' | 'all';
|
|
125
121
|
|
|
126
|
-
interface SearchSpaceArgs {
|
|
127
|
-
query: string;
|
|
128
|
-
spaces?: string[];
|
|
129
|
-
groups?: string[];
|
|
130
|
-
search_type?: 'hybrid' | 'bm25' | 'semantic';
|
|
131
|
-
content_type?: string;
|
|
132
|
-
tags?: string[];
|
|
133
|
-
min_weight?: number;
|
|
134
|
-
max_weight?: number;
|
|
135
|
-
date_from?: string;
|
|
136
|
-
date_to?: string;
|
|
137
|
-
moderation_filter?: ModerationFilter;
|
|
138
|
-
include_comments?: boolean;
|
|
139
|
-
limit?: number;
|
|
140
|
-
offset?: number;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
122
|
/**
|
|
144
123
|
* Build the moderation status filter for a Weaviate collection query.
|
|
145
|
-
*
|
|
146
|
-
* - 'approved' (default): matches approved OR null (backward compat for pre-moderation memories)
|
|
147
|
-
* - 'pending'/'rejected'/'removed': matches that specific status
|
|
148
|
-
* - 'all': no moderation filter applied
|
|
124
|
+
* @deprecated Kept for test compatibility — logic now lives in remember-core SpaceService
|
|
149
125
|
*/
|
|
150
126
|
export function buildModerationFilter(collection: any, moderationFilter: ModerationFilter = 'approved'): any | null {
|
|
151
|
-
if (moderationFilter === 'all')
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
|
|
127
|
+
if (moderationFilter === 'all') return null;
|
|
155
128
|
if (moderationFilter === 'approved') {
|
|
156
|
-
// Approved OR null (backward compat: existing memories without moderation_status are approved)
|
|
157
129
|
return Filters.or(
|
|
158
130
|
collection.filter.byProperty('moderation_status').equal('approved'),
|
|
159
131
|
collection.filter.byProperty('moderation_status').isNull(true)
|
|
160
132
|
);
|
|
161
133
|
}
|
|
162
|
-
|
|
163
|
-
// Specific non-approved status
|
|
164
134
|
return collection.filter.byProperty('moderation_status').equal(moderationFilter);
|
|
165
135
|
}
|
|
166
136
|
|
|
167
137
|
/**
|
|
168
138
|
* Build base filters applied to all space/group collection queries.
|
|
169
|
-
*
|
|
170
|
-
* Includes moderation status filter (default: approved/null only).
|
|
139
|
+
* @deprecated Kept for test compatibility — logic now lives in remember-core SpaceService
|
|
171
140
|
*/
|
|
172
141
|
export function buildBaseFilters(collection: any, args: SearchSpaceArgs): any[] {
|
|
173
142
|
const filterList: any[] = [];
|
|
174
|
-
|
|
175
|
-
// Exclude soft-deleted memories (requires indexNullState: true on collection)
|
|
176
143
|
filterList.push(collection.filter.byProperty('deleted_at').isNull(true));
|
|
177
|
-
|
|
178
|
-
// Only return memories (not relationships)
|
|
179
144
|
filterList.push(collection.filter.byProperty('doc_type').equal('memory'));
|
|
180
|
-
|
|
181
|
-
// Moderation status filter
|
|
182
145
|
const moderationFilter = buildModerationFilter(collection, args.moderation_filter);
|
|
183
|
-
if (moderationFilter)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (args.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Exclude comments and ghost memories by default (unless content_type is explicitly set)
|
|
193
|
-
if (!args.include_comments && !args.content_type) {
|
|
194
|
-
filterList.push(collection.filter.byProperty('content_type').notEqual('comment'));
|
|
195
|
-
}
|
|
196
|
-
if (!args.content_type) {
|
|
197
|
-
filterList.push(collection.filter.byProperty('content_type').notEqual('ghost'));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Apply tags filter (AND semantics: memory must have ALL specified tags)
|
|
201
|
-
if (args.tags && args.tags.length > 0) {
|
|
202
|
-
args.tags.forEach(tag => {
|
|
203
|
-
filterList.push(collection.filter.byProperty('tags').containsAny([tag]));
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Apply weight filters
|
|
208
|
-
if (args.min_weight !== undefined) {
|
|
209
|
-
filterList.push(collection.filter.byProperty('weight').greaterOrEqual(args.min_weight));
|
|
210
|
-
}
|
|
211
|
-
if (args.max_weight !== undefined) {
|
|
212
|
-
filterList.push(collection.filter.byProperty('weight').lessOrEqual(args.max_weight));
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Apply date filters (created_at stored as ISO 8601 text, sorts lexicographically)
|
|
216
|
-
if (args.date_from) {
|
|
217
|
-
filterList.push(collection.filter.byProperty('created_at').greaterOrEqual(new Date(args.date_from)));
|
|
218
|
-
}
|
|
219
|
-
if (args.date_to) {
|
|
220
|
-
filterList.push(collection.filter.byProperty('created_at').lessOrEqual(new Date(args.date_to)));
|
|
221
|
-
}
|
|
222
|
-
|
|
146
|
+
if (moderationFilter) filterList.push(moderationFilter);
|
|
147
|
+
if (args.content_type) filterList.push(collection.filter.byProperty('content_type').equal(args.content_type));
|
|
148
|
+
if (!args.include_comments && !args.content_type) filterList.push(collection.filter.byProperty('content_type').notEqual('comment'));
|
|
149
|
+
if (!args.content_type) filterList.push(collection.filter.byProperty('content_type').notEqual('ghost'));
|
|
150
|
+
if (args.tags && args.tags.length > 0) args.tags.forEach(tag => filterList.push(collection.filter.byProperty('tags').containsAny([tag])));
|
|
151
|
+
if (args.min_weight !== undefined) filterList.push(collection.filter.byProperty('weight').greaterOrEqual(args.min_weight));
|
|
152
|
+
if (args.max_weight !== undefined) filterList.push(collection.filter.byProperty('weight').lessOrEqual(args.max_weight));
|
|
153
|
+
if (args.date_from) filterList.push(collection.filter.byProperty('created_at').greaterOrEqual(new Date(args.date_from)));
|
|
154
|
+
if (args.date_to) filterList.push(collection.filter.byProperty('created_at').lessOrEqual(new Date(args.date_to)));
|
|
223
155
|
return filterList;
|
|
224
156
|
}
|
|
225
157
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
switch (searchType) {
|
|
242
|
-
case 'bm25':
|
|
243
|
-
return (await collection.query.bm25(query, opts)).objects;
|
|
244
|
-
case 'semantic':
|
|
245
|
-
return (await collection.query.nearText([query], opts)).objects;
|
|
246
|
-
case 'hybrid':
|
|
247
|
-
default:
|
|
248
|
-
return (await collection.query.hybrid(query, opts)).objects;
|
|
249
|
-
}
|
|
158
|
+
interface SearchSpaceArgs {
|
|
159
|
+
query: string;
|
|
160
|
+
spaces?: string[];
|
|
161
|
+
groups?: string[];
|
|
162
|
+
search_type?: 'hybrid' | 'bm25' | 'semantic';
|
|
163
|
+
content_type?: string;
|
|
164
|
+
tags?: string[];
|
|
165
|
+
min_weight?: number;
|
|
166
|
+
max_weight?: number;
|
|
167
|
+
date_from?: string;
|
|
168
|
+
date_to?: string;
|
|
169
|
+
moderation_filter?: ModerationFilter;
|
|
170
|
+
include_comments?: boolean;
|
|
171
|
+
limit?: number;
|
|
172
|
+
offset?: number;
|
|
250
173
|
}
|
|
251
174
|
|
|
252
175
|
/**
|
|
@@ -267,212 +190,43 @@ export async function handleSearchSpace(
|
|
|
267
190
|
debug.info('Tool invoked');
|
|
268
191
|
debug.trace('Arguments', { args });
|
|
269
192
|
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
},
|
|
291
|
-
null,
|
|
292
|
-
2
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Validate group IDs
|
|
298
|
-
if (groups.length > 0) {
|
|
299
|
-
const invalidGroups = groups.filter(g => !g || g.includes('.') || g.trim() === '');
|
|
300
|
-
if (invalidGroups.length > 0) {
|
|
301
|
-
return JSON.stringify(
|
|
302
|
-
{
|
|
303
|
-
success: false,
|
|
304
|
-
error: 'Invalid group IDs',
|
|
305
|
-
message: 'Group IDs cannot be empty or contain dots',
|
|
306
|
-
context: { invalid_groups: invalidGroups },
|
|
307
|
-
},
|
|
308
|
-
null,
|
|
309
|
-
2
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Permission check: non-approved moderation filters require can_moderate
|
|
315
|
-
const moderationFilter = args.moderation_filter || 'approved';
|
|
316
|
-
if (moderationFilter !== 'approved') {
|
|
317
|
-
// For group searches: check can_moderate per group
|
|
318
|
-
for (const groupId of groups) {
|
|
319
|
-
if (!canModerate(authContext, groupId)) {
|
|
320
|
-
return JSON.stringify(
|
|
321
|
-
{
|
|
322
|
-
success: false,
|
|
323
|
-
error: 'Permission denied',
|
|
324
|
-
message: `Moderator access required to view ${moderationFilter} memories in group ${groupId}`,
|
|
325
|
-
},
|
|
326
|
-
null,
|
|
327
|
-
2
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
// For space searches: check can_moderate on any group
|
|
332
|
-
if ((spaces.length > 0 || groups.length === 0) && !canModerateAny(authContext)) {
|
|
333
|
-
return JSON.stringify(
|
|
334
|
-
{
|
|
335
|
-
success: false,
|
|
336
|
-
error: 'Permission denied',
|
|
337
|
-
message: `Moderator access required to view ${moderationFilter} memories in spaces`,
|
|
338
|
-
},
|
|
339
|
-
null,
|
|
340
|
-
2
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const weaviateClient = getWeaviateClient();
|
|
346
|
-
// Fetch enough results before pagination so we can deduplicate across sources
|
|
347
|
-
const fetchLimit = (limit + offset) * Math.max(1, groups.length + (spaces.length > 0 || groups.length === 0 ? 1 : 0));
|
|
348
|
-
const allObjects: any[] = [];
|
|
349
|
-
|
|
350
|
-
logger.info('Starting space/group search', {
|
|
351
|
-
tool: 'remember_search_space',
|
|
352
|
-
userId,
|
|
353
|
-
spaces,
|
|
354
|
-
groups,
|
|
355
|
-
searchType,
|
|
356
|
-
query: args.query,
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
// --- Space collection search ---
|
|
360
|
-
// Runs when spaces are specified, OR when neither spaces nor groups are specified (all-public)
|
|
361
|
-
if (spaces.length > 0 || groups.length === 0) {
|
|
362
|
-
const spacesCollectionName = getCollectionName(CollectionType.SPACES);
|
|
363
|
-
const spacesCollection = weaviateClient.collections.get(spacesCollectionName);
|
|
364
|
-
|
|
365
|
-
const filterList = buildBaseFilters(spacesCollection, args);
|
|
366
|
-
|
|
367
|
-
// Filter by space_ids array when specific spaces are requested
|
|
368
|
-
if (spaces.length > 0) {
|
|
369
|
-
filterList.push(spacesCollection.filter.byProperty('space_ids').containsAny(spaces));
|
|
370
|
-
}
|
|
371
|
-
// When spaces.length === 0 and groups.length === 0: no space_ids filter → all-public search
|
|
372
|
-
|
|
373
|
-
const whereFilter = filterList.length > 0 ? Filters.and(...filterList) : undefined;
|
|
374
|
-
|
|
375
|
-
debug.debug('Searching Memory_spaces_public', {
|
|
376
|
-
filterCount: filterList.length,
|
|
377
|
-
spaces,
|
|
378
|
-
allPublic: spaces.length === 0,
|
|
379
|
-
searchType,
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
const spaceObjects = await debug.time('Space collection search', async () => {
|
|
383
|
-
return await executeSearch(spacesCollection, args.query, searchType, whereFilter, fetchLimit);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
allObjects.push(...spaceObjects);
|
|
387
|
-
|
|
388
|
-
logger.info('Space collection search complete', {
|
|
389
|
-
tool: 'remember_search_space',
|
|
390
|
-
collectionName: spacesCollectionName,
|
|
391
|
-
resultCount: spaceObjects.length,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// --- Group collection searches ---
|
|
396
|
-
for (const groupId of groups) {
|
|
397
|
-
const groupCollectionName = getCollectionName(CollectionType.GROUPS, groupId);
|
|
398
|
-
|
|
399
|
-
// Skip if the group collection doesn't exist yet
|
|
400
|
-
const exists = await weaviateClient.collections.exists(groupCollectionName);
|
|
401
|
-
if (!exists) {
|
|
402
|
-
debug.warn('Group collection not found, skipping', { groupId, groupCollectionName });
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const groupCollection = weaviateClient.collections.get(groupCollectionName);
|
|
407
|
-
const filterList = buildBaseFilters(groupCollection, args);
|
|
408
|
-
const whereFilter = filterList.length > 0 ? Filters.and(...filterList) : undefined;
|
|
409
|
-
|
|
410
|
-
debug.debug('Searching group collection', {
|
|
411
|
-
groupId,
|
|
412
|
-
groupCollectionName,
|
|
413
|
-
filterCount: filterList.length,
|
|
414
|
-
searchType,
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
const groupObjects = await debug.time(`Group collection search: ${groupId}`, async () => {
|
|
418
|
-
return await executeSearch(groupCollection, args.query, searchType, whereFilter, fetchLimit);
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
allObjects.push(...groupObjects);
|
|
422
|
-
|
|
423
|
-
logger.info('Group collection search complete', {
|
|
424
|
-
tool: 'remember_search_space',
|
|
425
|
-
groupId,
|
|
426
|
-
collectionName: groupCollectionName,
|
|
427
|
-
resultCount: groupObjects.length,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// --- Deduplicate by UUID (composite ID) ---
|
|
432
|
-
const seen = new Set<string>();
|
|
433
|
-
const deduplicated = allObjects.filter(obj => {
|
|
434
|
-
if (seen.has(obj.uuid)) return false;
|
|
435
|
-
seen.add(obj.uuid);
|
|
436
|
-
return true;
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
// --- Sort by relevance score descending ---
|
|
440
|
-
deduplicated.sort((a, b) => {
|
|
441
|
-
const scoreA = a.metadata?.score ?? 0;
|
|
442
|
-
const scoreB = b.metadata?.score ?? 0;
|
|
443
|
-
return scoreB - scoreA;
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
// --- Apply pagination ---
|
|
447
|
-
const paginated = deduplicated.slice(offset, offset + limit);
|
|
448
|
-
|
|
449
|
-
// Format results
|
|
450
|
-
const memories = paginated.map(obj => ({
|
|
451
|
-
id: obj.uuid,
|
|
452
|
-
...obj.properties,
|
|
453
|
-
_score: obj.metadata?.score,
|
|
454
|
-
}));
|
|
455
|
-
|
|
456
|
-
const isAllPublic = spaces.length === 0 && groups.length === 0;
|
|
193
|
+
const { space } = createCoreServices(userId);
|
|
194
|
+
const result = await space.search(
|
|
195
|
+
{
|
|
196
|
+
query: args.query,
|
|
197
|
+
spaces: args.spaces,
|
|
198
|
+
groups: args.groups,
|
|
199
|
+
search_type: args.search_type,
|
|
200
|
+
content_type: args.content_type,
|
|
201
|
+
tags: args.tags,
|
|
202
|
+
min_weight: args.min_weight,
|
|
203
|
+
max_weight: args.max_weight,
|
|
204
|
+
date_from: args.date_from,
|
|
205
|
+
date_to: args.date_to,
|
|
206
|
+
moderation_filter: args.moderation_filter as any,
|
|
207
|
+
include_comments: args.include_comments,
|
|
208
|
+
limit: args.limit,
|
|
209
|
+
offset: args.offset,
|
|
210
|
+
},
|
|
211
|
+
authContext as any
|
|
212
|
+
);
|
|
457
213
|
|
|
458
|
-
const
|
|
459
|
-
spaces_searched:
|
|
460
|
-
groups_searched:
|
|
214
|
+
const response = {
|
|
215
|
+
spaces_searched: result.spaces_searched,
|
|
216
|
+
groups_searched: result.groups_searched,
|
|
461
217
|
query: args.query,
|
|
462
|
-
search_type:
|
|
463
|
-
memories,
|
|
464
|
-
total:
|
|
465
|
-
offset,
|
|
466
|
-
limit,
|
|
218
|
+
search_type: args.search_type || 'hybrid',
|
|
219
|
+
memories: result.memories,
|
|
220
|
+
total: result.total,
|
|
221
|
+
offset: result.offset,
|
|
222
|
+
limit: result.limit,
|
|
467
223
|
};
|
|
468
224
|
|
|
469
225
|
debug.info('Tool completed successfully', {
|
|
470
|
-
resultCount:
|
|
471
|
-
spaces,
|
|
472
|
-
groups,
|
|
226
|
+
resultCount: result.total,
|
|
473
227
|
});
|
|
474
228
|
|
|
475
|
-
return JSON.stringify(
|
|
229
|
+
return JSON.stringify(response, null, 2);
|
|
476
230
|
} catch (error) {
|
|
477
231
|
debug.error('Tool failed', {
|
|
478
232
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* Update user preferences through natural conversation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { PreferencesDatabaseService } from '../services/preferences-database.service.js';
|
|
7
|
-
import { logger } from '../utils/logger.js';
|
|
8
6
|
import { handleToolError } from '../utils/error-handler.js';
|
|
9
7
|
import { createDebugLogger } from '../utils/debug.js';
|
|
10
8
|
import {
|
|
@@ -13,6 +11,7 @@ import {
|
|
|
13
11
|
getPreferencesSchema,
|
|
14
12
|
} from '../types/preferences.js';
|
|
15
13
|
import type { AuthContext } from '../types/auth.js';
|
|
14
|
+
import { createCoreServices } from '../core-services.js';
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Tool definition for remember_set_preference
|
|
@@ -128,10 +127,8 @@ export async function handleSetPreference(
|
|
|
128
127
|
|
|
129
128
|
const { preferences } = args;
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// Update preferences using service layer
|
|
134
|
-
const updatedPreferences = await PreferencesDatabaseService.updatePreferences(
|
|
130
|
+
const { preferences: preferencesService } = createCoreServices(userId);
|
|
131
|
+
const updatedPreferences = await preferencesService.updatePreferences(
|
|
135
132
|
userId,
|
|
136
133
|
preferences
|
|
137
134
|
);
|
|
@@ -144,8 +141,6 @@ export async function handleSetPreference(
|
|
|
144
141
|
message,
|
|
145
142
|
};
|
|
146
143
|
|
|
147
|
-
logger.info('Preferences set successfully', { userId });
|
|
148
|
-
|
|
149
144
|
return JSON.stringify(result, null, 2);
|
|
150
145
|
} catch (error) {
|
|
151
146
|
debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
|