@prmichaelsen/remember-mcp 2.5.2 → 2.6.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 +95 -0
- package/agent/milestones/milestone-12-comment-system.md +239 -0
- package/agent/tasks/task-55-add-comment-fields-to-schema.md +171 -0
- package/agent/tasks/task-56-update-search-space-for-comments.md +192 -0
- package/agent/tasks/task-57-update-query-space-for-comments.md +167 -0
- package/agent/tasks/task-58-add-comment-unit-tests.md +255 -0
- package/agent/tasks/task-59-update-documentation-for-comments.md +324 -0
- package/agent/tasks/task-60-standardize-structured-logging.md +300 -0
- package/agent/tasks/task-70-draft.md +13 -0
- package/dist/server-factory.js +342 -141
- package/dist/server.js +385 -158
- package/dist/tools/query-space.d.ts +1 -0
- package/dist/tools/search-space.d.ts +1 -0
- package/package.json +1 -1
- package/src/config.ts +8 -1
- package/src/firestore/init.ts +21 -6
- package/src/services/confirmation-token.service.ts +42 -23
- package/src/tools/confirm.ts +46 -15
- package/src/tools/publish.ts +34 -9
- package/src/tools/query-space.ts +23 -6
- package/src/tools/search-space.ts +14 -1
- package/src/weaviate/client.ts +29 -7
- package/src/weaviate/schema.ts +34 -4
- package/src/weaviate/space-schema.ts +28 -3
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
|
+
import { logger } from './utils/logger.js';
|
|
2
3
|
|
|
3
4
|
dotenv.config();
|
|
4
5
|
|
|
@@ -52,5 +53,11 @@ export function validateConfig(): void {
|
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
// Import logger here to avoid circular dependency
|
|
57
|
+
// Use dynamic import synchronously (logger is already loaded by this point)
|
|
58
|
+
import('./utils/logger.js').then(({ logger }) => {
|
|
59
|
+
logger.info('Configuration validated', {
|
|
60
|
+
module: 'config',
|
|
61
|
+
});
|
|
62
|
+
});
|
|
56
63
|
}
|
package/src/firestore/init.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { initializeApp } from '@prmichaelsen/firebase-admin-sdk-v8';
|
|
2
2
|
import { config } from '../config.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
3
4
|
|
|
4
5
|
let initialized = false;
|
|
5
6
|
|
|
@@ -23,11 +24,20 @@ export function initFirestore(): void {
|
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
initialized = true;
|
|
26
|
-
|
|
27
|
+
logger.info('Firestore initialized successfully', {
|
|
28
|
+
module: 'firestore-init',
|
|
29
|
+
});
|
|
27
30
|
} catch (error) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
logger.error('Firestore initialization failed', {
|
|
32
|
+
module: 'firestore-init',
|
|
33
|
+
error: error instanceof Error ? error.message : String(error),
|
|
34
|
+
});
|
|
35
|
+
logger.error('Make sure FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY is valid JSON', {
|
|
36
|
+
module: 'firestore-init',
|
|
37
|
+
});
|
|
38
|
+
logger.error('Check for proper escaping in .env file', {
|
|
39
|
+
module: 'firestore-init',
|
|
40
|
+
});
|
|
31
41
|
throw error;
|
|
32
42
|
}
|
|
33
43
|
}
|
|
@@ -52,10 +62,15 @@ export async function testFirestoreConnection(): Promise<boolean> {
|
|
|
52
62
|
const { getDocument } = await import('@prmichaelsen/firebase-admin-sdk-v8');
|
|
53
63
|
await getDocument('_health_check', 'test');
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
logger.info('Firestore connection test successful', {
|
|
66
|
+
module: 'firestore-init',
|
|
67
|
+
});
|
|
56
68
|
return true;
|
|
57
69
|
} catch (error) {
|
|
58
|
-
|
|
70
|
+
logger.error('Firestore connection test failed', {
|
|
71
|
+
module: 'firestore-init',
|
|
72
|
+
error: error instanceof Error ? error.message : String(error),
|
|
73
|
+
});
|
|
59
74
|
return false;
|
|
60
75
|
}
|
|
61
76
|
}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Confirmation Token Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Manages confirmation tokens for sensitive operations like publishing memories.
|
|
5
5
|
* Tokens are one-time use with 5-minute expiry.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { randomUUID } from 'crypto';
|
|
9
|
-
import {
|
|
10
|
-
getDocument,
|
|
11
|
-
addDocument,
|
|
9
|
+
import {
|
|
10
|
+
getDocument,
|
|
11
|
+
addDocument,
|
|
12
12
|
updateDocument,
|
|
13
13
|
queryDocuments,
|
|
14
|
-
type QueryOptions
|
|
14
|
+
type QueryOptions
|
|
15
15
|
} from '../firestore/init.js';
|
|
16
|
+
import { logger } from '../utils/logger.js';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Confirmation request stored in Firestore
|
|
@@ -69,21 +70,22 @@ export class ConfirmationTokenService {
|
|
|
69
70
|
|
|
70
71
|
// Add document to Firestore (auto-generates ID)
|
|
71
72
|
const collectionPath = `users/${userId}/requests`;
|
|
72
|
-
|
|
73
|
+
logger.info('Creating confirmation request', {
|
|
74
|
+
service: 'ConfirmationTokenService',
|
|
73
75
|
userId,
|
|
74
76
|
action,
|
|
75
77
|
targetCollection,
|
|
76
78
|
collectionPath,
|
|
77
|
-
|
|
78
|
-
token,
|
|
79
|
-
action,
|
|
80
|
-
payloadKeys: Object.keys(payload),
|
|
81
|
-
},
|
|
79
|
+
payloadKeys: Object.keys(payload),
|
|
82
80
|
});
|
|
83
81
|
|
|
84
|
-
|
|
82
|
+
logger.debug('Calling Firestore addDocument', {
|
|
83
|
+
service: 'ConfirmationTokenService',
|
|
84
|
+
collectionPath,
|
|
85
|
+
});
|
|
85
86
|
const docRef = await addDocument(collectionPath, request);
|
|
86
|
-
|
|
87
|
+
logger.debug('Firestore addDocument returned', {
|
|
88
|
+
service: 'ConfirmationTokenService',
|
|
87
89
|
hasDocRef: !!docRef,
|
|
88
90
|
hasId: !!docRef?.id,
|
|
89
91
|
docRefId: docRef?.id,
|
|
@@ -92,7 +94,8 @@ export class ConfirmationTokenService {
|
|
|
92
94
|
// Validate docRef
|
|
93
95
|
if (!docRef) {
|
|
94
96
|
const error = new Error('Firestore addDocument returned null/undefined');
|
|
95
|
-
|
|
97
|
+
logger.error('CRITICAL: addDocument returned null', {
|
|
98
|
+
service: 'ConfirmationTokenService',
|
|
96
99
|
userId,
|
|
97
100
|
collectionPath,
|
|
98
101
|
});
|
|
@@ -101,7 +104,8 @@ export class ConfirmationTokenService {
|
|
|
101
104
|
|
|
102
105
|
if (!docRef.id) {
|
|
103
106
|
const error = new Error('Firestore addDocument returned docRef without ID');
|
|
104
|
-
|
|
107
|
+
logger.error('CRITICAL: docRef has no ID', {
|
|
108
|
+
service: 'ConfirmationTokenService',
|
|
105
109
|
userId,
|
|
106
110
|
collectionPath,
|
|
107
111
|
docRef,
|
|
@@ -109,7 +113,8 @@ export class ConfirmationTokenService {
|
|
|
109
113
|
throw error;
|
|
110
114
|
}
|
|
111
115
|
|
|
112
|
-
|
|
116
|
+
logger.info('Confirmation request created successfully', {
|
|
117
|
+
service: 'ConfirmationTokenService',
|
|
113
118
|
requestId: docRef.id,
|
|
114
119
|
token,
|
|
115
120
|
expiresAt: request.expires_at,
|
|
@@ -117,7 +122,8 @@ export class ConfirmationTokenService {
|
|
|
117
122
|
|
|
118
123
|
return { requestId: docRef.id, token };
|
|
119
124
|
} catch (error) {
|
|
120
|
-
|
|
125
|
+
logger.error('Failed to create confirmation request', {
|
|
126
|
+
service: 'ConfirmationTokenService',
|
|
121
127
|
error: error instanceof Error ? error.message : String(error),
|
|
122
128
|
stack: error instanceof Error ? error.stack : undefined,
|
|
123
129
|
userId,
|
|
@@ -143,7 +149,8 @@ export class ConfirmationTokenService {
|
|
|
143
149
|
): Promise<(ConfirmationRequest & { request_id: string }) | null> {
|
|
144
150
|
const collectionPath = `users/${userId}/requests`;
|
|
145
151
|
|
|
146
|
-
|
|
152
|
+
logger.debug('Validating confirmation token', {
|
|
153
|
+
service: 'ConfirmationTokenService',
|
|
147
154
|
userId,
|
|
148
155
|
token,
|
|
149
156
|
collectionPath,
|
|
@@ -160,20 +167,25 @@ export class ConfirmationTokenService {
|
|
|
160
167
|
|
|
161
168
|
const results = await queryDocuments(collectionPath, queryOptions);
|
|
162
169
|
|
|
163
|
-
|
|
170
|
+
logger.debug('Token query results', {
|
|
171
|
+
service: 'ConfirmationTokenService',
|
|
164
172
|
resultsFound: results.length,
|
|
165
173
|
hasResults: results.length > 0,
|
|
166
174
|
});
|
|
167
175
|
|
|
168
176
|
if (results.length === 0) {
|
|
169
|
-
|
|
177
|
+
logger.info('Token not found or not pending', {
|
|
178
|
+
service: 'ConfirmationTokenService',
|
|
179
|
+
userId,
|
|
180
|
+
});
|
|
170
181
|
return null;
|
|
171
182
|
}
|
|
172
183
|
|
|
173
184
|
const doc = results[0];
|
|
174
185
|
const request = doc.data as ConfirmationRequest;
|
|
175
186
|
|
|
176
|
-
|
|
187
|
+
logger.info('Confirmation request found', {
|
|
188
|
+
service: 'ConfirmationTokenService',
|
|
177
189
|
requestId: doc.id,
|
|
178
190
|
action: request.action,
|
|
179
191
|
status: request.status,
|
|
@@ -183,7 +195,11 @@ export class ConfirmationTokenService {
|
|
|
183
195
|
// Check expiry
|
|
184
196
|
const expiresAt = new Date(request.expires_at);
|
|
185
197
|
if (expiresAt.getTime() < Date.now()) {
|
|
186
|
-
|
|
198
|
+
logger.info('Token expired', {
|
|
199
|
+
service: 'ConfirmationTokenService',
|
|
200
|
+
requestId: doc.id,
|
|
201
|
+
expiresAt: request.expires_at,
|
|
202
|
+
});
|
|
187
203
|
await this.updateStatus(userId, doc.id, 'expired');
|
|
188
204
|
return null;
|
|
189
205
|
}
|
|
@@ -298,7 +314,10 @@ export class ConfirmationTokenService {
|
|
|
298
314
|
// Note: firebase-admin-sdk-v8 doesn't support collectionGroup queries
|
|
299
315
|
// This would need to be implemented differently or rely on Firestore TTL
|
|
300
316
|
// For now, return 0 and rely on Firestore TTL policy
|
|
301
|
-
|
|
317
|
+
logger.warn('cleanupExpired not implemented - relying on Firestore TTL', {
|
|
318
|
+
service: 'ConfirmationTokenService',
|
|
319
|
+
note: 'Configure Firestore TTL policy on requests collection group',
|
|
320
|
+
});
|
|
302
321
|
return 0;
|
|
303
322
|
}
|
|
304
323
|
}
|
package/src/tools/confirm.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* remember_confirm tool
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Generic confirmation tool that executes any pending action.
|
|
5
5
|
* This is the second phase of the confirmation workflow.
|
|
6
6
|
*/
|
|
@@ -10,6 +10,7 @@ import { confirmationTokenService, type ConfirmationRequest } from '../services/
|
|
|
10
10
|
import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.js';
|
|
11
11
|
import { ensurePublicCollection } from '../weaviate/space-schema.js';
|
|
12
12
|
import { handleToolError } from '../utils/error-handler.js';
|
|
13
|
+
import { logger } from '../utils/logger.js';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Tool definition for remember_confirm
|
|
@@ -41,7 +42,8 @@ export async function handleConfirm(
|
|
|
41
42
|
userId: string
|
|
42
43
|
): Promise<string> {
|
|
43
44
|
try {
|
|
44
|
-
|
|
45
|
+
logger.info('Starting confirmation', {
|
|
46
|
+
tool: 'remember_confirm',
|
|
45
47
|
userId,
|
|
46
48
|
token: args.token,
|
|
47
49
|
});
|
|
@@ -49,13 +51,17 @@ export async function handleConfirm(
|
|
|
49
51
|
// Validate and confirm token
|
|
50
52
|
const request = await confirmationTokenService.confirmRequest(userId, args.token);
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
logger.debug('Token validation result', {
|
|
55
|
+
tool: 'remember_confirm',
|
|
53
56
|
requestFound: !!request,
|
|
54
57
|
action: request?.action,
|
|
55
58
|
});
|
|
56
59
|
|
|
57
60
|
if (!request) {
|
|
58
|
-
|
|
61
|
+
logger.info('Token invalid or expired', {
|
|
62
|
+
tool: 'remember_confirm',
|
|
63
|
+
userId,
|
|
64
|
+
});
|
|
59
65
|
return JSON.stringify(
|
|
60
66
|
{
|
|
61
67
|
success: false,
|
|
@@ -67,7 +73,11 @@ export async function handleConfirm(
|
|
|
67
73
|
);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
logger.info('Executing confirmed action', {
|
|
77
|
+
tool: 'remember_confirm',
|
|
78
|
+
action: request.action,
|
|
79
|
+
userId,
|
|
80
|
+
});
|
|
71
81
|
|
|
72
82
|
// GENERIC: Execute action based on type
|
|
73
83
|
// This is where the generic pattern delegates to action-specific executors
|
|
@@ -99,7 +109,8 @@ async function executePublishMemory(
|
|
|
99
109
|
userId: string
|
|
100
110
|
): Promise<string> {
|
|
101
111
|
try {
|
|
102
|
-
|
|
112
|
+
logger.info('Executing publish memory action', {
|
|
113
|
+
function: 'executePublishMemory',
|
|
103
114
|
userId,
|
|
104
115
|
memoryId: request.payload.memory_id,
|
|
105
116
|
spaces: request.payload.spaces,
|
|
@@ -112,19 +123,27 @@ async function executePublishMemory(
|
|
|
112
123
|
getMemoryCollectionName(userId)
|
|
113
124
|
);
|
|
114
125
|
|
|
115
|
-
|
|
126
|
+
logger.debug('Fetching original memory', {
|
|
127
|
+
function: 'executePublishMemory',
|
|
128
|
+
collectionName: getMemoryCollectionName(userId),
|
|
129
|
+
memoryId: request.payload.memory_id,
|
|
130
|
+
});
|
|
116
131
|
|
|
117
132
|
const originalMemory = await userCollection.query.fetchObjectById(
|
|
118
133
|
request.payload.memory_id
|
|
119
134
|
);
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
logger.debug('Original memory fetch result', {
|
|
137
|
+
function: 'executePublishMemory',
|
|
122
138
|
found: !!originalMemory,
|
|
123
139
|
memoryId: request.payload.memory_id,
|
|
124
140
|
});
|
|
125
141
|
|
|
126
142
|
if (!originalMemory) {
|
|
127
|
-
|
|
143
|
+
logger.info('Original memory not found', {
|
|
144
|
+
function: 'executePublishMemory',
|
|
145
|
+
memoryId: request.payload.memory_id,
|
|
146
|
+
});
|
|
128
147
|
return JSON.stringify(
|
|
129
148
|
{
|
|
130
149
|
success: false,
|
|
@@ -138,7 +157,12 @@ async function executePublishMemory(
|
|
|
138
157
|
|
|
139
158
|
// Verify ownership again
|
|
140
159
|
if (originalMemory.properties.user_id !== userId) {
|
|
141
|
-
|
|
160
|
+
logger.warn('Permission denied - wrong owner', {
|
|
161
|
+
function: 'executePublishMemory',
|
|
162
|
+
memoryId: request.payload.memory_id,
|
|
163
|
+
memoryOwner: originalMemory.properties.user_id,
|
|
164
|
+
requestingUser: userId,
|
|
165
|
+
});
|
|
142
166
|
return JSON.stringify(
|
|
143
167
|
{
|
|
144
168
|
success: false,
|
|
@@ -150,12 +174,17 @@ async function executePublishMemory(
|
|
|
150
174
|
);
|
|
151
175
|
}
|
|
152
176
|
|
|
153
|
-
|
|
177
|
+
logger.debug('Ensuring public collection exists', {
|
|
178
|
+
function: 'executePublishMemory',
|
|
179
|
+
});
|
|
154
180
|
|
|
155
181
|
// Get unified public collection
|
|
156
182
|
const publicCollection = await ensurePublicCollection(weaviateClient);
|
|
157
183
|
|
|
158
|
-
|
|
184
|
+
logger.debug('Public collection ready', {
|
|
185
|
+
function: 'executePublishMemory',
|
|
186
|
+
collectionName: 'Memory_public',
|
|
187
|
+
});
|
|
159
188
|
|
|
160
189
|
// Create published memory (copy with modifications)
|
|
161
190
|
const originalTags = Array.isArray(originalMemory.properties.tags)
|
|
@@ -183,7 +212,8 @@ async function executePublishMemory(
|
|
|
183
212
|
version: 1,
|
|
184
213
|
};
|
|
185
214
|
|
|
186
|
-
|
|
215
|
+
logger.info('Inserting memory into Memory_public', {
|
|
216
|
+
function: 'executePublishMemory',
|
|
187
217
|
spaces: request.payload.spaces,
|
|
188
218
|
spaceCount: request.payload.spaces?.length || 0,
|
|
189
219
|
memoryId: request.payload.memory_id,
|
|
@@ -194,9 +224,10 @@ async function executePublishMemory(
|
|
|
194
224
|
// Insert directly into unified public collection
|
|
195
225
|
const result = await publicCollection.data.insert(publishedMemory as any);
|
|
196
226
|
|
|
197
|
-
|
|
198
|
-
|
|
227
|
+
logger.info('Memory published successfully', {
|
|
228
|
+
function: 'executePublishMemory',
|
|
199
229
|
spaceMemoryId: result,
|
|
230
|
+
spaces: request.payload.spaces,
|
|
200
231
|
});
|
|
201
232
|
|
|
202
233
|
// Return minimal response with spaces array
|
package/src/tools/publish.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* remember_publish tool
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Generates a confirmation token for publishing a memory to a shared space.
|
|
5
5
|
* This is the first phase of the two-phase publish workflow.
|
|
6
6
|
*/
|
|
@@ -11,6 +11,7 @@ import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.j
|
|
|
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';
|
|
14
|
+
import { logger } from '../utils/logger.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Tool definition for remember_publish
|
|
@@ -60,7 +61,8 @@ export async function handlePublish(
|
|
|
60
61
|
userId: string
|
|
61
62
|
): Promise<string> {
|
|
62
63
|
try {
|
|
63
|
-
|
|
64
|
+
logger.info('Starting publish request', {
|
|
65
|
+
tool: 'remember_publish',
|
|
64
66
|
userId,
|
|
65
67
|
memoryId: args.memory_id,
|
|
66
68
|
spaces: args.spaces,
|
|
@@ -71,7 +73,11 @@ export async function handlePublish(
|
|
|
71
73
|
// Validate all space IDs
|
|
72
74
|
const invalidSpaces = args.spaces.filter(s => !isValidSpaceId(s));
|
|
73
75
|
if (invalidSpaces.length > 0) {
|
|
74
|
-
|
|
76
|
+
logger.warn('Invalid space IDs provided', {
|
|
77
|
+
tool: 'remember_publish',
|
|
78
|
+
invalidSpaces,
|
|
79
|
+
providedSpaces: args.spaces,
|
|
80
|
+
});
|
|
75
81
|
return JSON.stringify(
|
|
76
82
|
{
|
|
77
83
|
success: false,
|
|
@@ -90,7 +96,10 @@ export async function handlePublish(
|
|
|
90
96
|
|
|
91
97
|
// Validate not empty
|
|
92
98
|
if (args.spaces.length === 0) {
|
|
93
|
-
|
|
99
|
+
logger.warn('Empty spaces array provided', {
|
|
100
|
+
tool: 'remember_publish',
|
|
101
|
+
userId,
|
|
102
|
+
});
|
|
94
103
|
return JSON.stringify(
|
|
95
104
|
{
|
|
96
105
|
success: false,
|
|
@@ -105,19 +114,28 @@ export async function handlePublish(
|
|
|
105
114
|
// Verify memory exists and user owns it
|
|
106
115
|
const weaviateClient = getWeaviateClient();
|
|
107
116
|
const collectionName = getMemoryCollectionName(userId);
|
|
108
|
-
|
|
117
|
+
logger.debug('Fetching memory from collection', {
|
|
118
|
+
tool: 'remember_publish',
|
|
119
|
+
collectionName,
|
|
120
|
+
memoryId: args.memory_id,
|
|
121
|
+
});
|
|
109
122
|
|
|
110
123
|
const userCollection = weaviateClient.collections.get(collectionName);
|
|
111
124
|
|
|
112
125
|
const memory = await userCollection.query.fetchObjectById(args.memory_id);
|
|
113
126
|
|
|
114
|
-
|
|
127
|
+
logger.debug('Memory fetch result', {
|
|
128
|
+
tool: 'remember_publish',
|
|
115
129
|
found: !!memory,
|
|
116
130
|
memoryId: args.memory_id,
|
|
117
131
|
});
|
|
118
132
|
|
|
119
133
|
if (!memory) {
|
|
120
|
-
|
|
134
|
+
logger.info('Memory not found', {
|
|
135
|
+
tool: 'remember_publish',
|
|
136
|
+
memoryId: args.memory_id,
|
|
137
|
+
collectionName,
|
|
138
|
+
});
|
|
121
139
|
return JSON.stringify(
|
|
122
140
|
{
|
|
123
141
|
success: false,
|
|
@@ -175,7 +193,12 @@ export async function handlePublish(
|
|
|
175
193
|
additional_tags: args.additional_tags || [],
|
|
176
194
|
};
|
|
177
195
|
|
|
178
|
-
|
|
196
|
+
logger.info('Generating confirmation token', {
|
|
197
|
+
tool: 'remember_publish',
|
|
198
|
+
userId,
|
|
199
|
+
memoryId: args.memory_id,
|
|
200
|
+
spaces: args.spaces,
|
|
201
|
+
});
|
|
179
202
|
|
|
180
203
|
// Generate confirmation token
|
|
181
204
|
const { requestId, token} = await confirmationTokenService.createRequest(
|
|
@@ -185,10 +208,12 @@ export async function handlePublish(
|
|
|
185
208
|
undefined // No single target_collection anymore
|
|
186
209
|
);
|
|
187
210
|
|
|
188
|
-
|
|
211
|
+
logger.info('Confirmation token generated', {
|
|
212
|
+
tool: 'remember_publish',
|
|
189
213
|
requestId,
|
|
190
214
|
token,
|
|
191
215
|
action: 'publish_memory',
|
|
216
|
+
spaces: args.spaces,
|
|
192
217
|
});
|
|
193
218
|
|
|
194
219
|
// Return minimal response - agent already knows memory details
|
package/src/tools/query-space.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { handleToolError } from '../utils/error-handler.js';
|
|
|
17
17
|
*/
|
|
18
18
|
export const querySpaceTool: Tool = {
|
|
19
19
|
name: 'remember_query_space',
|
|
20
|
-
description: 'Ask natural language questions about memories in shared spaces.
|
|
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
21
|
inputSchema: {
|
|
22
22
|
type: 'object',
|
|
23
23
|
properties: {
|
|
@@ -25,11 +25,15 @@ export const querySpaceTool: Tool = {
|
|
|
25
25
|
type: 'string',
|
|
26
26
|
description: 'Natural language question',
|
|
27
27
|
},
|
|
28
|
-
|
|
29
|
-
type: '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
spaces: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
enum: SUPPORTED_SPACES,
|
|
33
|
+
},
|
|
34
|
+
description: 'Spaces to query (e.g., ["the_void", "dogs"])',
|
|
35
|
+
minItems: 1,
|
|
36
|
+
default: ['the_void'],
|
|
33
37
|
},
|
|
34
38
|
content_type: {
|
|
35
39
|
type: 'string',
|
|
@@ -54,6 +58,11 @@ export const querySpaceTool: Tool = {
|
|
|
54
58
|
type: 'string',
|
|
55
59
|
description: 'Filter memories created before this date (ISO 8601)',
|
|
56
60
|
},
|
|
61
|
+
include_comments: {
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
description: 'Include comments in query results (default: false)',
|
|
64
|
+
default: false,
|
|
65
|
+
},
|
|
57
66
|
limit: {
|
|
58
67
|
type: 'number',
|
|
59
68
|
default: 10,
|
|
@@ -78,6 +87,7 @@ interface QuerySpaceArgs {
|
|
|
78
87
|
min_weight?: number;
|
|
79
88
|
date_from?: string;
|
|
80
89
|
date_to?: string;
|
|
90
|
+
include_comments?: boolean;
|
|
81
91
|
limit?: number;
|
|
82
92
|
format?: 'detailed' | 'compact';
|
|
83
93
|
}
|
|
@@ -134,6 +144,13 @@ export async function handleQuerySpace(
|
|
|
134
144
|
filterList.push(publicCollection.filter.byProperty('type').equal(args.content_type));
|
|
135
145
|
}
|
|
136
146
|
|
|
147
|
+
// Exclude comments by default (unless explicitly included)
|
|
148
|
+
if (!args.include_comments && !args.content_type) {
|
|
149
|
+
// Only exclude comments if not filtering by content_type
|
|
150
|
+
// (if content_type is set, user has explicit control)
|
|
151
|
+
filterList.push(publicCollection.filter.byProperty('type').notEqual('comment'));
|
|
152
|
+
}
|
|
153
|
+
|
|
137
154
|
// Apply tags filter
|
|
138
155
|
if (args.tags && args.tags.length > 0) {
|
|
139
156
|
args.tags.forEach(tag => {
|
|
@@ -18,7 +18,7 @@ import type { SearchFilters } from '../types/memory.js';
|
|
|
18
18
|
*/
|
|
19
19
|
export const searchSpaceTool: Tool = {
|
|
20
20
|
name: 'remember_search_space',
|
|
21
|
-
description: 'Search one or more shared spaces to discover thoughts, ideas, and memories.
|
|
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
22
|
inputSchema: {
|
|
23
23
|
type: 'object',
|
|
24
24
|
properties: {
|
|
@@ -65,6 +65,11 @@ export const searchSpaceTool: Tool = {
|
|
|
65
65
|
type: 'string',
|
|
66
66
|
description: 'Filter memories created before this date (ISO 8601)',
|
|
67
67
|
},
|
|
68
|
+
include_comments: {
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
description: 'Include comments in search results (default: false)',
|
|
71
|
+
default: false,
|
|
72
|
+
},
|
|
68
73
|
limit: {
|
|
69
74
|
type: 'number',
|
|
70
75
|
default: 10,
|
|
@@ -89,6 +94,7 @@ interface SearchSpaceArgs {
|
|
|
89
94
|
max_weight?: number;
|
|
90
95
|
date_from?: string;
|
|
91
96
|
date_to?: string;
|
|
97
|
+
include_comments?: boolean;
|
|
92
98
|
limit?: number;
|
|
93
99
|
offset?: number;
|
|
94
100
|
}
|
|
@@ -150,6 +156,13 @@ export async function handleSearchSpace(
|
|
|
150
156
|
filterList.push(publicCollection.filter.byProperty('type').equal(args.content_type));
|
|
151
157
|
}
|
|
152
158
|
|
|
159
|
+
// Exclude comments by default (unless explicitly included)
|
|
160
|
+
if (!args.include_comments && !args.content_type) {
|
|
161
|
+
// Only exclude comments if not filtering by content_type
|
|
162
|
+
// (if content_type is set, user has explicit control)
|
|
163
|
+
filterList.push(publicCollection.filter.byProperty('type').notEqual('comment'));
|
|
164
|
+
}
|
|
165
|
+
|
|
153
166
|
// Apply tags filter
|
|
154
167
|
if (args.tags && args.tags.length > 0) {
|
|
155
168
|
args.tags.forEach(tag => {
|