@prmichaelsen/remember-mcp 3.15.7 → 3.16.2
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/.github/workflows/publish.yml +55 -0
- package/CHANGELOG.md +20 -0
- package/agent/design/local.unified-internal-memory-tools.md +325 -0
- package/agent/milestones/milestone-20-unified-internal-memory-tools.md +58 -0
- package/agent/progress.yaml +115 -1
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-212-add-internal-context-type.md +54 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-213-update-server-factory-internal-context.md +117 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-214-create-tag-builder-utility.md +50 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-215-create-unified-internal-memory-tools.md +65 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-216-update-default-search-filters.md +46 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-217-delete-standalone-ghost-tools.md +46 -0
- package/agent/tasks/milestone-20-unified-internal-memory-tools/task-218-add-tests-unified-internal-tools.md +66 -0
- package/dist/e2e-helpers.d.ts +1 -1
- package/dist/server-factory.d.ts +17 -41
- package/dist/server-factory.js +420 -149
- package/dist/server.js +202 -20
- package/dist/tools/{create-ghost-memory.d.ts → create-internal-memory.d.ts} +7 -9
- package/dist/tools/internal-tools.spec.d.ts +2 -0
- package/dist/tools/{query-ghost-memory.d.ts → query-internal-memory.d.ts} +6 -6
- package/dist/tools/{search-ghost-memory-by.d.ts → search-internal-memory-by.d.ts} +6 -6
- package/dist/tools/{search-ghost-memory.d.ts → search-internal-memory.d.ts} +6 -6
- package/dist/tools/{update-ghost-memory.d.ts → update-internal-memory.d.ts} +6 -6
- package/dist/types/auth.d.ts +22 -8
- package/dist/utils/internal-tags.d.ts +14 -0
- package/dist/utils/internal-tags.spec.d.ts +2 -0
- package/package.json +2 -3
- package/src/e2e-helpers.ts +4 -2
- package/src/ghost-persona.e2e.ts +18 -17
- package/src/server-factory.ts +117 -55
- package/src/tools/create-internal-memory.ts +105 -0
- package/src/tools/find-similar.ts +2 -2
- package/src/tools/internal-tools.spec.ts +312 -0
- package/src/tools/query-internal-memory.ts +73 -0
- package/src/tools/query-memory.ts +15 -12
- package/src/tools/search-by.spec.ts +6 -2
- package/src/tools/search-by.ts +6 -6
- package/src/tools/{search-ghost-memory-by.ts → search-internal-memory-by.ts} +34 -27
- package/src/tools/search-internal-memory.ts +87 -0
- package/src/tools/search-memory.ts +15 -12
- package/src/tools/search-space.ts +1 -0
- package/src/tools/{update-ghost-memory.ts → update-internal-memory.ts} +23 -17
- package/src/types/auth.ts +22 -8
- package/src/utils/internal-tags.spec.ts +104 -0
- package/src/utils/internal-tags.ts +46 -0
- package/dist/tools/ghost-tools.spec.d.ts +0 -2
- package/src/tools/create-ghost-memory.ts +0 -103
- package/src/tools/ghost-tools.spec.ts +0 -361
- package/src/tools/query-ghost-memory.ts +0 -63
- package/src/tools/search-ghost-memory.ts +0 -73
|
@@ -1,361 +0,0 @@
|
|
|
1
|
-
import { createGhostMemoryTool, handleCreateGhostMemory } from './create-ghost-memory.js';
|
|
2
|
-
import { updateGhostMemoryTool, handleUpdateGhostMemory } from './update-ghost-memory.js';
|
|
3
|
-
import { searchGhostMemoryTool, handleSearchGhostMemory } from './search-ghost-memory.js';
|
|
4
|
-
import { queryGhostMemoryTool, handleQueryGhostMemory } from './query-ghost-memory.js';
|
|
5
|
-
import { searchGhostMemoryByTool, handleSearchGhostMemoryBy } from './search-ghost-memory-by.js';
|
|
6
|
-
|
|
7
|
-
// Mock core-services
|
|
8
|
-
const mockCreate = jest.fn();
|
|
9
|
-
const mockUpdate = jest.fn();
|
|
10
|
-
const mockByTime = jest.fn();
|
|
11
|
-
|
|
12
|
-
jest.mock('../core-services.js', () => ({
|
|
13
|
-
createCoreServices: jest.fn(() => ({
|
|
14
|
-
memory: {
|
|
15
|
-
create: mockCreate,
|
|
16
|
-
update: mockUpdate,
|
|
17
|
-
byTime: mockByTime,
|
|
18
|
-
byDensity: jest.fn().mockResolvedValue({ memories: [], total: 0, offset: 0, limit: 10 }),
|
|
19
|
-
byRating: jest.fn().mockResolvedValue({ memories: [], total: 0, offset: 0, limit: 10 }),
|
|
20
|
-
byDiscovery: jest.fn().mockResolvedValue({ memories: [], total: 0, offset: 0, limit: 10 }),
|
|
21
|
-
},
|
|
22
|
-
})),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
// Mock search-memory handler
|
|
26
|
-
const mockHandleSearchMemory = jest.fn();
|
|
27
|
-
jest.mock('./search-memory.js', () => ({
|
|
28
|
-
handleSearchMemory: (...args: any[]) => mockHandleSearchMemory(...args),
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
// Mock query-memory handler
|
|
32
|
-
const mockHandleQueryMemory = jest.fn();
|
|
33
|
-
jest.mock('./query-memory.js', () => ({
|
|
34
|
-
handleQueryMemory: (...args: any[]) => mockHandleQueryMemory(...args),
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
// Mock weaviate schema for update-ghost-memory
|
|
38
|
-
const mockFetchObjectById = jest.fn();
|
|
39
|
-
jest.mock('../weaviate/schema.js', () => ({
|
|
40
|
-
getMemoryCollection: jest.fn(() => ({
|
|
41
|
-
query: { fetchObjectById: mockFetchObjectById },
|
|
42
|
-
})),
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
jest.mock('../utils/debug.js', () => ({
|
|
46
|
-
createDebugLogger: () => ({
|
|
47
|
-
info: jest.fn(),
|
|
48
|
-
trace: jest.fn(),
|
|
49
|
-
error: jest.fn(),
|
|
50
|
-
}),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
describe('Ghost Memory Tools', () => {
|
|
54
|
-
const userId = 'test-user-1';
|
|
55
|
-
|
|
56
|
-
beforeEach(() => {
|
|
57
|
-
jest.clearAllMocks();
|
|
58
|
-
mockHandleSearchMemory.mockResolvedValue(JSON.stringify({ memories: [], total: 0 }));
|
|
59
|
-
mockHandleQueryMemory.mockResolvedValue(JSON.stringify({ memories: [], total: 0 }));
|
|
60
|
-
mockByTime.mockResolvedValue({ memories: [], total: 0, offset: 0, limit: 10 });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// ── create_ghost_memory ──
|
|
64
|
-
|
|
65
|
-
describe('remember_create_ghost_memory', () => {
|
|
66
|
-
it('has correct tool name', () => {
|
|
67
|
-
expect(createGhostMemoryTool.name).toBe('remember_create_ghost_memory');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('requires content', () => {
|
|
71
|
-
expect(createGhostMemoryTool.inputSchema.required).toContain('content');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('hardcodes content_type to ghost', async () => {
|
|
75
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
76
|
-
await handleCreateGhostMemory({ content: 'test ghost' }, userId);
|
|
77
|
-
expect(mockCreate).toHaveBeenCalledWith(
|
|
78
|
-
expect.objectContaining({ type: 'ghost' }),
|
|
79
|
-
);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('adds ghost tag automatically', async () => {
|
|
83
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
84
|
-
await handleCreateGhostMemory({ content: 'test' }, userId);
|
|
85
|
-
expect(mockCreate).toHaveBeenCalledWith(
|
|
86
|
-
expect.objectContaining({
|
|
87
|
-
tags: expect.arrayContaining(['ghost']),
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('adds ghost:{accessor_user_id} tag from auth context', async () => {
|
|
93
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
94
|
-
const authContext = {
|
|
95
|
-
accessToken: 'token',
|
|
96
|
-
credentials: null,
|
|
97
|
-
ghostMode: {
|
|
98
|
-
owner_user_id: 'owner-123',
|
|
99
|
-
accessor_user_id: 'accessor-456',
|
|
100
|
-
accessor_trust_level: 0.7,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
await handleCreateGhostMemory({ content: 'test' }, userId, authContext);
|
|
104
|
-
expect(mockCreate).toHaveBeenCalledWith(
|
|
105
|
-
expect.objectContaining({
|
|
106
|
-
tags: expect.arrayContaining(['ghost', 'ghost:accessor-456']),
|
|
107
|
-
}),
|
|
108
|
-
);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('merges user tags without duplicating ghost', async () => {
|
|
112
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
113
|
-
await handleCreateGhostMemory({ content: 'test', tags: ['ghost', 'custom'] }, userId);
|
|
114
|
-
const callArgs = mockCreate.mock.calls[0][0];
|
|
115
|
-
const ghostCount = callArgs.tags.filter((t: string) => t === 'ghost').length;
|
|
116
|
-
expect(ghostCount).toBe(1);
|
|
117
|
-
expect(callArgs.tags).toContain('custom');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('returns memory_id and content_type in response', async () => {
|
|
121
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
122
|
-
const result = await handleCreateGhostMemory({ content: 'test' }, userId);
|
|
123
|
-
const parsed = JSON.parse(result);
|
|
124
|
-
expect(parsed.memory_id).toBe('mem-1');
|
|
125
|
-
expect(parsed.content_type).toBe('ghost');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('passes feel_* fields through', async () => {
|
|
129
|
-
mockCreate.mockResolvedValue({ memory_id: 'mem-1', created_at: '2026-01-01' });
|
|
130
|
-
await handleCreateGhostMemory(
|
|
131
|
-
{ content: 'test', feel_salience: 0.8, feel_social_weight: 0.5 },
|
|
132
|
-
userId,
|
|
133
|
-
);
|
|
134
|
-
expect(mockCreate).toHaveBeenCalledWith(
|
|
135
|
-
expect.objectContaining({ feel_salience: 0.8, feel_social_weight: 0.5 }),
|
|
136
|
-
);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// ── update_ghost_memory ──
|
|
141
|
-
|
|
142
|
-
describe('remember_update_ghost_memory', () => {
|
|
143
|
-
it('has correct tool name', () => {
|
|
144
|
-
expect(updateGhostMemoryTool.name).toBe('remember_update_ghost_memory');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('requires memory_id', () => {
|
|
148
|
-
expect(updateGhostMemoryTool.inputSchema.required).toContain('memory_id');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('rejects non-ghost memories', async () => {
|
|
152
|
-
mockFetchObjectById.mockResolvedValue({
|
|
153
|
-
properties: { content_type: 'note' },
|
|
154
|
-
});
|
|
155
|
-
const result = await handleUpdateGhostMemory(
|
|
156
|
-
{ memory_id: 'mem-1', content: 'updated' },
|
|
157
|
-
userId,
|
|
158
|
-
);
|
|
159
|
-
const parsed = JSON.parse(result);
|
|
160
|
-
expect(parsed.error).toContain('not a ghost memory');
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('returns error for non-existent memory', async () => {
|
|
164
|
-
mockFetchObjectById.mockResolvedValue(null);
|
|
165
|
-
const result = await handleUpdateGhostMemory(
|
|
166
|
-
{ memory_id: 'mem-missing' },
|
|
167
|
-
userId,
|
|
168
|
-
);
|
|
169
|
-
const parsed = JSON.parse(result);
|
|
170
|
-
expect(parsed.error).toContain('not found');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('updates ghost memory successfully', async () => {
|
|
174
|
-
mockFetchObjectById.mockResolvedValue({
|
|
175
|
-
properties: { content_type: 'ghost' },
|
|
176
|
-
});
|
|
177
|
-
mockUpdate.mockResolvedValue({
|
|
178
|
-
memory_id: 'mem-1',
|
|
179
|
-
updated_at: '2026-01-01',
|
|
180
|
-
version: 2,
|
|
181
|
-
updated_fields: ['content'],
|
|
182
|
-
});
|
|
183
|
-
const result = await handleUpdateGhostMemory(
|
|
184
|
-
{ memory_id: 'mem-1', content: 'updated ghost' },
|
|
185
|
-
userId,
|
|
186
|
-
);
|
|
187
|
-
const parsed = JSON.parse(result);
|
|
188
|
-
expect(parsed.memory_id).toBe('mem-1');
|
|
189
|
-
expect(parsed.updated_fields).toContain('content');
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// ── search_ghost_memory ──
|
|
194
|
-
|
|
195
|
-
describe('remember_search_ghost_memory', () => {
|
|
196
|
-
it('has correct tool name', () => {
|
|
197
|
-
expect(searchGhostMemoryTool.name).toBe('remember_search_ghost_memory');
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('requires query', () => {
|
|
201
|
-
expect(searchGhostMemoryTool.inputSchema.required).toContain('query');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('hardcodes filters.types to ghost', async () => {
|
|
205
|
-
await handleSearchGhostMemory({ query: 'test' }, userId);
|
|
206
|
-
expect(mockHandleSearchMemory).toHaveBeenCalledWith(
|
|
207
|
-
expect.objectContaining({
|
|
208
|
-
filters: expect.objectContaining({ types: ['ghost'] }),
|
|
209
|
-
}),
|
|
210
|
-
userId,
|
|
211
|
-
undefined,
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('passes query and alpha through', async () => {
|
|
216
|
-
await handleSearchGhostMemory({ query: 'hello', alpha: 0.5 }, userId);
|
|
217
|
-
expect(mockHandleSearchMemory).toHaveBeenCalledWith(
|
|
218
|
-
expect.objectContaining({ query: 'hello', alpha: 0.5 }),
|
|
219
|
-
userId,
|
|
220
|
-
undefined,
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('passes tags through in filters', async () => {
|
|
225
|
-
await handleSearchGhostMemory({ query: 'test', tags: ['important'] }, userId);
|
|
226
|
-
expect(mockHandleSearchMemory).toHaveBeenCalledWith(
|
|
227
|
-
expect.objectContaining({
|
|
228
|
-
filters: expect.objectContaining({ tags: ['important'], types: ['ghost'] }),
|
|
229
|
-
}),
|
|
230
|
-
userId,
|
|
231
|
-
undefined,
|
|
232
|
-
);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('passes limit and offset', async () => {
|
|
236
|
-
await handleSearchGhostMemory({ query: 'test', limit: 20, offset: 5 }, userId);
|
|
237
|
-
expect(mockHandleSearchMemory).toHaveBeenCalledWith(
|
|
238
|
-
expect.objectContaining({ limit: 20, offset: 5 }),
|
|
239
|
-
userId,
|
|
240
|
-
undefined,
|
|
241
|
-
);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it('passes deleted_filter', async () => {
|
|
245
|
-
await handleSearchGhostMemory({ query: 'test', deleted_filter: 'only' }, userId);
|
|
246
|
-
expect(mockHandleSearchMemory).toHaveBeenCalledWith(
|
|
247
|
-
expect.objectContaining({ deleted_filter: 'only' }),
|
|
248
|
-
userId,
|
|
249
|
-
undefined,
|
|
250
|
-
);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// ── query_ghost_memory ──
|
|
255
|
-
|
|
256
|
-
describe('remember_query_ghost_memory', () => {
|
|
257
|
-
it('has correct tool name', () => {
|
|
258
|
-
expect(queryGhostMemoryTool.name).toBe('remember_query_ghost_memory');
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('requires query', () => {
|
|
262
|
-
expect(queryGhostMemoryTool.inputSchema.required).toContain('query');
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it('hardcodes filters.types to ghost', async () => {
|
|
266
|
-
await handleQueryGhostMemory({ query: 'what happened?' }, userId);
|
|
267
|
-
expect(mockHandleQueryMemory).toHaveBeenCalledWith(
|
|
268
|
-
expect.objectContaining({
|
|
269
|
-
filters: expect.objectContaining({ types: ['ghost'] }),
|
|
270
|
-
}),
|
|
271
|
-
userId,
|
|
272
|
-
undefined,
|
|
273
|
-
);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it('passes query through', async () => {
|
|
277
|
-
await handleQueryGhostMemory({ query: 'tell me about interactions' }, userId);
|
|
278
|
-
expect(mockHandleQueryMemory).toHaveBeenCalledWith(
|
|
279
|
-
expect.objectContaining({ query: 'tell me about interactions' }),
|
|
280
|
-
userId,
|
|
281
|
-
undefined,
|
|
282
|
-
);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it('passes limit and min_relevance', async () => {
|
|
286
|
-
await handleQueryGhostMemory({ query: 'test', limit: 10, min_relevance: 0.8 }, userId);
|
|
287
|
-
expect(mockHandleQueryMemory).toHaveBeenCalledWith(
|
|
288
|
-
expect.objectContaining({ limit: 10, min_relevance: 0.8 }),
|
|
289
|
-
userId,
|
|
290
|
-
undefined,
|
|
291
|
-
);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('passes authContext through', async () => {
|
|
295
|
-
const authContext = {
|
|
296
|
-
accessToken: 'token',
|
|
297
|
-
credentials: null,
|
|
298
|
-
ghostMode: {
|
|
299
|
-
owner_user_id: 'owner-123',
|
|
300
|
-
accessor_user_id: 'accessor-456',
|
|
301
|
-
accessor_trust_level: 0.7,
|
|
302
|
-
},
|
|
303
|
-
};
|
|
304
|
-
await handleQueryGhostMemory({ query: 'test' }, userId, authContext);
|
|
305
|
-
expect(mockHandleQueryMemory).toHaveBeenCalledWith(
|
|
306
|
-
expect.anything(),
|
|
307
|
-
userId,
|
|
308
|
-
authContext,
|
|
309
|
-
);
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// ── search_ghost_memory_by ──
|
|
314
|
-
|
|
315
|
-
describe('remember_search_ghost_memory_by', () => {
|
|
316
|
-
it('has correct tool name', () => {
|
|
317
|
-
expect(searchGhostMemoryByTool.name).toBe('remember_search_ghost_memory_by');
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('requires mode', () => {
|
|
321
|
-
expect(searchGhostMemoryByTool.inputSchema.required).toContain('mode');
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('hardcodes filters.types to ghost for byTime', async () => {
|
|
325
|
-
await handleSearchGhostMemoryBy({ mode: 'byTime' }, userId);
|
|
326
|
-
expect(mockByTime).toHaveBeenCalledWith(
|
|
327
|
-
expect.objectContaining({
|
|
328
|
-
filters: expect.objectContaining({ types: ['ghost'] }),
|
|
329
|
-
}),
|
|
330
|
-
);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it('passes sort_order through', async () => {
|
|
334
|
-
await handleSearchGhostMemoryBy({ mode: 'byTime', sort_order: 'asc' }, userId);
|
|
335
|
-
expect(mockByTime).toHaveBeenCalledWith(
|
|
336
|
-
expect.objectContaining({ direction: 'asc' }),
|
|
337
|
-
);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it('passes limit and offset', async () => {
|
|
341
|
-
await handleSearchGhostMemoryBy({ mode: 'byTime', limit: 20, offset: 5 }, userId);
|
|
342
|
-
expect(mockByTime).toHaveBeenCalledWith(
|
|
343
|
-
expect.objectContaining({ limit: 20, offset: 5 }),
|
|
344
|
-
);
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
it('passes deleted_filter', async () => {
|
|
348
|
-
await handleSearchGhostMemoryBy({ mode: 'byTime', deleted_filter: 'only' }, userId);
|
|
349
|
-
expect(mockByTime).toHaveBeenCalledWith(
|
|
350
|
-
expect.objectContaining({ deleted_filter: 'only' }),
|
|
351
|
-
);
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
it('has all mode options in schema', () => {
|
|
355
|
-
const modeProp = (searchGhostMemoryByTool.inputSchema.properties as any).mode;
|
|
356
|
-
expect(modeProp.enum).toEqual(
|
|
357
|
-
expect.arrayContaining(['byTime', 'byDensity', 'byRating', 'byDiscovery', 'byProperty', 'bySignificance', 'byRandom', 'byBroad']),
|
|
358
|
-
);
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* remember_query_ghost_memory tool
|
|
3
|
-
* Wraps query_memory with hardcoded ghost type filter
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { handleToolError } from '../utils/error-handler.js';
|
|
7
|
-
import { createDebugLogger } from '../utils/debug.js';
|
|
8
|
-
import type { AuthContext } from '../types/auth.js';
|
|
9
|
-
import { handleQueryMemory } from './query-memory.js';
|
|
10
|
-
|
|
11
|
-
export const queryGhostMemoryTool = {
|
|
12
|
-
name: 'remember_query_ghost_memory',
|
|
13
|
-
description: `Query ghost memories using natural language (pure semantic search).
|
|
14
|
-
Automatically filters to content_type: ghost.`,
|
|
15
|
-
inputSchema: {
|
|
16
|
-
type: 'object',
|
|
17
|
-
properties: {
|
|
18
|
-
query: { type: 'string', description: 'Natural language question' },
|
|
19
|
-
limit: { type: 'number', description: 'Max results. Default: 5' },
|
|
20
|
-
min_relevance: { type: 'number', description: 'Minimum relevance score. Default: 0.6' },
|
|
21
|
-
},
|
|
22
|
-
required: ['query'],
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export interface QueryGhostMemoryArgs {
|
|
27
|
-
query: string;
|
|
28
|
-
limit?: number;
|
|
29
|
-
min_relevance?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function handleQueryGhostMemory(
|
|
33
|
-
args: QueryGhostMemoryArgs,
|
|
34
|
-
userId: string,
|
|
35
|
-
authContext?: AuthContext
|
|
36
|
-
): Promise<string> {
|
|
37
|
-
const debug = createDebugLogger({ tool: 'remember_query_ghost_memory', userId, operation: 'query ghost memories' });
|
|
38
|
-
try {
|
|
39
|
-
debug.info('Tool invoked');
|
|
40
|
-
debug.trace('Arguments', { args });
|
|
41
|
-
|
|
42
|
-
// Delegate to query_memory with ghost type filter hardcoded
|
|
43
|
-
return await handleQueryMemory(
|
|
44
|
-
{
|
|
45
|
-
query: args.query,
|
|
46
|
-
limit: args.limit,
|
|
47
|
-
min_relevance: args.min_relevance,
|
|
48
|
-
filters: {
|
|
49
|
-
types: ['ghost'] as any,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
userId,
|
|
53
|
-
authContext
|
|
54
|
-
);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
|
|
57
|
-
handleToolError(error, {
|
|
58
|
-
toolName: 'remember_query_ghost_memory',
|
|
59
|
-
operation: 'query ghost memories',
|
|
60
|
-
userId,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* remember_search_ghost_memory tool
|
|
3
|
-
* Wraps search_memory with hardcoded ghost type filter
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { handleToolError } from '../utils/error-handler.js';
|
|
7
|
-
import { createDebugLogger } from '../utils/debug.js';
|
|
8
|
-
import type { AuthContext } from '../types/auth.js';
|
|
9
|
-
import { handleSearchMemory } from './search-memory.js';
|
|
10
|
-
|
|
11
|
-
export const searchGhostMemoryTool = {
|
|
12
|
-
name: 'remember_search_ghost_memory',
|
|
13
|
-
description: `Search ghost memories using hybrid semantic + keyword search.
|
|
14
|
-
Automatically filters to content_type: ghost. Use this to find specific
|
|
15
|
-
ghost interaction records.`,
|
|
16
|
-
inputSchema: {
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
query: { type: 'string', description: 'Search query' },
|
|
20
|
-
alpha: { type: 'number', minimum: 0, maximum: 1, description: 'Semantic vs keyword balance. Default: 0.7' },
|
|
21
|
-
tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags' },
|
|
22
|
-
limit: { type: 'number', description: 'Max results. Default: 10' },
|
|
23
|
-
offset: { type: 'number' },
|
|
24
|
-
deleted_filter: { type: 'string', enum: ['exclude', 'include', 'only'] },
|
|
25
|
-
},
|
|
26
|
-
required: ['query'],
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export interface SearchGhostMemoryArgs {
|
|
31
|
-
query: string;
|
|
32
|
-
alpha?: number;
|
|
33
|
-
tags?: string[];
|
|
34
|
-
limit?: number;
|
|
35
|
-
offset?: number;
|
|
36
|
-
deleted_filter?: 'exclude' | 'include' | 'only';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function handleSearchGhostMemory(
|
|
40
|
-
args: SearchGhostMemoryArgs,
|
|
41
|
-
userId: string,
|
|
42
|
-
authContext?: AuthContext
|
|
43
|
-
): Promise<string> {
|
|
44
|
-
const debug = createDebugLogger({ tool: 'remember_search_ghost_memory', userId, operation: 'search ghost memories' });
|
|
45
|
-
try {
|
|
46
|
-
debug.info('Tool invoked');
|
|
47
|
-
debug.trace('Arguments', { args });
|
|
48
|
-
|
|
49
|
-
// Delegate to search_memory with ghost type filter hardcoded
|
|
50
|
-
return await handleSearchMemory(
|
|
51
|
-
{
|
|
52
|
-
query: args.query,
|
|
53
|
-
alpha: args.alpha,
|
|
54
|
-
limit: args.limit,
|
|
55
|
-
offset: args.offset,
|
|
56
|
-
filters: {
|
|
57
|
-
types: ['ghost'] as any,
|
|
58
|
-
tags: args.tags,
|
|
59
|
-
},
|
|
60
|
-
deleted_filter: args.deleted_filter,
|
|
61
|
-
},
|
|
62
|
-
userId,
|
|
63
|
-
authContext
|
|
64
|
-
);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
|
|
67
|
-
handleToolError(error, {
|
|
68
|
-
toolName: 'remember_search_ghost_memory',
|
|
69
|
-
operation: 'search ghost memories',
|
|
70
|
-
userId,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|