awolve-myoffice-cli 1.1.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.
Files changed (94) hide show
  1. package/README.md +205 -0
  2. package/dist/auth/cache-plugin.d.ts +20 -0
  3. package/dist/auth/cache-plugin.d.ts.map +1 -0
  4. package/dist/auth/cache-plugin.js +49 -0
  5. package/dist/auth/cache-plugin.js.map +1 -0
  6. package/dist/auth/config.d.ts +22 -0
  7. package/dist/auth/config.d.ts.map +1 -0
  8. package/dist/auth/config.js +64 -0
  9. package/dist/auth/config.js.map +1 -0
  10. package/dist/auth/device-code.d.ts +2 -0
  11. package/dist/auth/device-code.d.ts.map +1 -0
  12. package/dist/auth/device-code.js +38 -0
  13. package/dist/auth/device-code.js.map +1 -0
  14. package/dist/auth/index.d.ts +4 -0
  15. package/dist/auth/index.d.ts.map +1 -0
  16. package/dist/auth/index.js +4 -0
  17. package/dist/auth/index.js.map +1 -0
  18. package/dist/auth/login.d.ts +7 -0
  19. package/dist/auth/login.d.ts.map +1 -0
  20. package/dist/auth/login.js +22 -0
  21. package/dist/auth/login.js.map +1 -0
  22. package/dist/auth/token-manager.d.ts +4 -0
  23. package/dist/auth/token-manager.d.ts.map +1 -0
  24. package/dist/auth/token-manager.js +78 -0
  25. package/dist/auth/token-manager.js.map +1 -0
  26. package/dist/cli/formatter.d.ts +5 -0
  27. package/dist/cli/formatter.d.ts.map +1 -0
  28. package/dist/cli/formatter.js +317 -0
  29. package/dist/cli/formatter.js.map +1 -0
  30. package/dist/cli.d.ts +3 -0
  31. package/dist/cli.d.ts.map +1 -0
  32. package/dist/cli.js +802 -0
  33. package/dist/cli.js.map +1 -0
  34. package/dist/core/handler.d.ts +8 -0
  35. package/dist/core/handler.d.ts.map +1 -0
  36. package/dist/core/handler.js +289 -0
  37. package/dist/core/handler.js.map +1 -0
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +819 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/tools/calendar.d.ts +124 -0
  43. package/dist/tools/calendar.d.ts.map +1 -0
  44. package/dist/tools/calendar.js +129 -0
  45. package/dist/tools/calendar.js.map +1 -0
  46. package/dist/tools/chats.d.ts +66 -0
  47. package/dist/tools/chats.d.ts.map +1 -0
  48. package/dist/tools/chats.js +102 -0
  49. package/dist/tools/chats.js.map +1 -0
  50. package/dist/tools/contacts.d.ts +119 -0
  51. package/dist/tools/contacts.d.ts.map +1 -0
  52. package/dist/tools/contacts.js +136 -0
  53. package/dist/tools/contacts.js.map +1 -0
  54. package/dist/tools/index.d.ts +10 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +10 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/mail.d.ts +138 -0
  59. package/dist/tools/mail.d.ts.map +1 -0
  60. package/dist/tools/mail.js +187 -0
  61. package/dist/tools/mail.js.map +1 -0
  62. package/dist/tools/onedrive.d.ts +107 -0
  63. package/dist/tools/onedrive.d.ts.map +1 -0
  64. package/dist/tools/onedrive.js +136 -0
  65. package/dist/tools/onedrive.js.map +1 -0
  66. package/dist/tools/planner.d.ts +261 -0
  67. package/dist/tools/planner.d.ts.map +1 -0
  68. package/dist/tools/planner.js +401 -0
  69. package/dist/tools/planner.js.map +1 -0
  70. package/dist/tools/sharepoint.d.ts +138 -0
  71. package/dist/tools/sharepoint.d.ts.map +1 -0
  72. package/dist/tools/sharepoint.js +156 -0
  73. package/dist/tools/sharepoint.js.map +1 -0
  74. package/dist/tools/tasks.d.ts +107 -0
  75. package/dist/tools/tasks.d.ts.map +1 -0
  76. package/dist/tools/tasks.js +131 -0
  77. package/dist/tools/tasks.js.map +1 -0
  78. package/dist/tools/teams.d.ts +66 -0
  79. package/dist/tools/teams.d.ts.map +1 -0
  80. package/dist/tools/teams.js +69 -0
  81. package/dist/tools/teams.js.map +1 -0
  82. package/dist/utils/graph-client.d.ts +10 -0
  83. package/dist/utils/graph-client.d.ts.map +1 -0
  84. package/dist/utils/graph-client.js +49 -0
  85. package/dist/utils/graph-client.js.map +1 -0
  86. package/dist/utils/signature.d.ts +2 -0
  87. package/dist/utils/signature.d.ts.map +1 -0
  88. package/dist/utils/signature.js +17 -0
  89. package/dist/utils/signature.js.map +1 -0
  90. package/dist/utils/version.d.ts +2 -0
  91. package/dist/utils/version.d.ts.map +1 -0
  92. package/dist/utils/version.js +20 -0
  93. package/dist/utils/version.js.map +1 -0
  94. package/package.json +51 -0
package/dist/cli.js ADDED
@@ -0,0 +1,802 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { getVersion } from './utils/version.js';
4
+ import { executeCommand } from './core/handler.js';
5
+ import { isAuthenticated, authenticateWithDeviceCode } from './auth/index.js';
6
+ import { formatOutput } from './cli/formatter.js';
7
+ const program = new Command();
8
+ // Global state for JSON output mode
9
+ let jsonOutput = false;
10
+ let currentToolName;
11
+ function output(data) {
12
+ if (jsonOutput) {
13
+ console.log(JSON.stringify(data, null, 2));
14
+ }
15
+ else {
16
+ console.log(formatOutput(data, currentToolName));
17
+ }
18
+ }
19
+ function outputError(message, code) {
20
+ if (jsonOutput) {
21
+ console.error(JSON.stringify({ error: message, code: code || 'ERROR' }));
22
+ }
23
+ else {
24
+ console.error(`Error: ${message}`);
25
+ }
26
+ process.exit(1);
27
+ }
28
+ async function requireAuth() {
29
+ const authenticated = await isAuthenticated();
30
+ if (!authenticated) {
31
+ outputError('Not authenticated. Run: myoffice login', 'AUTH_REQUIRED');
32
+ }
33
+ }
34
+ async function runCommand(toolName, args = {}) {
35
+ await requireAuth();
36
+ currentToolName = toolName;
37
+ const result = await executeCommand(toolName, args);
38
+ if (result.success) {
39
+ output(result.data);
40
+ }
41
+ else {
42
+ outputError(result.error || 'Unknown error', result.code);
43
+ }
44
+ }
45
+ // Main program setup
46
+ program
47
+ .name('myoffice')
48
+ .description('Access your Microsoft 365 data from the command line')
49
+ .version(getVersion())
50
+ .option('--json', 'Output as JSON')
51
+ .hook('preAction', (thisCommand) => {
52
+ const opts = thisCommand.opts();
53
+ jsonOutput = opts.json || false;
54
+ });
55
+ // Login command
56
+ program
57
+ .command('login')
58
+ .description('Authenticate with Microsoft 365')
59
+ .action(async () => {
60
+ try {
61
+ console.log('Starting authentication...');
62
+ console.log('');
63
+ await authenticateWithDeviceCode();
64
+ console.log('');
65
+ console.log('Authentication successful!');
66
+ }
67
+ catch (error) {
68
+ const message = error instanceof Error ? error.message : String(error);
69
+ outputError(`Authentication failed: ${message}`, 'AUTH_FAILED');
70
+ }
71
+ });
72
+ // Status command
73
+ program
74
+ .command('status')
75
+ .description('Check authentication status')
76
+ .action(async () => {
77
+ currentToolName = 'auth_status';
78
+ const result = await executeCommand('auth_status', {});
79
+ if (result.success) {
80
+ output(result.data);
81
+ }
82
+ else {
83
+ outputError(result.error || 'Failed to get status', result.code);
84
+ }
85
+ });
86
+ // Debug command
87
+ program
88
+ .command('debug')
89
+ .description('Show debug information')
90
+ .action(async () => {
91
+ currentToolName = 'debug_info';
92
+ const result = await executeCommand('debug_info', {});
93
+ if (result.success) {
94
+ output(result.data);
95
+ }
96
+ else {
97
+ outputError(result.error || 'Failed to get debug info', result.code);
98
+ }
99
+ });
100
+ // Mail commands
101
+ const mailCmd = program
102
+ .command('mail')
103
+ .description('Email operations (list, read, send, reply, search, delete, mark)');
104
+ mailCmd
105
+ .command('list')
106
+ .description('List emails from a folder')
107
+ .option('--folder <name>', 'Folder name (default: inbox)')
108
+ .option('--limit <n>', 'Maximum emails to return', '25')
109
+ .option('--unread', 'Only show unread emails')
110
+ .action(async (opts) => {
111
+ await runCommand('mail_list', {
112
+ folder: opts.folder,
113
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
114
+ unreadOnly: opts.unread || undefined,
115
+ });
116
+ });
117
+ mailCmd
118
+ .command('read')
119
+ .description('Read a specific email')
120
+ .requiredOption('--id <messageId>', 'The message ID')
121
+ .action(async (opts) => {
122
+ await runCommand('mail_read', { messageId: opts.id });
123
+ });
124
+ mailCmd
125
+ .command('search')
126
+ .description('Search emails')
127
+ .requiredOption('--query <query>', 'Search query')
128
+ .option('--limit <n>', 'Maximum results', '25')
129
+ .action(async (opts) => {
130
+ await runCommand('mail_search', {
131
+ query: opts.query,
132
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
133
+ });
134
+ });
135
+ mailCmd
136
+ .command('send')
137
+ .description('Send an email')
138
+ .requiredOption('--to <emails...>', 'Recipient emails')
139
+ .requiredOption('--subject <subject>', 'Email subject')
140
+ .requiredOption('--body <body>', 'Email body')
141
+ .option('--cc <emails...>', 'CC recipients')
142
+ .option('--bcc <emails...>', 'BCC recipients')
143
+ .option('--no-html', 'Send as plain text')
144
+ .option('--no-signature', 'Do not append signature')
145
+ .action(async (opts) => {
146
+ await runCommand('mail_send', {
147
+ to: opts.to,
148
+ subject: opts.subject,
149
+ body: opts.body,
150
+ cc: opts.cc,
151
+ bcc: opts.bcc,
152
+ isHtml: opts.html !== false,
153
+ useSignature: opts.signature !== false,
154
+ });
155
+ });
156
+ mailCmd
157
+ .command('reply')
158
+ .description('Reply to an email')
159
+ .requiredOption('--id <messageId>', 'The message ID to reply to')
160
+ .requiredOption('--body <body>', 'Reply body')
161
+ .option('--all', 'Reply to all recipients')
162
+ .option('--no-html', 'Send as plain text')
163
+ .option('--signature', 'Append signature')
164
+ .action(async (opts) => {
165
+ await runCommand('mail_reply', {
166
+ messageId: opts.id,
167
+ body: opts.body,
168
+ replyAll: opts.all || false,
169
+ isHtml: opts.html !== false,
170
+ useSignature: opts.signature || false,
171
+ });
172
+ });
173
+ mailCmd
174
+ .command('delete')
175
+ .description('Delete an email')
176
+ .requiredOption('--id <messageId>', 'The message ID to delete')
177
+ .action(async (opts) => {
178
+ await runCommand('mail_delete', { messageId: opts.id });
179
+ });
180
+ mailCmd
181
+ .command('mark')
182
+ .description('Mark an email as read or unread')
183
+ .requiredOption('--id <messageId>', 'The message ID')
184
+ .option('--unread', 'Mark as unread (default: mark as read)')
185
+ .action(async (opts) => {
186
+ await runCommand('mail_mark_read', {
187
+ messageId: opts.id,
188
+ isRead: !opts.unread,
189
+ });
190
+ });
191
+ // Calendar commands
192
+ const calendarCmd = program
193
+ .command('calendar')
194
+ .description('Calendar events (list, get, create, update, delete)');
195
+ calendarCmd
196
+ .command('list')
197
+ .description('List calendar events')
198
+ .option('--start <date>', 'Start date (ISO format)')
199
+ .option('--end <date>', 'End date (ISO format)')
200
+ .option('--limit <n>', 'Maximum events', '50')
201
+ .action(async (opts) => {
202
+ await runCommand('calendar_list', {
203
+ startDate: opts.start,
204
+ endDate: opts.end,
205
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
206
+ });
207
+ });
208
+ calendarCmd
209
+ .command('get')
210
+ .description('Get details of a calendar event')
211
+ .requiredOption('--id <eventId>', 'The event ID')
212
+ .action(async (opts) => {
213
+ await runCommand('calendar_get', { eventId: opts.id });
214
+ });
215
+ calendarCmd
216
+ .command('create')
217
+ .description('Create a calendar event')
218
+ .requiredOption('--subject <subject>', 'Event title')
219
+ .requiredOption('--start <datetime>', 'Start datetime (ISO)')
220
+ .requiredOption('--end <datetime>', 'End datetime (ISO)')
221
+ .option('--timezone <tz>', 'Timezone (default: UTC)')
222
+ .option('--location <location>', 'Event location')
223
+ .option('--body <body>', 'Event description')
224
+ .option('--attendees <emails...>', 'Attendee emails')
225
+ .option('--online', 'Create Teams meeting')
226
+ .action(async (opts) => {
227
+ await runCommand('calendar_create', {
228
+ subject: opts.subject,
229
+ start: opts.start,
230
+ end: opts.end,
231
+ timeZone: opts.timezone,
232
+ location: opts.location,
233
+ body: opts.body,
234
+ attendees: opts.attendees,
235
+ isOnlineMeeting: opts.online || false,
236
+ });
237
+ });
238
+ calendarCmd
239
+ .command('update')
240
+ .description('Update a calendar event')
241
+ .requiredOption('--id <eventId>', 'The event ID')
242
+ .option('--subject <subject>', 'New title')
243
+ .option('--start <datetime>', 'New start datetime')
244
+ .option('--end <datetime>', 'New end datetime')
245
+ .option('--location <location>', 'New location')
246
+ .option('--body <body>', 'New description')
247
+ .action(async (opts) => {
248
+ await runCommand('calendar_update', {
249
+ eventId: opts.id,
250
+ subject: opts.subject,
251
+ start: opts.start,
252
+ end: opts.end,
253
+ location: opts.location,
254
+ body: opts.body,
255
+ });
256
+ });
257
+ calendarCmd
258
+ .command('delete')
259
+ .description('Delete a calendar event')
260
+ .requiredOption('--id <eventId>', 'The event ID to delete')
261
+ .action(async (opts) => {
262
+ await runCommand('calendar_delete', { eventId: opts.id });
263
+ });
264
+ // Tasks commands
265
+ const tasksCmd = program
266
+ .command('tasks')
267
+ .description('Microsoft To Do (lists, list, create, update, complete, delete)');
268
+ tasksCmd
269
+ .command('lists')
270
+ .description('List all task lists')
271
+ .action(async () => {
272
+ await runCommand('tasks_list_lists', {});
273
+ });
274
+ tasksCmd
275
+ .command('list')
276
+ .description('List tasks from a task list')
277
+ .option('--list-id <listId>', 'Task list ID (default: default list)')
278
+ .option('--include-completed', 'Include completed tasks')
279
+ .option('--limit <n>', 'Maximum tasks', '50')
280
+ .action(async (opts) => {
281
+ await runCommand('tasks_list', {
282
+ listId: opts.listId,
283
+ includeCompleted: opts.includeCompleted || false,
284
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
285
+ });
286
+ });
287
+ tasksCmd
288
+ .command('create')
289
+ .description('Create a new task')
290
+ .requiredOption('--title <title>', 'Task title')
291
+ .option('--list-id <listId>', 'Task list ID')
292
+ .option('--due <date>', 'Due date (ISO)')
293
+ .option('--importance <level>', 'Importance: low, normal, high')
294
+ .option('--body <body>', 'Task notes')
295
+ .action(async (opts) => {
296
+ await runCommand('tasks_create', {
297
+ title: opts.title,
298
+ listId: opts.listId,
299
+ dueDate: opts.due,
300
+ importance: opts.importance,
301
+ body: opts.body,
302
+ });
303
+ });
304
+ tasksCmd
305
+ .command('update')
306
+ .description('Update a task')
307
+ .requiredOption('--id <taskId>', 'Task ID')
308
+ .option('--list-id <listId>', 'Task list ID')
309
+ .option('--title <title>', 'New title')
310
+ .option('--due <date>', 'New due date')
311
+ .option('--importance <level>', 'New importance: low, normal, high')
312
+ .option('--body <body>', 'New notes')
313
+ .action(async (opts) => {
314
+ await runCommand('tasks_update', {
315
+ taskId: opts.id,
316
+ listId: opts.listId,
317
+ title: opts.title,
318
+ dueDate: opts.due,
319
+ importance: opts.importance,
320
+ body: opts.body,
321
+ });
322
+ });
323
+ tasksCmd
324
+ .command('complete')
325
+ .description('Mark a task as completed')
326
+ .requiredOption('--id <taskId>', 'Task ID')
327
+ .option('--list-id <listId>', 'Task list ID')
328
+ .action(async (opts) => {
329
+ await runCommand('tasks_complete', {
330
+ taskId: opts.id,
331
+ listId: opts.listId,
332
+ });
333
+ });
334
+ tasksCmd
335
+ .command('delete')
336
+ .description('Delete a task')
337
+ .requiredOption('--id <taskId>', 'Task ID')
338
+ .option('--list-id <listId>', 'Task list ID')
339
+ .action(async (opts) => {
340
+ await runCommand('tasks_delete', {
341
+ taskId: opts.id,
342
+ listId: opts.listId,
343
+ });
344
+ });
345
+ // Files (OneDrive) commands
346
+ const filesCmd = program
347
+ .command('files')
348
+ .description('OneDrive files (list, get, search, read, mkdir, shared)');
349
+ filesCmd
350
+ .command('list')
351
+ .description('List files and folders')
352
+ .option('--path <path>', 'Folder path (default: root)')
353
+ .option('--limit <n>', 'Maximum items', '50')
354
+ .action(async (opts) => {
355
+ await runCommand('onedrive_list', {
356
+ path: opts.path,
357
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
358
+ });
359
+ });
360
+ filesCmd
361
+ .command('get')
362
+ .description('Get metadata for a file or folder')
363
+ .requiredOption('--path <path>', 'File/folder path')
364
+ .action(async (opts) => {
365
+ await runCommand('onedrive_get', { path: opts.path });
366
+ });
367
+ filesCmd
368
+ .command('search')
369
+ .description('Search for files')
370
+ .requiredOption('--query <query>', 'Search query')
371
+ .option('--limit <n>', 'Maximum results', '25')
372
+ .action(async (opts) => {
373
+ await runCommand('onedrive_search', {
374
+ query: opts.query,
375
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
376
+ });
377
+ });
378
+ filesCmd
379
+ .command('read')
380
+ .description('Read content of a text file')
381
+ .requiredOption('--path <path>', 'File path')
382
+ .action(async (opts) => {
383
+ await runCommand('onedrive_read', { path: opts.path });
384
+ });
385
+ filesCmd
386
+ .command('mkdir')
387
+ .description('Create a new folder')
388
+ .requiredOption('--name <name>', 'Folder name')
389
+ .option('--parent <path>', 'Parent path (default: root)')
390
+ .action(async (opts) => {
391
+ await runCommand('onedrive_create_folder', {
392
+ name: opts.name,
393
+ parentPath: opts.parent,
394
+ });
395
+ });
396
+ filesCmd
397
+ .command('shared')
398
+ .description('List files shared with you')
399
+ .option('--limit <n>', 'Maximum items', '50')
400
+ .action(async (opts) => {
401
+ await runCommand('onedrive_shared_with_me', {
402
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
403
+ });
404
+ });
405
+ // SharePoint commands
406
+ const sharepointCmd = program
407
+ .command('sharepoint')
408
+ .description('SharePoint sites and document libraries');
409
+ sharepointCmd
410
+ .command('sites')
411
+ .description('List SharePoint sites')
412
+ .option('--search <query>', 'Search query to find sites')
413
+ .option('--limit <n>', 'Maximum sites', '50')
414
+ .action(async (opts) => {
415
+ await runCommand('sharepoint_list_sites', {
416
+ search: opts.search,
417
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
418
+ });
419
+ });
420
+ sharepointCmd
421
+ .command('site')
422
+ .description('Get details of a SharePoint site')
423
+ .requiredOption('--id <siteId>', 'Site ID or hostname:path')
424
+ .action(async (opts) => {
425
+ await runCommand('sharepoint_get_site', { siteId: opts.id });
426
+ });
427
+ sharepointCmd
428
+ .command('drives')
429
+ .description('List document libraries in a site')
430
+ .requiredOption('--site-id <siteId>', 'Site ID')
431
+ .option('--limit <n>', 'Maximum drives', '50')
432
+ .action(async (opts) => {
433
+ await runCommand('sharepoint_list_drives', {
434
+ siteId: opts.siteId,
435
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
436
+ });
437
+ });
438
+ sharepointCmd
439
+ .command('files')
440
+ .description('List files in a document library')
441
+ .requiredOption('--drive-id <driveId>', 'Drive ID')
442
+ .option('--path <path>', 'Folder path (default: root)')
443
+ .option('--limit <n>', 'Maximum items', '50')
444
+ .action(async (opts) => {
445
+ await runCommand('sharepoint_list_files', {
446
+ driveId: opts.driveId,
447
+ path: opts.path,
448
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
449
+ });
450
+ });
451
+ sharepointCmd
452
+ .command('file')
453
+ .description('Get metadata for a file')
454
+ .requiredOption('--drive-id <driveId>', 'Drive ID')
455
+ .requiredOption('--path <path>', 'File path')
456
+ .action(async (opts) => {
457
+ await runCommand('sharepoint_get_file', {
458
+ driveId: opts.driveId,
459
+ path: opts.path,
460
+ });
461
+ });
462
+ sharepointCmd
463
+ .command('read')
464
+ .description('Read content of a text file')
465
+ .requiredOption('--drive-id <driveId>', 'Drive ID')
466
+ .requiredOption('--path <path>', 'File path')
467
+ .action(async (opts) => {
468
+ await runCommand('sharepoint_read_file', {
469
+ driveId: opts.driveId,
470
+ path: opts.path,
471
+ });
472
+ });
473
+ sharepointCmd
474
+ .command('search')
475
+ .description('Search for files in a document library')
476
+ .requiredOption('--drive-id <driveId>', 'Drive ID')
477
+ .requiredOption('--query <query>', 'Search query')
478
+ .option('--limit <n>', 'Maximum results', '25')
479
+ .action(async (opts) => {
480
+ await runCommand('sharepoint_search_files', {
481
+ driveId: opts.driveId,
482
+ query: opts.query,
483
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
484
+ });
485
+ });
486
+ // Contacts commands
487
+ const contactsCmd = program
488
+ .command('contacts')
489
+ .description('Contacts (list, search, get, create, update)');
490
+ contactsCmd
491
+ .command('list')
492
+ .description('List contacts')
493
+ .option('--limit <n>', 'Maximum contacts', '50')
494
+ .action(async (opts) => {
495
+ await runCommand('contacts_list', {
496
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
497
+ });
498
+ });
499
+ contactsCmd
500
+ .command('search')
501
+ .description('Search contacts')
502
+ .requiredOption('--query <query>', 'Search query')
503
+ .option('--limit <n>', 'Maximum results', '25')
504
+ .action(async (opts) => {
505
+ await runCommand('contacts_search', {
506
+ query: opts.query,
507
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
508
+ });
509
+ });
510
+ contactsCmd
511
+ .command('get')
512
+ .description('Get details of a contact')
513
+ .requiredOption('--id <contactId>', 'Contact ID')
514
+ .action(async (opts) => {
515
+ await runCommand('contacts_get', { contactId: opts.id });
516
+ });
517
+ contactsCmd
518
+ .command('create')
519
+ .description('Create a new contact')
520
+ .option('--given-name <name>', 'First name')
521
+ .option('--surname <name>', 'Last name')
522
+ .option('--email <email>', 'Email address')
523
+ .option('--mobile <phone>', 'Mobile phone')
524
+ .option('--business-phone <phone>', 'Business phone')
525
+ .option('--company <name>', 'Company name')
526
+ .option('--job-title <title>', 'Job title')
527
+ .action(async (opts) => {
528
+ await runCommand('contacts_create', {
529
+ givenName: opts.givenName,
530
+ surname: opts.surname,
531
+ email: opts.email,
532
+ mobilePhone: opts.mobile,
533
+ businessPhone: opts.businessPhone,
534
+ companyName: opts.company,
535
+ jobTitle: opts.jobTitle,
536
+ });
537
+ });
538
+ contactsCmd
539
+ .command('update')
540
+ .description('Update an existing contact')
541
+ .requiredOption('--id <contactId>', 'Contact ID')
542
+ .option('--given-name <name>', 'First name')
543
+ .option('--surname <name>', 'Last name')
544
+ .option('--email <email>', 'Email address')
545
+ .option('--mobile <phone>', 'Mobile phone')
546
+ .option('--business-phone <phone>', 'Business phone')
547
+ .option('--company <name>', 'Company name')
548
+ .option('--job-title <title>', 'Job title')
549
+ .action(async (opts) => {
550
+ await runCommand('contacts_update', {
551
+ contactId: opts.id,
552
+ givenName: opts.givenName,
553
+ surname: opts.surname,
554
+ email: opts.email,
555
+ mobilePhone: opts.mobile,
556
+ businessPhone: opts.businessPhone,
557
+ companyName: opts.company,
558
+ jobTitle: opts.jobTitle,
559
+ });
560
+ });
561
+ // Teams commands
562
+ const teamsCmd = program
563
+ .command('teams')
564
+ .description('Teams channels and messages');
565
+ teamsCmd
566
+ .command('list')
567
+ .description('List Teams you are a member of')
568
+ .option('--limit <n>', 'Maximum teams', '50')
569
+ .action(async (opts) => {
570
+ await runCommand('teams_list', {
571
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
572
+ });
573
+ });
574
+ teamsCmd
575
+ .command('channels')
576
+ .description('List channels in a Team')
577
+ .requiredOption('--team-id <teamId>', 'Team ID')
578
+ .action(async (opts) => {
579
+ await runCommand('teams_channels', { teamId: opts.teamId });
580
+ });
581
+ teamsCmd
582
+ .command('messages')
583
+ .description('Read messages from a channel')
584
+ .requiredOption('--team-id <teamId>', 'Team ID')
585
+ .requiredOption('--channel-id <channelId>', 'Channel ID')
586
+ .option('--limit <n>', 'Maximum messages', '25')
587
+ .action(async (opts) => {
588
+ await runCommand('teams_channel_messages', {
589
+ teamId: opts.teamId,
590
+ channelId: opts.channelId,
591
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
592
+ });
593
+ });
594
+ teamsCmd
595
+ .command('post')
596
+ .description('Post a message to a channel')
597
+ .requiredOption('--team-id <teamId>', 'Team ID')
598
+ .requiredOption('--channel-id <channelId>', 'Channel ID')
599
+ .requiredOption('--content <content>', 'Message content')
600
+ .action(async (opts) => {
601
+ await runCommand('teams_channel_post', {
602
+ teamId: opts.teamId,
603
+ channelId: opts.channelId,
604
+ content: opts.content,
605
+ });
606
+ });
607
+ // Chats commands
608
+ const chatsCmd = program
609
+ .command('chats')
610
+ .description('1:1 and group chats');
611
+ chatsCmd
612
+ .command('list')
613
+ .description('List your chats')
614
+ .option('--limit <n>', 'Maximum chats', '25')
615
+ .action(async (opts) => {
616
+ await runCommand('chats_list', {
617
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
618
+ });
619
+ });
620
+ chatsCmd
621
+ .command('messages')
622
+ .description('Read messages from a chat')
623
+ .requiredOption('--chat-id <chatId>', 'Chat ID')
624
+ .option('--limit <n>', 'Maximum messages', '25')
625
+ .action(async (opts) => {
626
+ await runCommand('chats_messages', {
627
+ chatId: opts.chatId,
628
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
629
+ });
630
+ });
631
+ chatsCmd
632
+ .command('send')
633
+ .description('Send a message in a chat')
634
+ .requiredOption('--chat-id <chatId>', 'Chat ID')
635
+ .requiredOption('--content <content>', 'Message content')
636
+ .action(async (opts) => {
637
+ await runCommand('chats_send', {
638
+ chatId: opts.chatId,
639
+ content: opts.content,
640
+ });
641
+ });
642
+ chatsCmd
643
+ .command('create')
644
+ .description('Create a new chat')
645
+ .requiredOption('--members <emails...>', 'Email addresses of chat members')
646
+ .option('--topic <topic>', 'Chat topic/title (for group chats)')
647
+ .action(async (opts) => {
648
+ await runCommand('chats_create', {
649
+ members: opts.members,
650
+ topic: opts.topic,
651
+ });
652
+ });
653
+ // Planner commands
654
+ const plannerCmd = program
655
+ .command('planner')
656
+ .description('Planner plans, buckets, and tasks');
657
+ plannerCmd
658
+ .command('plans')
659
+ .description('List all Planner plans')
660
+ .option('--limit <n>', 'Maximum plans', '50')
661
+ .action(async (opts) => {
662
+ await runCommand('planner_list_plans', {
663
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
664
+ });
665
+ });
666
+ plannerCmd
667
+ .command('plan')
668
+ .description('Get details of a plan')
669
+ .requiredOption('--id <planId>', 'Plan ID')
670
+ .action(async (opts) => {
671
+ await runCommand('planner_get_plan', { planId: opts.id });
672
+ });
673
+ plannerCmd
674
+ .command('buckets')
675
+ .description('List buckets in a plan')
676
+ .requiredOption('--plan-id <planId>', 'Plan ID')
677
+ .action(async (opts) => {
678
+ await runCommand('planner_list_buckets', { planId: opts.planId });
679
+ });
680
+ plannerCmd
681
+ .command('bucket-create')
682
+ .description('Create a new bucket')
683
+ .requiredOption('--plan-id <planId>', 'Plan ID')
684
+ .requiredOption('--name <name>', 'Bucket name')
685
+ .action(async (opts) => {
686
+ await runCommand('planner_create_bucket', {
687
+ planId: opts.planId,
688
+ name: opts.name,
689
+ });
690
+ });
691
+ plannerCmd
692
+ .command('bucket-update')
693
+ .description('Update a bucket')
694
+ .requiredOption('--id <bucketId>', 'Bucket ID')
695
+ .requiredOption('--name <name>', 'New bucket name')
696
+ .action(async (opts) => {
697
+ await runCommand('planner_update_bucket', {
698
+ bucketId: opts.id,
699
+ name: opts.name,
700
+ });
701
+ });
702
+ plannerCmd
703
+ .command('bucket-delete')
704
+ .description('Delete a bucket')
705
+ .requiredOption('--id <bucketId>', 'Bucket ID')
706
+ .action(async (opts) => {
707
+ await runCommand('planner_delete_bucket', { bucketId: opts.id });
708
+ });
709
+ plannerCmd
710
+ .command('tasks')
711
+ .description('List tasks in a plan')
712
+ .requiredOption('--plan-id <planId>', 'Plan ID')
713
+ .option('--bucket-id <bucketId>', 'Filter by bucket')
714
+ .option('--limit <n>', 'Maximum tasks', '100')
715
+ .action(async (opts) => {
716
+ await runCommand('planner_list_tasks', {
717
+ planId: opts.planId,
718
+ bucketId: opts.bucketId,
719
+ maxItems: opts.limit ? parseInt(opts.limit, 10) : undefined,
720
+ });
721
+ });
722
+ plannerCmd
723
+ .command('task')
724
+ .description('Get details of a task')
725
+ .requiredOption('--id <taskId>', 'Task ID')
726
+ .action(async (opts) => {
727
+ await runCommand('planner_get_task', { taskId: opts.id });
728
+ });
729
+ plannerCmd
730
+ .command('task-create')
731
+ .description('Create a new task')
732
+ .requiredOption('--plan-id <planId>', 'Plan ID')
733
+ .requiredOption('--title <title>', 'Task title')
734
+ .option('--bucket-id <bucketId>', 'Bucket ID')
735
+ .option('--assignments <emails...>', 'Assign to users (emails)')
736
+ .option('--due <datetime>', 'Due date (ISO)')
737
+ .option('--start <datetime>', 'Start date (ISO)')
738
+ .option('--priority <level>', 'Priority: urgent, important, medium, low')
739
+ .option('--progress <status>', 'Progress: notStarted, inProgress, completed')
740
+ .action(async (opts) => {
741
+ await runCommand('planner_create_task', {
742
+ planId: opts.planId,
743
+ title: opts.title,
744
+ bucketId: opts.bucketId,
745
+ assignments: opts.assignments,
746
+ dueDateTime: opts.due,
747
+ startDateTime: opts.start,
748
+ priority: opts.priority,
749
+ progress: opts.progress,
750
+ });
751
+ });
752
+ plannerCmd
753
+ .command('task-update')
754
+ .description('Update a task')
755
+ .requiredOption('--id <taskId>', 'Task ID')
756
+ .option('--title <title>', 'New title')
757
+ .option('--bucket-id <bucketId>', 'Move to bucket')
758
+ .option('--assignments <emails...>', 'Assign to users (replaces existing)')
759
+ .option('--due <datetime>', 'New due date')
760
+ .option('--start <datetime>', 'New start date')
761
+ .option('--priority <level>', 'New priority')
762
+ .option('--progress <status>', 'New progress')
763
+ .action(async (opts) => {
764
+ await runCommand('planner_update_task', {
765
+ taskId: opts.id,
766
+ title: opts.title,
767
+ bucketId: opts.bucketId,
768
+ assignments: opts.assignments,
769
+ dueDateTime: opts.due,
770
+ startDateTime: opts.start,
771
+ priority: opts.priority,
772
+ progress: opts.progress,
773
+ });
774
+ });
775
+ plannerCmd
776
+ .command('task-delete')
777
+ .description('Delete a task')
778
+ .requiredOption('--id <taskId>', 'Task ID')
779
+ .action(async (opts) => {
780
+ await runCommand('planner_delete_task', { taskId: opts.id });
781
+ });
782
+ plannerCmd
783
+ .command('task-details')
784
+ .description('Get task details (description, checklist)')
785
+ .requiredOption('--id <taskId>', 'Task ID')
786
+ .action(async (opts) => {
787
+ await runCommand('planner_get_task_details', { taskId: opts.id });
788
+ });
789
+ plannerCmd
790
+ .command('task-details-update')
791
+ .description('Update task description and checklist')
792
+ .requiredOption('--id <taskId>', 'Task ID')
793
+ .option('--description <text>', 'Task description')
794
+ .action(async (opts) => {
795
+ await runCommand('planner_update_task_details', {
796
+ taskId: opts.id,
797
+ description: opts.description,
798
+ });
799
+ });
800
+ // Parse and execute
801
+ program.parse();
802
+ //# sourceMappingURL=cli.js.map