gogcli-mcp-drive 2.7.1 → 2.18.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.
@@ -1,7 +1,8 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { registerExtraDriveTools } from '../../src/tools/drive-extra.js';
3
3
  import * as lib from '../../../gogcli-mcp/src/lib.js';
4
- import { setupHandlers, toText, type ToolHandler } from '../../../gogcli-mcp/tests/helpers/test-harness.js';
4
+ import { createTestHarness, type TestHarness } from '@chrischall/mcp-utils/test';
5
+ import { rawTextResult } from '@chrischall/mcp-utils';
5
6
 
6
7
  vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
7
8
  const actual = await importOriginal<typeof lib>();
@@ -11,37 +12,45 @@ vi.mock('../../../gogcli-mcp/src/lib.js', async (importOriginal) => {
11
12
  };
12
13
  });
13
14
 
14
- let handlers: Map<string, ToolHandler>;
15
+ let harness: TestHarness;
15
16
 
16
- beforeEach(() => {
17
+ beforeEach(async () => {
17
18
  vi.clearAllMocks();
18
- vi.mocked(lib.runOrDiagnose).mockResolvedValue(toText('{}'));
19
- handlers = setupHandlers(registerExtraDriveTools);
19
+ vi.mocked(lib.runOrDiagnose).mockResolvedValue(rawTextResult('{}'));
20
+ harness = await createTestHarness(registerExtraDriveTools);
20
21
  });
21
22
 
22
23
  describe('gog_drive_download', () => {
23
24
  it('calls runOrDiagnose with fileId only', async () => {
24
- await handlers.get('gog_drive_download')!({ fileId: 'f1' });
25
+ await harness.callTool('gog_drive_download', { fileId: 'f1' });
25
26
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'download', 'f1'], { account: undefined });
26
27
  });
27
28
 
28
29
  it('passes --out and --format when provided', async () => {
29
- await handlers.get('gog_drive_download')!({ fileId: 'f1', out: '/tmp/file.pdf', format: 'pdf', account: 'a@b.com' });
30
+ await harness.callTool('gog_drive_download', { fileId: 'f1', out: '/tmp/file.pdf', format: 'pdf', account: 'a@b.com' });
30
31
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
31
32
  ['drive', 'download', 'f1', '--out=/tmp/file.pdf', '--format=pdf'],
32
33
  { account: 'a@b.com' },
33
34
  );
34
35
  });
36
+
37
+ it('passes --overwrite when requested', async () => {
38
+ await harness.callTool('gog_drive_download', { fileId: 'f1', out: '/tmp/file.pdf', overwrite: true });
39
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
40
+ ['drive', 'download', 'f1', '--out=/tmp/file.pdf', '--overwrite'],
41
+ { account: undefined },
42
+ );
43
+ });
35
44
  });
36
45
 
37
46
  describe('gog_drive_upload', () => {
38
47
  it('calls runOrDiagnose with localPath only', async () => {
39
- await handlers.get('gog_drive_upload')!({ localPath: '/tmp/x.txt' });
48
+ await harness.callTool('gog_drive_upload', { localPath: '/tmp/x.txt' });
40
49
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'upload', '/tmp/x.txt'], { account: undefined });
41
50
  });
42
51
 
43
52
  it('passes all upload flags', async () => {
44
- await handlers.get('gog_drive_upload')!({
53
+ await harness.callTool('gog_drive_upload', {
45
54
  localPath: '/tmp/x.txt',
46
55
  name: 'renamed.txt',
47
56
  parent: 'folder1',
@@ -67,19 +76,49 @@ describe('gog_drive_upload', () => {
67
76
  });
68
77
 
69
78
  it('omits boolean flags when false', async () => {
70
- await handlers.get('gog_drive_upload')!({ localPath: '/tmp/x.txt', keepRevisionForever: false, convert: false });
79
+ await harness.callTool('gog_drive_upload', { localPath: '/tmp/x.txt', keepRevisionForever: false, convert: false });
71
80
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'upload', '/tmp/x.txt'], { account: undefined });
72
81
  });
73
82
  });
74
83
 
84
+ describe('gog_drive_sync_push', () => {
85
+ it('calls runOrDiagnose with localPath and required parent', async () => {
86
+ await harness.callTool('gog_drive_sync_push', { localPath: '/tmp/dir', parent: 'folder1' });
87
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
88
+ ['drive', 'sync', 'push', '/tmp/dir', '--parent=folder1'],
89
+ { account: undefined },
90
+ );
91
+ });
92
+
93
+ it('passes --dry-run and --no-all-drives', async () => {
94
+ await harness.callTool('gog_drive_sync_push', {
95
+ localPath: '/tmp/dir', parent: 'folder1', dryRun: true, allDrives: false,
96
+ });
97
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
98
+ ['drive', 'sync', 'push', '/tmp/dir', '--parent=folder1', '--dry-run', '--no-all-drives'],
99
+ { account: undefined },
100
+ );
101
+ });
102
+
103
+ it('omits --no-all-drives when allDrives is true and dryRun false', async () => {
104
+ await harness.callTool('gog_drive_sync_push', {
105
+ localPath: '/tmp/dir', parent: 'folder1', dryRun: false, allDrives: true,
106
+ });
107
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
108
+ ['drive', 'sync', 'push', '/tmp/dir', '--parent=folder1'],
109
+ { account: undefined },
110
+ );
111
+ });
112
+ });
113
+
75
114
  describe('gog_drive_copy', () => {
76
115
  it('calls runOrDiagnose with fileId and name', async () => {
77
- await handlers.get('gog_drive_copy')!({ fileId: 'f1', name: 'Copy' });
116
+ await harness.callTool('gog_drive_copy', { fileId: 'f1', name: 'Copy' });
78
117
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'copy', 'f1', 'Copy'], { account: undefined });
79
118
  });
80
119
 
81
120
  it('passes --parent when provided', async () => {
82
- await handlers.get('gog_drive_copy')!({ fileId: 'f1', name: 'Copy', parent: 'folder1' });
121
+ await harness.callTool('gog_drive_copy', { fileId: 'f1', name: 'Copy', parent: 'folder1' });
83
122
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
84
123
  ['drive', 'copy', 'f1', 'Copy', '--parent=folder1'],
85
124
  { account: undefined },
@@ -89,24 +128,24 @@ describe('gog_drive_copy', () => {
89
128
 
90
129
  describe('gog_drive_url', () => {
91
130
  it('calls runOrDiagnose with single fileId', async () => {
92
- await handlers.get('gog_drive_url')!({ fileIds: ['f1'] });
131
+ await harness.callTool('gog_drive_url', { fileIds: ['f1'] });
93
132
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'url', 'f1'], { account: undefined });
94
133
  });
95
134
 
96
135
  it('calls runOrDiagnose with multiple fileIds', async () => {
97
- await handlers.get('gog_drive_url')!({ fileIds: ['f1', 'f2', 'f3'] });
136
+ await harness.callTool('gog_drive_url', { fileIds: ['f1', 'f2', 'f3'] });
98
137
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'url', 'f1', 'f2', 'f3'], { account: undefined });
99
138
  });
100
139
  });
101
140
 
102
141
  describe('gog_drive_permissions', () => {
103
142
  it('calls runOrDiagnose with fileId', async () => {
104
- await handlers.get('gog_drive_permissions')!({ fileId: 'f1' });
143
+ await harness.callTool('gog_drive_permissions', { fileId: 'f1' });
105
144
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'permissions', 'f1'], { account: undefined });
106
145
  });
107
146
 
108
147
  it('passes --max and --page when provided', async () => {
109
- await handlers.get('gog_drive_permissions')!({ fileId: 'f1', max: 50, page: 'tok' });
148
+ await harness.callTool('gog_drive_permissions', { fileId: 'f1', max: 50, page: 'tok' });
110
149
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
111
150
  ['drive', 'permissions', 'f1', '--max=50', '--page=tok'],
112
151
  { account: undefined },
@@ -116,9 +155,9 @@ describe('gog_drive_permissions', () => {
116
155
 
117
156
  describe('gog_drive_unshare', () => {
118
157
  it('calls runOrDiagnose with fileId and permissionId', async () => {
119
- await handlers.get('gog_drive_unshare')!({ fileId: 'f1', permissionId: 'p1' });
158
+ await harness.callTool('gog_drive_unshare', { fileId: 'f1', permissionId: 'p1' });
120
159
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
121
- ['drive', 'unshare', 'f1', 'p1'],
160
+ ['drive', 'unshare', 'f1', 'p1', '--force'],
122
161
  { account: undefined },
123
162
  );
124
163
  });
@@ -126,12 +165,12 @@ describe('gog_drive_unshare', () => {
126
165
 
127
166
  describe('gog_drive_drives_list', () => {
128
167
  it('calls runOrDiagnose with no flags', async () => {
129
- await handlers.get('gog_drive_drives_list')!({});
168
+ await harness.callTool('gog_drive_drives_list', {});
130
169
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'drives'], { account: undefined });
131
170
  });
132
171
 
133
172
  it('passes all listing flags', async () => {
134
- await handlers.get('gog_drive_drives_list')!({ max: 50, page: 'tok', all: true, query: 'engineering' });
173
+ await harness.callTool('gog_drive_drives_list', { max: 50, page: 'tok', all: true, query: 'engineering' });
135
174
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
136
175
  ['drive', 'drives', '--max=50', '--page=tok', '--all', '--query=engineering'],
137
176
  { account: undefined },
@@ -139,14 +178,14 @@ describe('gog_drive_drives_list', () => {
139
178
  });
140
179
 
141
180
  it('omits --all when false', async () => {
142
- await handlers.get('gog_drive_drives_list')!({ all: false });
181
+ await harness.callTool('gog_drive_drives_list', { all: false });
143
182
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'drives'], { account: undefined });
144
183
  });
145
184
  });
146
185
 
147
186
  describe('gog_drive_comments_list', () => {
148
187
  it('calls runOrDiagnose with fileId', async () => {
149
- await handlers.get('gog_drive_comments_list')!({ fileId: 'f1' });
188
+ await harness.callTool('gog_drive_comments_list', { fileId: 'f1' });
150
189
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
151
190
  ['drive', 'comments', 'list', 'f1'],
152
191
  { account: undefined },
@@ -155,7 +194,7 @@ describe('gog_drive_comments_list', () => {
155
194
 
156
195
  // gog 0.22.0 adds --since; --include-quoted and pagination were already supported by gog.
157
196
  it('includes --since, --include-quoted and pagination flags when set', async () => {
158
- await handlers.get('gog_drive_comments_list')!({
197
+ await harness.callTool('gog_drive_comments_list', {
159
198
  fileId: 'f1', since: '2026-06-01T00:00:00Z', includeQuoted: true, max: 5, page: 'tok', all: true,
160
199
  });
161
200
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -167,7 +206,7 @@ describe('gog_drive_comments_list', () => {
167
206
 
168
207
  describe('gog_drive_comments_get', () => {
169
208
  it('calls runOrDiagnose with fileId and commentId', async () => {
170
- await handlers.get('gog_drive_comments_get')!({ fileId: 'f1', commentId: 'c1' });
209
+ await harness.callTool('gog_drive_comments_get', { fileId: 'f1', commentId: 'c1' });
171
210
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
172
211
  ['drive', 'comments', 'get', 'f1', 'c1'],
173
212
  { account: undefined },
@@ -177,7 +216,7 @@ describe('gog_drive_comments_get', () => {
177
216
 
178
217
  describe('gog_drive_comments_add', () => {
179
218
  it('calls runOrDiagnose with fileId and content', async () => {
180
- await handlers.get('gog_drive_comments_add')!({ fileId: 'f1', content: 'LGTM' });
219
+ await harness.callTool('gog_drive_comments_add', { fileId: 'f1', content: 'LGTM' });
181
220
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
182
221
  ['drive', 'comments', 'create', 'f1', 'LGTM'],
183
222
  { account: undefined },
@@ -187,7 +226,7 @@ describe('gog_drive_comments_add', () => {
187
226
 
188
227
  describe('gog_drive_comments_update', () => {
189
228
  it('calls runOrDiagnose with fileId, commentId, and content', async () => {
190
- await handlers.get('gog_drive_comments_update')!({ fileId: 'f1', commentId: 'c1', content: 'edited' });
229
+ await harness.callTool('gog_drive_comments_update', { fileId: 'f1', commentId: 'c1', content: 'edited' });
191
230
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
192
231
  ['drive', 'comments', 'update', 'f1', 'c1', 'edited'],
193
232
  { account: undefined },
@@ -197,9 +236,9 @@ describe('gog_drive_comments_update', () => {
197
236
 
198
237
  describe('gog_drive_comments_delete', () => {
199
238
  it('calls runOrDiagnose with fileId and commentId', async () => {
200
- await handlers.get('gog_drive_comments_delete')!({ fileId: 'f1', commentId: 'c1' });
239
+ await harness.callTool('gog_drive_comments_delete', { fileId: 'f1', commentId: 'c1' });
201
240
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
202
- ['drive', 'comments', 'delete', 'f1', 'c1'],
241
+ ['drive', 'comments', 'delete', 'f1', 'c1', '--force'],
203
242
  { account: undefined },
204
243
  );
205
244
  });
@@ -207,7 +246,7 @@ describe('gog_drive_comments_delete', () => {
207
246
 
208
247
  describe('gog_drive_comments_reply', () => {
209
248
  it('calls runOrDiagnose with fileId, commentId, and content', async () => {
210
- await handlers.get('gog_drive_comments_reply')!({ fileId: 'f1', commentId: 'c1', content: 'thanks' });
249
+ await harness.callTool('gog_drive_comments_reply', { fileId: 'f1', commentId: 'c1', content: 'thanks' });
211
250
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
212
251
  ['drive', 'comments', 'reply', 'f1', 'c1', 'thanks'],
213
252
  { account: undefined },
@@ -216,7 +255,7 @@ describe('gog_drive_comments_reply', () => {
216
255
 
217
256
  // gog 0.18.0: --action atomically flips resolved state on the parent comment.
218
257
  it('passes --action=resolve when action provided', async () => {
219
- await handlers.get('gog_drive_comments_reply')!({
258
+ await harness.callTool('gog_drive_comments_reply', {
220
259
  fileId: 'f1', commentId: 'c1', content: 'lgtm, resolving', action: 'resolve',
221
260
  });
222
261
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -226,7 +265,7 @@ describe('gog_drive_comments_reply', () => {
226
265
  });
227
266
 
228
267
  it('passes --action=reopen when action provided', async () => {
229
- await handlers.get('gog_drive_comments_reply')!({
268
+ await harness.callTool('gog_drive_comments_reply', {
230
269
  fileId: 'f1', commentId: 'c1', content: 'actually wait', action: 'reopen',
231
270
  });
232
271
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -240,7 +279,7 @@ describe('gog_drive_comments_reply', () => {
240
279
 
241
280
  describe('gog_drive_comments_resolve', () => {
242
281
  it('calls runOrDiagnose with fileId and commentId', async () => {
243
- await handlers.get('gog_drive_comments_resolve')!({ fileId: 'f1', commentId: 'c1' });
282
+ await harness.callTool('gog_drive_comments_resolve', { fileId: 'f1', commentId: 'c1' });
244
283
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
245
284
  ['drive', 'comments', 'resolve', 'f1', 'c1'],
246
285
  { account: undefined },
@@ -248,7 +287,7 @@ describe('gog_drive_comments_resolve', () => {
248
287
  });
249
288
 
250
289
  it('forwards account', async () => {
251
- await handlers.get('gog_drive_comments_resolve')!({ fileId: 'f1', commentId: 'c1', account: 'a@b.com' });
290
+ await harness.callTool('gog_drive_comments_resolve', { fileId: 'f1', commentId: 'c1', account: 'a@b.com' });
252
291
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
253
292
  ['drive', 'comments', 'resolve', 'f1', 'c1'],
254
293
  { account: 'a@b.com' },
@@ -258,7 +297,7 @@ describe('gog_drive_comments_resolve', () => {
258
297
 
259
298
  describe('gog_drive_comments_reopen', () => {
260
299
  it('calls runOrDiagnose with fileId and commentId', async () => {
261
- await handlers.get('gog_drive_comments_reopen')!({ fileId: 'f1', commentId: 'c1' });
300
+ await harness.callTool('gog_drive_comments_reopen', { fileId: 'f1', commentId: 'c1' });
262
301
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
263
302
  ['drive', 'comments', 'reopen', 'f1', 'c1'],
264
303
  { account: undefined },
@@ -270,12 +309,12 @@ describe('gog_drive_comments_reopen', () => {
270
309
 
271
310
  describe('gog_drive_du', () => {
272
311
  it('calls runOrDiagnose with no flags', async () => {
273
- await handlers.get('gog_drive_du')!({});
312
+ await harness.callTool('gog_drive_du', {});
274
313
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'du'], { account: undefined });
275
314
  });
276
315
 
277
316
  it('passes all flags', async () => {
278
- await handlers.get('gog_drive_du')!({
317
+ await harness.callTool('gog_drive_du', {
279
318
  parent: 'folder1', depth: 3, max: 20, sort: 'files', order: 'asc', noAllDrives: true, account: 'a@b.com',
280
319
  });
281
320
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -285,7 +324,7 @@ describe('gog_drive_du', () => {
285
324
  });
286
325
 
287
326
  it('handles depth/max=0 and omits noAllDrives when false', async () => {
288
- await handlers.get('gog_drive_du')!({ depth: 0, max: 0, noAllDrives: false });
327
+ await harness.callTool('gog_drive_du', { depth: 0, max: 0, noAllDrives: false });
289
328
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
290
329
  ['drive', 'du', '--depth=0', '--max=0'],
291
330
  { account: undefined },
@@ -295,12 +334,12 @@ describe('gog_drive_du', () => {
295
334
 
296
335
  describe('gog_drive_tree', () => {
297
336
  it('calls runOrDiagnose with no flags', async () => {
298
- await handlers.get('gog_drive_tree')!({});
337
+ await harness.callTool('gog_drive_tree', {});
299
338
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'tree'], { account: undefined });
300
339
  });
301
340
 
302
341
  it('passes all flags', async () => {
303
- await handlers.get('gog_drive_tree')!({ parent: 'folder1', depth: 4, max: 100, noAllDrives: true });
342
+ await harness.callTool('gog_drive_tree', { parent: 'folder1', depth: 4, max: 100, noAllDrives: true });
304
343
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
305
344
  ['drive', 'tree', '--parent=folder1', '--depth=4', '--max=100', '--no-all-drives'],
306
345
  { account: undefined },
@@ -308,19 +347,19 @@ describe('gog_drive_tree', () => {
308
347
  });
309
348
 
310
349
  it('handles depth=0 and omits noAllDrives when false', async () => {
311
- await handlers.get('gog_drive_tree')!({ depth: 0, noAllDrives: false });
350
+ await harness.callTool('gog_drive_tree', { depth: 0, noAllDrives: false });
312
351
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'tree', '--depth=0'], { account: undefined });
313
352
  });
314
353
  });
315
354
 
316
355
  describe('gog_drive_changes_start_token', () => {
317
356
  it('calls runOrDiagnose with no flags', async () => {
318
- await handlers.get('gog_drive_changes_start_token')!({});
357
+ await harness.callTool('gog_drive_changes_start_token', {});
319
358
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'changes', 'start-token'], { account: undefined });
320
359
  });
321
360
 
322
361
  it('passes --drive when provided', async () => {
323
- await handlers.get('gog_drive_changes_start_token')!({ drive: 'd1', account: 'a@b.com' });
362
+ await harness.callTool('gog_drive_changes_start_token', { drive: 'd1', account: 'a@b.com' });
324
363
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
325
364
  ['drive', 'changes', 'start-token', '--drive=d1'],
326
365
  { account: 'a@b.com' },
@@ -330,7 +369,7 @@ describe('gog_drive_changes_start_token', () => {
330
369
 
331
370
  describe('gog_drive_changes_list', () => {
332
371
  it('calls runOrDiagnose with token only', async () => {
333
- await handlers.get('gog_drive_changes_list')!({ token: 'tok1' });
372
+ await harness.callTool('gog_drive_changes_list', { token: 'tok1' });
334
373
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
335
374
  ['drive', 'changes', 'list', '--token=tok1'],
336
375
  { account: undefined },
@@ -338,7 +377,7 @@ describe('gog_drive_changes_list', () => {
338
377
  });
339
378
 
340
379
  it('passes all flags', async () => {
341
- await handlers.get('gog_drive_changes_list')!({
380
+ await harness.callTool('gog_drive_changes_list', {
342
381
  token: 'tok1', max: 50, page: 'p2', all: true, includeRemoved: true, drive: 'd1',
343
382
  });
344
383
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -348,7 +387,7 @@ describe('gog_drive_changes_list', () => {
348
387
  });
349
388
 
350
389
  it('omits boolean flags when false', async () => {
351
- await handlers.get('gog_drive_changes_list')!({ token: 'tok1', all: false, includeRemoved: false });
390
+ await harness.callTool('gog_drive_changes_list', { token: 'tok1', all: false, includeRemoved: false });
352
391
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
353
392
  ['drive', 'changes', 'list', '--token=tok1'],
354
393
  { account: undefined },
@@ -358,12 +397,12 @@ describe('gog_drive_changes_list', () => {
358
397
 
359
398
  describe('gog_drive_labels_list', () => {
360
399
  it('calls runOrDiagnose with no flags', async () => {
361
- await handlers.get('gog_drive_labels_list')!({});
400
+ await harness.callTool('gog_drive_labels_list', {});
362
401
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'labels', 'list'], { account: undefined });
363
402
  });
364
403
 
365
404
  it('passes all flags', async () => {
366
- await handlers.get('gog_drive_labels_list')!({
405
+ await harness.callTool('gog_drive_labels_list', {
367
406
  language: 'en', view: 'LABEL_VIEW_FULL', minimumRole: 'APPLIER', publishedOnly: true, adminAccess: true,
368
407
  });
369
408
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -373,19 +412,19 @@ describe('gog_drive_labels_list', () => {
373
412
  });
374
413
 
375
414
  it('omits boolean flags when false', async () => {
376
- await handlers.get('gog_drive_labels_list')!({ publishedOnly: false, adminAccess: false });
415
+ await harness.callTool('gog_drive_labels_list', { publishedOnly: false, adminAccess: false });
377
416
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'labels', 'list'], { account: undefined });
378
417
  });
379
418
  });
380
419
 
381
420
  describe('gog_drive_labels_get', () => {
382
421
  it('calls runOrDiagnose with name only', async () => {
383
- await handlers.get('gog_drive_labels_get')!({ name: 'labels/abc' });
422
+ await harness.callTool('gog_drive_labels_get', { name: 'labels/abc' });
384
423
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'labels', 'get', 'labels/abc'], { account: undefined });
385
424
  });
386
425
 
387
426
  it('passes all flags', async () => {
388
- await handlers.get('gog_drive_labels_get')!({
427
+ await harness.callTool('gog_drive_labels_get', {
389
428
  name: 'labels/abc', language: 'en', view: 'LABEL_VIEW_BASIC', adminAccess: true,
390
429
  });
391
430
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -395,14 +434,14 @@ describe('gog_drive_labels_get', () => {
395
434
  });
396
435
 
397
436
  it('omits --admin-access when false', async () => {
398
- await handlers.get('gog_drive_labels_get')!({ name: 'labels/abc', adminAccess: false });
437
+ await harness.callTool('gog_drive_labels_get', { name: 'labels/abc', adminAccess: false });
399
438
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'labels', 'get', 'labels/abc'], { account: undefined });
400
439
  });
401
440
  });
402
441
 
403
442
  describe('gog_drive_labels_file_list', () => {
404
443
  it('calls runOrDiagnose with fileId only', async () => {
405
- await handlers.get('gog_drive_labels_file_list')!({ fileId: 'f1' });
444
+ await harness.callTool('gog_drive_labels_file_list', { fileId: 'f1' });
406
445
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
407
446
  ['drive', 'labels', 'file', 'list', 'f1'],
408
447
  { account: undefined },
@@ -410,7 +449,7 @@ describe('gog_drive_labels_file_list', () => {
410
449
  });
411
450
 
412
451
  it('passes --max and --page when provided', async () => {
413
- await handlers.get('gog_drive_labels_file_list')!({ fileId: 'f1', max: 25, page: 'tok' });
452
+ await harness.callTool('gog_drive_labels_file_list', { fileId: 'f1', max: 25, page: 'tok' });
414
453
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
415
454
  ['drive', 'labels', 'file', 'list', 'f1', '--max=25', '--page=tok'],
416
455
  { account: undefined },
@@ -420,7 +459,7 @@ describe('gog_drive_labels_file_list', () => {
420
459
 
421
460
  describe('gog_drive_labels_file_apply', () => {
422
461
  it('calls runOrDiagnose with fileId and labelId only', async () => {
423
- await handlers.get('gog_drive_labels_file_apply')!({ fileId: 'f1', labelId: 'l1' });
462
+ await harness.callTool('gog_drive_labels_file_apply', { fileId: 'f1', labelId: 'l1' });
424
463
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
425
464
  ['drive', 'labels', 'file', 'apply', 'f1', 'l1'],
426
465
  { account: undefined },
@@ -428,7 +467,7 @@ describe('gog_drive_labels_file_apply', () => {
428
467
  });
429
468
 
430
469
  it('passes all repeatable field flags and fields-json', async () => {
431
- await handlers.get('gog_drive_labels_file_apply')!({
470
+ await harness.callTool('gog_drive_labels_file_apply', {
432
471
  fileId: 'f1',
433
472
  labelId: 'l1',
434
473
  text: ['t1=hello', 't2=world'],
@@ -455,7 +494,7 @@ describe('gog_drive_labels_file_apply', () => {
455
494
  });
456
495
 
457
496
  it('omits empty arrays', async () => {
458
- await handlers.get('gog_drive_labels_file_apply')!({
497
+ await harness.callTool('gog_drive_labels_file_apply', {
459
498
  fileId: 'f1', labelId: 'l1', text: [], selection: [], integer: [], date: [], user: [], unset: [],
460
499
  });
461
500
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -467,9 +506,9 @@ describe('gog_drive_labels_file_apply', () => {
467
506
 
468
507
  describe('gog_drive_labels_file_remove', () => {
469
508
  it('calls runOrDiagnose with fileId and labelId', async () => {
470
- await handlers.get('gog_drive_labels_file_remove')!({ fileId: 'f1', labelId: 'l1' });
509
+ await harness.callTool('gog_drive_labels_file_remove', { fileId: 'f1', labelId: 'l1' });
471
510
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
472
- ['drive', 'labels', 'file', 'remove', 'f1', 'l1'],
511
+ ['drive', 'labels', 'file', 'remove', 'f1', 'l1', '--force'],
473
512
  { account: undefined },
474
513
  );
475
514
  });
@@ -477,12 +516,12 @@ describe('gog_drive_labels_file_remove', () => {
477
516
 
478
517
  describe('gog_drive_activity', () => {
479
518
  it('calls runOrDiagnose with no flags', async () => {
480
- await handlers.get('gog_drive_activity')!({});
519
+ await harness.callTool('gog_drive_activity', {});
481
520
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'activity', 'query'], { account: undefined });
482
521
  });
483
522
 
484
523
  it('passes all flags', async () => {
485
- await handlers.get('gog_drive_activity')!({
524
+ await harness.callTool('gog_drive_activity', {
486
525
  file: 'f1',
487
526
  folder: 'fo1',
488
527
  actions: 'edit,share',
@@ -506,19 +545,19 @@ describe('gog_drive_activity', () => {
506
545
  });
507
546
 
508
547
  it('omits boolean flags when false', async () => {
509
- await handlers.get('gog_drive_activity')!({ all: false, consolidate: false });
548
+ await harness.callTool('gog_drive_activity', { all: false, consolidate: false });
510
549
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'activity', 'query'], { account: undefined });
511
550
  });
512
551
  });
513
552
 
514
553
  describe('gog_drive_audit_sharing', () => {
515
554
  it('calls runOrDiagnose with no flags', async () => {
516
- await handlers.get('gog_drive_audit_sharing')!({});
555
+ await harness.callTool('gog_drive_audit_sharing', {});
517
556
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(['drive', 'audit', 'sharing'], { account: undefined });
518
557
  });
519
558
 
520
559
  it('passes all flags', async () => {
521
- await handlers.get('gog_drive_audit_sharing')!({
560
+ await harness.callTool('gog_drive_audit_sharing', {
522
561
  file: 'f1',
523
562
  parent: 'fo1',
524
563
  depth: 3,
@@ -540,7 +579,7 @@ describe('gog_drive_audit_sharing', () => {
540
579
  });
541
580
 
542
581
  it('handles depth/max=0, empty domains, and omits booleans when false', async () => {
543
- await handlers.get('gog_drive_audit_sharing')!({
582
+ await harness.callTool('gog_drive_audit_sharing', {
544
583
  depth: 0, max: 0, internalDomain: [], publicOnly: false, externalOnly: false, noAllDrives: false,
545
584
  });
546
585
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -552,7 +591,7 @@ describe('gog_drive_audit_sharing', () => {
552
591
 
553
592
  describe('gog_drive_audit_user', () => {
554
593
  it('calls runOrDiagnose with user only', async () => {
555
- await handlers.get('gog_drive_audit_user')!({ user: 'a@b.com' });
594
+ await harness.callTool('gog_drive_audit_user', { user: 'a@b.com' });
556
595
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
557
596
  ['drive', 'audit', 'user', 'a@b.com'],
558
597
  { account: undefined },
@@ -560,7 +599,7 @@ describe('gog_drive_audit_user', () => {
560
599
  });
561
600
 
562
601
  it('passes all flags', async () => {
563
- await handlers.get('gog_drive_audit_user')!({
602
+ await harness.callTool('gog_drive_audit_user', {
564
603
  user: 'a@b.com', file: 'f1', parent: 'fo1', depth: 3, max: 100, noAllDrives: true,
565
604
  });
566
605
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
@@ -570,7 +609,7 @@ describe('gog_drive_audit_user', () => {
570
609
  });
571
610
 
572
611
  it('handles depth/max=0 and omits noAllDrives when false', async () => {
573
- await handlers.get('gog_drive_audit_user')!({ user: 'a@b.com', depth: 0, max: 0, noAllDrives: false });
612
+ await harness.callTool('gog_drive_audit_user', { user: 'a@b.com', depth: 0, max: 0, noAllDrives: false });
574
613
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
575
614
  ['drive', 'audit', 'user', 'a@b.com', '--depth=0', '--max=0'],
576
615
  { account: undefined },
@@ -581,7 +620,7 @@ describe('gog_drive_audit_user', () => {
581
620
  // gog 0.24.0
582
621
  describe('gog_drive_revisions_list', () => {
583
622
  it('lists revisions with pagination', async () => {
584
- await handlers.get('gog_drive_revisions_list')!({ fileId: 'f1', max: 10, page: 'tok', all: true });
623
+ await harness.callTool('gog_drive_revisions_list', { fileId: 'f1', max: 10, page: 'tok', all: true });
585
624
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
586
625
  ['drive', 'revisions', 'list', 'f1', '--max=10', '--page=tok', '--all'],
587
626
  { account: undefined },
@@ -591,10 +630,29 @@ describe('gog_drive_revisions_list', () => {
591
630
 
592
631
  describe('gog_drive_revisions_get', () => {
593
632
  it('gets one revision', async () => {
594
- await handlers.get('gog_drive_revisions_get')!({ fileId: 'f1', revisionId: 'r3', account: 'a@b.com' });
633
+ await harness.callTool('gog_drive_revisions_get', { fileId: 'f1', revisionId: 'r3', account: 'a@b.com' });
595
634
  expect(lib.runOrDiagnose).toHaveBeenCalledWith(
596
635
  ['drive', 'revisions', 'get', 'f1', 'r3'],
597
636
  { account: 'a@b.com' },
598
637
  );
599
638
  });
600
639
  });
640
+
641
+ // gog 0.25.0
642
+ describe('gog_drive_shortcut_create', () => {
643
+ it('creates a shortcut to a target in a folder', async () => {
644
+ await harness.callTool('gog_drive_shortcut_create', { targetId: 'f1', parent: 'folder9' });
645
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
646
+ ['drive', 'shortcut', 'create', 'f1', '--parent=folder9'],
647
+ { account: undefined },
648
+ );
649
+ });
650
+
651
+ it('passes an explicit shortcut name', async () => {
652
+ await harness.callTool('gog_drive_shortcut_create', { targetId: 'f1', parent: 'folder9', name: 'My Link', account: 'a@b.com' });
653
+ expect(lib.runOrDiagnose).toHaveBeenCalledWith(
654
+ ['drive', 'shortcut', 'create', 'f1', '--parent=folder9', '--name=My Link'],
655
+ { account: 'a@b.com' },
656
+ );
657
+ });
658
+ });
package/tsconfig.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "rootDir": "../"
6
6
  },
7
7
  "include": ["src/**/*", "../gogcli-mcp/src/**/*"],
8
- "exclude": ["node_modules", "dist"]
8
+ "exclude": ["node_modules", "dist", "../gogcli-mcp/src/worker.ts"]
9
9
  }