@botmem/cli 0.10.1 → 0.11.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/dist/__tests__/cli.test.d.ts +1 -0
- package/dist/__tests__/cli.test.js +218 -0
- package/dist/__tests__/cli.test.js.map +1 -0
- package/dist/__tests__/client.test.d.ts +1 -0
- package/dist/__tests__/client.test.js +426 -0
- package/dist/__tests__/client.test.js.map +1 -0
- package/dist/__tests__/commands.test.d.ts +1 -0
- package/dist/__tests__/commands.test.js +821 -0
- package/dist/__tests__/commands.test.js.map +1 -0
- package/dist/__tests__/format.test.d.ts +1 -0
- package/dist/__tests__/format.test.js +458 -0
- package/dist/__tests__/format.test.js.map +1 -0
- package/dist/cli.js +8 -60
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +0 -8
- package/dist/client.js +0 -8
- package/dist/client.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const vitest_1 = require("vitest");
|
|
37
|
+
// Mock the format module to avoid ANSI noise
|
|
38
|
+
vitest_1.vi.mock('../format.js', async () => {
|
|
39
|
+
const actual = await vitest_1.vi.importActual('../format.js');
|
|
40
|
+
return {
|
|
41
|
+
...actual,
|
|
42
|
+
// Keep real implementations — we just need the module to be importable
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
// Helper to create a mock client
|
|
46
|
+
function createMockClient() {
|
|
47
|
+
return {
|
|
48
|
+
searchMemories: vitest_1.vi.fn().mockResolvedValue({ items: [], fallback: false }),
|
|
49
|
+
listMemories: vitest_1.vi.fn().mockResolvedValue({ items: [], total: 0 }),
|
|
50
|
+
getMemory: vitest_1.vi.fn().mockResolvedValue({
|
|
51
|
+
id: 'm1',
|
|
52
|
+
text: 'test',
|
|
53
|
+
sourceType: 'email',
|
|
54
|
+
connectorType: 'gmail',
|
|
55
|
+
eventTime: '2025-01-01',
|
|
56
|
+
importance: null,
|
|
57
|
+
factuality: null,
|
|
58
|
+
embeddingStatus: 'done',
|
|
59
|
+
entities: null,
|
|
60
|
+
}),
|
|
61
|
+
deleteMemory: vitest_1.vi.fn().mockResolvedValue({ ok: true }),
|
|
62
|
+
getMemoryStats: vitest_1.vi.fn().mockResolvedValue({
|
|
63
|
+
total: 100,
|
|
64
|
+
bySource: {},
|
|
65
|
+
byConnector: {},
|
|
66
|
+
byFactuality: {},
|
|
67
|
+
}),
|
|
68
|
+
listContacts: vitest_1.vi.fn().mockResolvedValue({ items: [], total: 0 }),
|
|
69
|
+
searchContacts: vitest_1.vi.fn().mockResolvedValue([]),
|
|
70
|
+
getContact: vitest_1.vi.fn().mockResolvedValue({
|
|
71
|
+
id: 'c1',
|
|
72
|
+
displayName: 'Test',
|
|
73
|
+
identifiers: [],
|
|
74
|
+
}),
|
|
75
|
+
getContactMemories: vitest_1.vi.fn().mockResolvedValue([]),
|
|
76
|
+
agentAsk: vitest_1.vi.fn().mockResolvedValue({ answer: 'test answer' }),
|
|
77
|
+
agentSummarize: vitest_1.vi.fn().mockResolvedValue({ summary: 'test summary' }),
|
|
78
|
+
agentContext: vitest_1.vi.fn().mockResolvedValue({ contact: { displayName: 'Test' } }),
|
|
79
|
+
listJobs: vitest_1.vi.fn().mockResolvedValue({ jobs: [] }),
|
|
80
|
+
triggerSync: vitest_1.vi.fn().mockResolvedValue({ job: { id: 'j1' } }),
|
|
81
|
+
retryFailedJobs: vitest_1.vi.fn().mockResolvedValue({ ok: true, retried: 2 }),
|
|
82
|
+
retryFailedMemories: vitest_1.vi.fn().mockResolvedValue({ enqueued: 3, total: 5 }),
|
|
83
|
+
listAccounts: vitest_1.vi.fn().mockResolvedValue({ accounts: [] }),
|
|
84
|
+
getVersion: vitest_1.vi.fn().mockResolvedValue({
|
|
85
|
+
buildTime: '2025-01-01',
|
|
86
|
+
gitHash: 'abc',
|
|
87
|
+
uptime: 3600,
|
|
88
|
+
}),
|
|
89
|
+
getTimeline: vitest_1.vi.fn().mockResolvedValue({ items: [], total: 0 }),
|
|
90
|
+
getRelated: vitest_1.vi.fn().mockResolvedValue({ items: [], source: null }),
|
|
91
|
+
searchEntities: vitest_1.vi.fn().mockResolvedValue({ entities: [], total: 0 }),
|
|
92
|
+
getEntityGraph: vitest_1.vi.fn().mockResolvedValue({
|
|
93
|
+
entity: 'Test',
|
|
94
|
+
memories: [],
|
|
95
|
+
relatedEntities: [],
|
|
96
|
+
contacts: [],
|
|
97
|
+
memoryCount: 0,
|
|
98
|
+
}),
|
|
99
|
+
listMemoryBanks: vitest_1.vi.fn().mockResolvedValue([]),
|
|
100
|
+
createMemoryBank: vitest_1.vi.fn().mockResolvedValue({ id: 'b1', name: 'Work' }),
|
|
101
|
+
renameMemoryBank: vitest_1.vi.fn().mockResolvedValue({ id: 'b1', name: 'Personal' }),
|
|
102
|
+
deleteMemoryBank: vitest_1.vi.fn().mockResolvedValue(undefined),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
let logSpy;
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
+
let errorSpy;
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
|
+
let exitSpy;
|
|
111
|
+
/** Helper to extract a logged string from spy calls (avoids `unknown` type errors). */
|
|
112
|
+
function logged(spy, call = 0, arg = 0) {
|
|
113
|
+
return spy.mock.calls[call][arg];
|
|
114
|
+
}
|
|
115
|
+
(0, vitest_1.beforeEach)(() => {
|
|
116
|
+
logSpy = vitest_1.vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
117
|
+
errorSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
118
|
+
exitSpy = vitest_1.vi.spyOn(process, 'exit').mockImplementation((() => { }));
|
|
119
|
+
});
|
|
120
|
+
(0, vitest_1.afterEach)(() => {
|
|
121
|
+
logSpy.mockRestore();
|
|
122
|
+
errorSpy.mockRestore();
|
|
123
|
+
exitSpy.mockRestore();
|
|
124
|
+
});
|
|
125
|
+
// --- Search ---
|
|
126
|
+
(0, vitest_1.describe)('runSearch', () => {
|
|
127
|
+
let runSearch;
|
|
128
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
129
|
+
({ runSearch } = await Promise.resolve().then(() => __importStar(require('../commands/search.js'))));
|
|
130
|
+
});
|
|
131
|
+
(0, vitest_1.it)('should search with query words', async () => {
|
|
132
|
+
const client = createMockClient();
|
|
133
|
+
await runSearch(client, ['hello', 'world'], false);
|
|
134
|
+
(0, vitest_1.expect)(client.searchMemories).toHaveBeenCalledWith('hello world', undefined, undefined, undefined);
|
|
135
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalled();
|
|
136
|
+
});
|
|
137
|
+
(0, vitest_1.it)('should pass filters and limit', async () => {
|
|
138
|
+
const client = createMockClient();
|
|
139
|
+
await runSearch(client, [
|
|
140
|
+
'test',
|
|
141
|
+
'--source',
|
|
142
|
+
'email',
|
|
143
|
+
'--connector',
|
|
144
|
+
'gmail',
|
|
145
|
+
'--limit',
|
|
146
|
+
'5',
|
|
147
|
+
'--memory-bank',
|
|
148
|
+
'bank-1',
|
|
149
|
+
], false);
|
|
150
|
+
(0, vitest_1.expect)(client.searchMemories).toHaveBeenCalledWith('test', { sourceType: 'email', connectorType: 'gmail' }, 5, 'bank-1');
|
|
151
|
+
});
|
|
152
|
+
(0, vitest_1.it)('should output JSON when json=true', async () => {
|
|
153
|
+
const client = createMockClient();
|
|
154
|
+
await runSearch(client, ['test'], true);
|
|
155
|
+
const output = logged(logSpy, 0, 0);
|
|
156
|
+
(0, vitest_1.expect)(() => JSON.parse(output)).not.toThrow();
|
|
157
|
+
});
|
|
158
|
+
(0, vitest_1.it)('should exit when no query provided', async () => {
|
|
159
|
+
const client = createMockClient();
|
|
160
|
+
await runSearch(client, [], false);
|
|
161
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a query'));
|
|
162
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
163
|
+
});
|
|
164
|
+
(0, vitest_1.it)('should display resolved entities info when present', async () => {
|
|
165
|
+
const client = createMockClient();
|
|
166
|
+
client.searchMemories.mockResolvedValue({
|
|
167
|
+
items: [
|
|
168
|
+
{
|
|
169
|
+
id: 'm1',
|
|
170
|
+
text: 'test',
|
|
171
|
+
sourceType: 'email',
|
|
172
|
+
connectorType: 'gmail',
|
|
173
|
+
eventTime: '2025-01-01',
|
|
174
|
+
score: 0.9,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
fallback: false,
|
|
178
|
+
resolvedEntities: {
|
|
179
|
+
contacts: [{ id: 'c1', displayName: 'Amr' }],
|
|
180
|
+
topicWords: ['project'],
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
await runSearch(client, ['test'], false);
|
|
184
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Amr'));
|
|
185
|
+
});
|
|
186
|
+
(0, vitest_1.it)('should show no memories message when resolved entities but no results', async () => {
|
|
187
|
+
const client = createMockClient();
|
|
188
|
+
client.searchMemories.mockResolvedValue({
|
|
189
|
+
items: [],
|
|
190
|
+
fallback: false,
|
|
191
|
+
resolvedEntities: {
|
|
192
|
+
contacts: [{ id: 'c1', displayName: 'Amr' }],
|
|
193
|
+
topicWords: [],
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
await runSearch(client, ['test'], false);
|
|
197
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('No memories found'));
|
|
198
|
+
});
|
|
199
|
+
(0, vitest_1.it)('should show fallback message when fallback=true', async () => {
|
|
200
|
+
const client = createMockClient();
|
|
201
|
+
client.searchMemories.mockResolvedValue({
|
|
202
|
+
items: [
|
|
203
|
+
{
|
|
204
|
+
id: 'm1',
|
|
205
|
+
text: 'test',
|
|
206
|
+
sourceType: 'email',
|
|
207
|
+
connectorType: 'gmail',
|
|
208
|
+
eventTime: '2025-01-01',
|
|
209
|
+
score: 0.9,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
fallback: true,
|
|
213
|
+
});
|
|
214
|
+
await runSearch(client, ['test'], false);
|
|
215
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('semantically similar'));
|
|
216
|
+
});
|
|
217
|
+
(0, vitest_1.it)('should show temporal range when parsed.temporal is present', async () => {
|
|
218
|
+
const client = createMockClient();
|
|
219
|
+
client.searchMemories.mockResolvedValue({
|
|
220
|
+
items: [
|
|
221
|
+
{
|
|
222
|
+
id: 'm1',
|
|
223
|
+
text: 'test',
|
|
224
|
+
sourceType: 'email',
|
|
225
|
+
connectorType: 'gmail',
|
|
226
|
+
eventTime: '2025-01-01',
|
|
227
|
+
score: 0.9,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
fallback: false,
|
|
231
|
+
parsed: { temporal: { from: '2025-01-01', to: '2025-01-31' }, temporalFallback: false },
|
|
232
|
+
});
|
|
233
|
+
await runSearch(client, ['test'], false);
|
|
234
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Date filter'));
|
|
235
|
+
});
|
|
236
|
+
(0, vitest_1.it)('should show temporal fallback message', async () => {
|
|
237
|
+
const client = createMockClient();
|
|
238
|
+
client.searchMemories.mockResolvedValue({
|
|
239
|
+
items: [],
|
|
240
|
+
fallback: false,
|
|
241
|
+
parsed: { temporal: { from: '2025-01-01', to: '2025-01-31' }, temporalFallback: true },
|
|
242
|
+
});
|
|
243
|
+
await runSearch(client, ['test'], false);
|
|
244
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('No results for that time range'));
|
|
245
|
+
});
|
|
246
|
+
(0, vitest_1.it)('should show intent when not recall', async () => {
|
|
247
|
+
const client = createMockClient();
|
|
248
|
+
client.searchMemories.mockResolvedValue({
|
|
249
|
+
items: [],
|
|
250
|
+
fallback: false,
|
|
251
|
+
parsed: { intent: 'summarize' },
|
|
252
|
+
});
|
|
253
|
+
await runSearch(client, ['test'], false);
|
|
254
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Intent: summarize'));
|
|
255
|
+
});
|
|
256
|
+
(0, vitest_1.it)('should pass --contact filter', async () => {
|
|
257
|
+
const client = createMockClient();
|
|
258
|
+
await runSearch(client, ['test', '--contact', 'c1'], false);
|
|
259
|
+
(0, vitest_1.expect)(client.searchMemories).toHaveBeenCalledWith('test', { contactId: 'c1' }, undefined, undefined);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
// --- Memories ---
|
|
263
|
+
(0, vitest_1.describe)('runMemories', () => {
|
|
264
|
+
let runMemories;
|
|
265
|
+
let runMemory;
|
|
266
|
+
let runStats;
|
|
267
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
268
|
+
({ runMemories, runMemory, runStats } = await Promise.resolve().then(() => __importStar(require('../commands/memories.js'))));
|
|
269
|
+
});
|
|
270
|
+
(0, vitest_1.it)('should list memories with params', async () => {
|
|
271
|
+
const client = createMockClient();
|
|
272
|
+
await runMemories(client, ['--limit', '10', '--offset', '5', '--source', 'email', '--connector', 'gmail'], false);
|
|
273
|
+
(0, vitest_1.expect)(client.listMemories).toHaveBeenCalledWith({
|
|
274
|
+
limit: 10,
|
|
275
|
+
offset: 5,
|
|
276
|
+
sourceType: 'email',
|
|
277
|
+
connectorType: 'gmail',
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
(0, vitest_1.it)('should output JSON when json=true', async () => {
|
|
281
|
+
const client = createMockClient();
|
|
282
|
+
await runMemories(client, [], true);
|
|
283
|
+
const output = logged(logSpy, 0, 0);
|
|
284
|
+
(0, vitest_1.expect)(() => JSON.parse(output)).not.toThrow();
|
|
285
|
+
});
|
|
286
|
+
(0, vitest_1.describe)('runMemory', () => {
|
|
287
|
+
(0, vitest_1.it)('should get a single memory', async () => {
|
|
288
|
+
const client = createMockClient();
|
|
289
|
+
await runMemory(client, ['m1'], false);
|
|
290
|
+
(0, vitest_1.expect)(client.getMemory).toHaveBeenCalledWith('m1');
|
|
291
|
+
});
|
|
292
|
+
(0, vitest_1.it)('should delete a memory', async () => {
|
|
293
|
+
const client = createMockClient();
|
|
294
|
+
await runMemory(client, ['m1', 'delete'], false);
|
|
295
|
+
(0, vitest_1.expect)(client.deleteMemory).toHaveBeenCalledWith('m1');
|
|
296
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith('Memory deleted.');
|
|
297
|
+
});
|
|
298
|
+
(0, vitest_1.it)('should output JSON for delete', async () => {
|
|
299
|
+
const client = createMockClient();
|
|
300
|
+
await runMemory(client, ['m1', 'delete'], true);
|
|
301
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
302
|
+
});
|
|
303
|
+
(0, vitest_1.it)('should error when no ID provided', async () => {
|
|
304
|
+
const client = createMockClient();
|
|
305
|
+
await runMemory(client, [], false);
|
|
306
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires an ID'));
|
|
307
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
(0, vitest_1.describe)('runStats', () => {
|
|
311
|
+
(0, vitest_1.it)('should get memory stats', async () => {
|
|
312
|
+
const client = createMockClient();
|
|
313
|
+
await runStats(client, false);
|
|
314
|
+
(0, vitest_1.expect)(client.getMemoryStats).toHaveBeenCalled();
|
|
315
|
+
});
|
|
316
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
317
|
+
const client = createMockClient();
|
|
318
|
+
await runStats(client, true);
|
|
319
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
// --- Contacts ---
|
|
324
|
+
(0, vitest_1.describe)('runContacts', () => {
|
|
325
|
+
let runContacts;
|
|
326
|
+
let runContact;
|
|
327
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
328
|
+
({ runContacts, runContact } = await Promise.resolve().then(() => __importStar(require('../commands/contacts.js'))));
|
|
329
|
+
});
|
|
330
|
+
(0, vitest_1.it)('should list contacts', async () => {
|
|
331
|
+
const client = createMockClient();
|
|
332
|
+
await runContacts(client, ['--limit', '20', '--offset', '10'], false);
|
|
333
|
+
(0, vitest_1.expect)(client.listContacts).toHaveBeenCalledWith({ limit: 20, offset: 10 });
|
|
334
|
+
});
|
|
335
|
+
(0, vitest_1.it)('should search contacts', async () => {
|
|
336
|
+
const client = createMockClient();
|
|
337
|
+
await runContacts(client, ['search', 'Amr'], false);
|
|
338
|
+
(0, vitest_1.expect)(client.searchContacts).toHaveBeenCalledWith('Amr');
|
|
339
|
+
});
|
|
340
|
+
(0, vitest_1.it)('should output JSON for list', async () => {
|
|
341
|
+
const client = createMockClient();
|
|
342
|
+
await runContacts(client, [], true);
|
|
343
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
344
|
+
});
|
|
345
|
+
(0, vitest_1.it)('should error on empty search query', async () => {
|
|
346
|
+
const client = createMockClient();
|
|
347
|
+
await runContacts(client, ['search'], false);
|
|
348
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a query'));
|
|
349
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
350
|
+
});
|
|
351
|
+
(0, vitest_1.describe)('runContact', () => {
|
|
352
|
+
(0, vitest_1.it)('should get contact details', async () => {
|
|
353
|
+
const client = createMockClient();
|
|
354
|
+
await runContact(client, ['c1'], false);
|
|
355
|
+
(0, vitest_1.expect)(client.getContact).toHaveBeenCalledWith('c1');
|
|
356
|
+
});
|
|
357
|
+
(0, vitest_1.it)('should get contact memories', async () => {
|
|
358
|
+
const client = createMockClient();
|
|
359
|
+
await runContact(client, ['c1', 'memories'], false);
|
|
360
|
+
(0, vitest_1.expect)(client.getContactMemories).toHaveBeenCalledWith('c1');
|
|
361
|
+
});
|
|
362
|
+
(0, vitest_1.it)('should error when no ID', async () => {
|
|
363
|
+
const client = createMockClient();
|
|
364
|
+
await runContact(client, [], false);
|
|
365
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires an ID'));
|
|
366
|
+
});
|
|
367
|
+
(0, vitest_1.it)('should output JSON for contact', async () => {
|
|
368
|
+
const client = createMockClient();
|
|
369
|
+
await runContact(client, ['c1'], true);
|
|
370
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
371
|
+
});
|
|
372
|
+
(0, vitest_1.it)('should output JSON for contact memories', async () => {
|
|
373
|
+
const client = createMockClient();
|
|
374
|
+
await runContact(client, ['c1', 'memories'], true);
|
|
375
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
// --- Agent ---
|
|
380
|
+
(0, vitest_1.describe)('runAsk', () => {
|
|
381
|
+
let runAsk;
|
|
382
|
+
let runContext;
|
|
383
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
384
|
+
({ runAsk, runContext } = await Promise.resolve().then(() => __importStar(require('../commands/agent.js'))));
|
|
385
|
+
});
|
|
386
|
+
(0, vitest_1.it)('should ask with query', async () => {
|
|
387
|
+
const client = createMockClient();
|
|
388
|
+
await runAsk(client, ['what', 'happened?'], false);
|
|
389
|
+
(0, vitest_1.expect)(client.agentAsk).toHaveBeenCalledWith('what happened?', undefined, undefined);
|
|
390
|
+
});
|
|
391
|
+
(0, vitest_1.it)('should use summarize when --summarize flag', async () => {
|
|
392
|
+
const client = createMockClient();
|
|
393
|
+
await runAsk(client, ['my', 'week', '--summarize'], false);
|
|
394
|
+
(0, vitest_1.expect)(client.agentSummarize).toHaveBeenCalledWith('my week', undefined);
|
|
395
|
+
});
|
|
396
|
+
(0, vitest_1.it)('should pass filters and limit', async () => {
|
|
397
|
+
const client = createMockClient();
|
|
398
|
+
await runAsk(client, [
|
|
399
|
+
'test',
|
|
400
|
+
'--source',
|
|
401
|
+
'email',
|
|
402
|
+
'--connector',
|
|
403
|
+
'gmail',
|
|
404
|
+
'--limit',
|
|
405
|
+
'5',
|
|
406
|
+
'--memory-bank',
|
|
407
|
+
'bank-1',
|
|
408
|
+
], false);
|
|
409
|
+
(0, vitest_1.expect)(client.agentAsk).toHaveBeenCalledWith('test', { sourceType: 'email', connectorType: 'gmail', memoryBankId: 'bank-1' }, 5);
|
|
410
|
+
});
|
|
411
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
412
|
+
const client = createMockClient();
|
|
413
|
+
await runAsk(client, ['test'], true);
|
|
414
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
415
|
+
});
|
|
416
|
+
(0, vitest_1.it)('should error when no query', async () => {
|
|
417
|
+
const client = createMockClient();
|
|
418
|
+
await runAsk(client, [], false);
|
|
419
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a query'));
|
|
420
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
421
|
+
});
|
|
422
|
+
(0, vitest_1.describe)('runContext', () => {
|
|
423
|
+
(0, vitest_1.it)('should get context for contact', async () => {
|
|
424
|
+
const client = createMockClient();
|
|
425
|
+
await runContext(client, ['c1'], false);
|
|
426
|
+
(0, vitest_1.expect)(client.agentContext).toHaveBeenCalledWith('c1');
|
|
427
|
+
});
|
|
428
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
429
|
+
const client = createMockClient();
|
|
430
|
+
await runContext(client, ['c1'], true);
|
|
431
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
432
|
+
});
|
|
433
|
+
(0, vitest_1.it)('should error when no contact ID', async () => {
|
|
434
|
+
const client = createMockClient();
|
|
435
|
+
await runContext(client, [], false);
|
|
436
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a contact ID'));
|
|
437
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
// --- Jobs ---
|
|
442
|
+
(0, vitest_1.describe)('runJobs', () => {
|
|
443
|
+
let runJobs;
|
|
444
|
+
let runSync;
|
|
445
|
+
let runRetry;
|
|
446
|
+
let runAccounts;
|
|
447
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
448
|
+
({ runJobs, runSync, runRetry, runAccounts } = await Promise.resolve().then(() => __importStar(require('../commands/jobs.js'))));
|
|
449
|
+
});
|
|
450
|
+
(0, vitest_1.it)('should list jobs', async () => {
|
|
451
|
+
const client = createMockClient();
|
|
452
|
+
await runJobs(client, [], false);
|
|
453
|
+
(0, vitest_1.expect)(client.listJobs).toHaveBeenCalledWith(undefined);
|
|
454
|
+
});
|
|
455
|
+
(0, vitest_1.it)('should list jobs with account filter', async () => {
|
|
456
|
+
const client = createMockClient();
|
|
457
|
+
await runJobs(client, ['--account', 'acc-1'], false);
|
|
458
|
+
(0, vitest_1.expect)(client.listJobs).toHaveBeenCalledWith('acc-1');
|
|
459
|
+
});
|
|
460
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
461
|
+
const client = createMockClient();
|
|
462
|
+
await runJobs(client, [], true);
|
|
463
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
464
|
+
});
|
|
465
|
+
(0, vitest_1.describe)('runSync', () => {
|
|
466
|
+
(0, vitest_1.it)('should trigger sync', async () => {
|
|
467
|
+
const client = createMockClient();
|
|
468
|
+
await runSync(client, ['acc-1'], false);
|
|
469
|
+
(0, vitest_1.expect)(client.triggerSync).toHaveBeenCalledWith('acc-1');
|
|
470
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('j1'));
|
|
471
|
+
});
|
|
472
|
+
(0, vitest_1.it)('should error when no account ID', async () => {
|
|
473
|
+
const client = createMockClient();
|
|
474
|
+
await runSync(client, [], false);
|
|
475
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires an account ID'));
|
|
476
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
477
|
+
});
|
|
478
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
479
|
+
const client = createMockClient();
|
|
480
|
+
await runSync(client, ['acc-1'], true);
|
|
481
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
(0, vitest_1.describe)('runRetry', () => {
|
|
485
|
+
(0, vitest_1.it)('should retry failed jobs and memories', async () => {
|
|
486
|
+
const client = createMockClient();
|
|
487
|
+
await runRetry(client, false);
|
|
488
|
+
(0, vitest_1.expect)(client.retryFailedJobs).toHaveBeenCalled();
|
|
489
|
+
(0, vitest_1.expect)(client.retryFailedMemories).toHaveBeenCalled();
|
|
490
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('2'));
|
|
491
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('3'));
|
|
492
|
+
});
|
|
493
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
494
|
+
const client = createMockClient();
|
|
495
|
+
await runRetry(client, true);
|
|
496
|
+
const output = JSON.parse(logged(logSpy, 0, 0));
|
|
497
|
+
(0, vitest_1.expect)(output.jobs.retried).toBe(2);
|
|
498
|
+
(0, vitest_1.expect)(output.memories.enqueued).toBe(3);
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
(0, vitest_1.describe)('runAccounts', () => {
|
|
502
|
+
(0, vitest_1.it)('should list accounts', async () => {
|
|
503
|
+
const client = createMockClient();
|
|
504
|
+
await runAccounts(client, false);
|
|
505
|
+
(0, vitest_1.expect)(client.listAccounts).toHaveBeenCalled();
|
|
506
|
+
});
|
|
507
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
508
|
+
const client = createMockClient();
|
|
509
|
+
await runAccounts(client, true);
|
|
510
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
// --- Timeline ---
|
|
515
|
+
(0, vitest_1.describe)('runTimeline', () => {
|
|
516
|
+
let runTimeline;
|
|
517
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
518
|
+
({ runTimeline } = await Promise.resolve().then(() => __importStar(require('../commands/timeline.js'))));
|
|
519
|
+
});
|
|
520
|
+
(0, vitest_1.it)('should get timeline with params', async () => {
|
|
521
|
+
const client = createMockClient();
|
|
522
|
+
await runTimeline(client, [
|
|
523
|
+
'--from',
|
|
524
|
+
'2025-01-01',
|
|
525
|
+
'--to',
|
|
526
|
+
'2025-01-31',
|
|
527
|
+
'--query',
|
|
528
|
+
'meeting',
|
|
529
|
+
'--connector',
|
|
530
|
+
'gmail',
|
|
531
|
+
'--source',
|
|
532
|
+
'email',
|
|
533
|
+
'--limit',
|
|
534
|
+
'10',
|
|
535
|
+
], false);
|
|
536
|
+
(0, vitest_1.expect)(client.getTimeline).toHaveBeenCalledWith({
|
|
537
|
+
from: '2025-01-01',
|
|
538
|
+
to: '2025-01-31',
|
|
539
|
+
query: 'meeting',
|
|
540
|
+
connectorType: 'gmail',
|
|
541
|
+
sourceType: 'email',
|
|
542
|
+
limit: 10,
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
546
|
+
const client = createMockClient();
|
|
547
|
+
await runTimeline(client, [], true);
|
|
548
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
549
|
+
});
|
|
550
|
+
(0, vitest_1.it)('should show "no memories" message when empty', async () => {
|
|
551
|
+
const client = createMockClient();
|
|
552
|
+
await runTimeline(client, [], false);
|
|
553
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('No memories'));
|
|
554
|
+
});
|
|
555
|
+
(0, vitest_1.it)('should display timeline items grouped by date', async () => {
|
|
556
|
+
const client = createMockClient();
|
|
557
|
+
client.getTimeline.mockResolvedValue({
|
|
558
|
+
items: [
|
|
559
|
+
{
|
|
560
|
+
id: 'm1',
|
|
561
|
+
text: 'Meeting at 10am',
|
|
562
|
+
sourceType: 'email',
|
|
563
|
+
connectorType: 'gmail',
|
|
564
|
+
eventTime: '2025-06-15T10:00:00Z',
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: 'm2',
|
|
568
|
+
text: 'Lunch plans',
|
|
569
|
+
sourceType: 'message',
|
|
570
|
+
connectorType: 'slack',
|
|
571
|
+
eventTime: '2025-06-15T12:00:00Z',
|
|
572
|
+
},
|
|
573
|
+
],
|
|
574
|
+
total: 2,
|
|
575
|
+
});
|
|
576
|
+
await runTimeline(client, [], false);
|
|
577
|
+
// Should contain date headers and items
|
|
578
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Meeting at 10am'));
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
// --- Entities ---
|
|
582
|
+
(0, vitest_1.describe)('runEntities', () => {
|
|
583
|
+
let runEntities;
|
|
584
|
+
let runRelated;
|
|
585
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
586
|
+
({ runEntities, runRelated } = await Promise.resolve().then(() => __importStar(require('../commands/entities.js'))));
|
|
587
|
+
});
|
|
588
|
+
(0, vitest_1.it)('should show help when no subcommand', async () => {
|
|
589
|
+
const client = createMockClient();
|
|
590
|
+
await runEntities(client, [], false);
|
|
591
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('entities'));
|
|
592
|
+
});
|
|
593
|
+
(0, vitest_1.it)('should search entities', async () => {
|
|
594
|
+
const client = createMockClient();
|
|
595
|
+
client.searchEntities.mockResolvedValue({
|
|
596
|
+
entities: [{ value: 'Google', type: 'organization', memoryCount: 10, connectors: ['gmail'] }],
|
|
597
|
+
total: 1,
|
|
598
|
+
});
|
|
599
|
+
await runEntities(client, ['search', 'Google', '--limit', '5', '--type', 'organization'], false);
|
|
600
|
+
(0, vitest_1.expect)(client.searchEntities).toHaveBeenCalledWith('Google', 5, 'organization');
|
|
601
|
+
});
|
|
602
|
+
(0, vitest_1.it)('should output JSON for search', async () => {
|
|
603
|
+
const client = createMockClient();
|
|
604
|
+
await runEntities(client, ['search', 'test'], true);
|
|
605
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
606
|
+
});
|
|
607
|
+
(0, vitest_1.it)('should error when search has no query', async () => {
|
|
608
|
+
const client = createMockClient();
|
|
609
|
+
await runEntities(client, ['search'], false);
|
|
610
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a query'));
|
|
611
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
612
|
+
});
|
|
613
|
+
(0, vitest_1.it)('should show entity graph', async () => {
|
|
614
|
+
const client = createMockClient();
|
|
615
|
+
client.getEntityGraph.mockResolvedValue({
|
|
616
|
+
entity: 'Google',
|
|
617
|
+
memories: [
|
|
618
|
+
{
|
|
619
|
+
id: 'm1',
|
|
620
|
+
text: 'Google meeting',
|
|
621
|
+
sourceType: 'email',
|
|
622
|
+
connectorType: 'gmail',
|
|
623
|
+
eventTime: '2025-01-01',
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
relatedEntities: [{ value: 'AWS', type: 'organization', count: 5 }],
|
|
627
|
+
contacts: [{ id: 'c1', displayName: 'Test User' }],
|
|
628
|
+
memoryCount: 10,
|
|
629
|
+
});
|
|
630
|
+
await runEntities(client, ['graph', 'Google'], false);
|
|
631
|
+
(0, vitest_1.expect)(client.getEntityGraph).toHaveBeenCalledWith('Google', undefined);
|
|
632
|
+
});
|
|
633
|
+
(0, vitest_1.it)('should output JSON for graph', async () => {
|
|
634
|
+
const client = createMockClient();
|
|
635
|
+
await runEntities(client, ['graph', 'Google'], true);
|
|
636
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
637
|
+
});
|
|
638
|
+
(0, vitest_1.it)('should error on unknown subcommand', async () => {
|
|
639
|
+
const client = createMockClient();
|
|
640
|
+
await runEntities(client, ['unknown'], false);
|
|
641
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Unknown'));
|
|
642
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
643
|
+
});
|
|
644
|
+
(0, vitest_1.describe)('runRelated', () => {
|
|
645
|
+
(0, vitest_1.it)('should get related memories', async () => {
|
|
646
|
+
const client = createMockClient();
|
|
647
|
+
client.getRelated.mockResolvedValue({
|
|
648
|
+
items: [
|
|
649
|
+
{
|
|
650
|
+
id: 'm2',
|
|
651
|
+
text: 'Related memory',
|
|
652
|
+
sourceType: 'email',
|
|
653
|
+
connectorType: 'gmail',
|
|
654
|
+
eventTime: '2025-01-01',
|
|
655
|
+
score: 0.9,
|
|
656
|
+
relationship: 'similar',
|
|
657
|
+
},
|
|
658
|
+
],
|
|
659
|
+
source: { text: 'Source memory' },
|
|
660
|
+
});
|
|
661
|
+
await runRelated(client, ['m1', '--limit', '5'], false);
|
|
662
|
+
(0, vitest_1.expect)(client.getRelated).toHaveBeenCalledWith('m1', 5);
|
|
663
|
+
});
|
|
664
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
665
|
+
const client = createMockClient();
|
|
666
|
+
await runRelated(client, ['m1'], true);
|
|
667
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
668
|
+
});
|
|
669
|
+
(0, vitest_1.it)('should error when no memory ID', async () => {
|
|
670
|
+
const client = createMockClient();
|
|
671
|
+
await runRelated(client, [], false);
|
|
672
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a memory ID'));
|
|
673
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
674
|
+
});
|
|
675
|
+
(0, vitest_1.it)('should show empty message when no related found', async () => {
|
|
676
|
+
const client = createMockClient();
|
|
677
|
+
await runRelated(client, ['m1'], false);
|
|
678
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('No related'));
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
// --- Memory Banks ---
|
|
683
|
+
(0, vitest_1.describe)('runMemoryBanks', () => {
|
|
684
|
+
let runMemoryBanks;
|
|
685
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
686
|
+
({ runMemoryBanks } = await Promise.resolve().then(() => __importStar(require('../commands/memory-banks.js'))));
|
|
687
|
+
});
|
|
688
|
+
(0, vitest_1.it)('should list memory banks', async () => {
|
|
689
|
+
const client = createMockClient();
|
|
690
|
+
await runMemoryBanks(client, [], false);
|
|
691
|
+
(0, vitest_1.expect)(client.listMemoryBanks).toHaveBeenCalled();
|
|
692
|
+
});
|
|
693
|
+
(0, vitest_1.it)('should create a memory bank', async () => {
|
|
694
|
+
const client = createMockClient();
|
|
695
|
+
await runMemoryBanks(client, ['create', 'Work'], false);
|
|
696
|
+
(0, vitest_1.expect)(client.createMemoryBank).toHaveBeenCalledWith('Work');
|
|
697
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Work'));
|
|
698
|
+
});
|
|
699
|
+
(0, vitest_1.it)('should rename a memory bank', async () => {
|
|
700
|
+
const client = createMockClient();
|
|
701
|
+
await runMemoryBanks(client, ['rename', 'b1', 'Personal'], false);
|
|
702
|
+
(0, vitest_1.expect)(client.renameMemoryBank).toHaveBeenCalledWith('b1', 'Personal');
|
|
703
|
+
});
|
|
704
|
+
(0, vitest_1.it)('should delete a memory bank', async () => {
|
|
705
|
+
const client = createMockClient();
|
|
706
|
+
await runMemoryBanks(client, ['delete', 'b1'], false);
|
|
707
|
+
(0, vitest_1.expect)(client.deleteMemoryBank).toHaveBeenCalledWith('b1');
|
|
708
|
+
});
|
|
709
|
+
(0, vitest_1.it)('should output JSON for list', async () => {
|
|
710
|
+
const client = createMockClient();
|
|
711
|
+
await runMemoryBanks(client, [], true);
|
|
712
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
713
|
+
});
|
|
714
|
+
(0, vitest_1.it)('should output JSON for create', async () => {
|
|
715
|
+
const client = createMockClient();
|
|
716
|
+
await runMemoryBanks(client, ['create', 'Work'], true);
|
|
717
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
718
|
+
});
|
|
719
|
+
(0, vitest_1.it)('should output JSON for rename', async () => {
|
|
720
|
+
const client = createMockClient();
|
|
721
|
+
await runMemoryBanks(client, ['rename', 'b1', 'New'], true);
|
|
722
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
723
|
+
});
|
|
724
|
+
(0, vitest_1.it)('should output JSON for delete', async () => {
|
|
725
|
+
const client = createMockClient();
|
|
726
|
+
await runMemoryBanks(client, ['delete', 'b1'], true);
|
|
727
|
+
(0, vitest_1.expect)(() => JSON.parse(logged(logSpy, 0, 0))).not.toThrow();
|
|
728
|
+
});
|
|
729
|
+
(0, vitest_1.it)('should error when create has no name', async () => {
|
|
730
|
+
const client = createMockClient();
|
|
731
|
+
await runMemoryBanks(client, ['create'], false);
|
|
732
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires a name'));
|
|
733
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
734
|
+
});
|
|
735
|
+
(0, vitest_1.it)('should error when rename missing args', async () => {
|
|
736
|
+
const client = createMockClient();
|
|
737
|
+
await runMemoryBanks(client, ['rename', 'b1'], false);
|
|
738
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('rename requires'));
|
|
739
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
740
|
+
});
|
|
741
|
+
(0, vitest_1.it)('should error when delete has no id', async () => {
|
|
742
|
+
const client = createMockClient();
|
|
743
|
+
await runMemoryBanks(client, ['delete'], false);
|
|
744
|
+
(0, vitest_1.expect)(errorSpy).toHaveBeenCalledWith(vitest_1.expect.stringContaining('requires an id'));
|
|
745
|
+
(0, vitest_1.expect)(exitSpy).toHaveBeenCalledWith(1);
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
// --- Install Skill ---
|
|
749
|
+
(0, vitest_1.describe)('runInstallSkill', () => {
|
|
750
|
+
let runInstallSkill;
|
|
751
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
752
|
+
({ runInstallSkill } = await Promise.resolve().then(() => __importStar(require('../commands/install-skill.js'))));
|
|
753
|
+
});
|
|
754
|
+
(0, vitest_1.it)('should create skill files in .agents and .claude directories', () => {
|
|
755
|
+
const fs = require('fs');
|
|
756
|
+
const path = require('path');
|
|
757
|
+
const os = require('os');
|
|
758
|
+
// Use a temp dir as cwd
|
|
759
|
+
const tempDir = path.join(os.tmpdir(), `botmem-skill-test-${Date.now()}`);
|
|
760
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
761
|
+
const origCwd = process.cwd();
|
|
762
|
+
process.chdir(tempDir);
|
|
763
|
+
try {
|
|
764
|
+
runInstallSkill();
|
|
765
|
+
// Check .agents skill file was created
|
|
766
|
+
const agentsSkill = path.join(tempDir, '.agents', 'skills', 'botmem-cli', 'SKILL.md');
|
|
767
|
+
(0, vitest_1.expect)(fs.existsSync(agentsSkill)).toBe(true);
|
|
768
|
+
const content = fs.readFileSync(agentsSkill, 'utf-8');
|
|
769
|
+
(0, vitest_1.expect)(content).toContain('botmem-cli');
|
|
770
|
+
// Check .claude symlink was created
|
|
771
|
+
const claudeSkill = path.join(tempDir, '.claude', 'skills', 'botmem-cli', 'SKILL.md');
|
|
772
|
+
(0, vitest_1.expect)(fs.existsSync(claudeSkill)).toBe(true);
|
|
773
|
+
}
|
|
774
|
+
finally {
|
|
775
|
+
process.chdir(origCwd);
|
|
776
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
(0, vitest_1.it)('should handle running twice (existing symlink)', () => {
|
|
780
|
+
const fs = require('fs');
|
|
781
|
+
const path = require('path');
|
|
782
|
+
const os = require('os');
|
|
783
|
+
const tempDir = path.join(os.tmpdir(), `botmem-skill-test2-${Date.now()}`);
|
|
784
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
785
|
+
const origCwd = process.cwd();
|
|
786
|
+
process.chdir(tempDir);
|
|
787
|
+
try {
|
|
788
|
+
runInstallSkill();
|
|
789
|
+
// Run again — should not throw
|
|
790
|
+
runInstallSkill();
|
|
791
|
+
const claudeSkill = path.join(tempDir, '.claude', 'skills', 'botmem-cli', 'SKILL.md');
|
|
792
|
+
(0, vitest_1.expect)(fs.existsSync(claudeSkill)).toBe(true);
|
|
793
|
+
}
|
|
794
|
+
finally {
|
|
795
|
+
process.chdir(origCwd);
|
|
796
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
// --- Version ---
|
|
801
|
+
(0, vitest_1.describe)('runVersion', () => {
|
|
802
|
+
let runVersion;
|
|
803
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
804
|
+
({ runVersion } = await Promise.resolve().then(() => __importStar(require('../commands/version.js'))));
|
|
805
|
+
});
|
|
806
|
+
(0, vitest_1.it)('should get and display version info', async () => {
|
|
807
|
+
const client = createMockClient();
|
|
808
|
+
await runVersion(client, false);
|
|
809
|
+
(0, vitest_1.expect)(client.getVersion).toHaveBeenCalled();
|
|
810
|
+
(0, vitest_1.expect)(logSpy).toHaveBeenCalled();
|
|
811
|
+
});
|
|
812
|
+
(0, vitest_1.it)('should output JSON', async () => {
|
|
813
|
+
const client = createMockClient();
|
|
814
|
+
await runVersion(client, true);
|
|
815
|
+
const output = JSON.parse(logged(logSpy, 0, 0));
|
|
816
|
+
(0, vitest_1.expect)(output.buildTime).toBe('2025-01-01');
|
|
817
|
+
(0, vitest_1.expect)(output.gitHash).toBe('abc');
|
|
818
|
+
(0, vitest_1.expect)(output.uptime).toBe(3600);
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
//# sourceMappingURL=commands.test.js.map
|