m365-agent-cli 1.2.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.
- package/LICENSE +22 -0
- package/README.md +916 -0
- package/package.json +50 -0
- package/src/cli.ts +100 -0
- package/src/commands/auto-reply.ts +182 -0
- package/src/commands/calendar.ts +576 -0
- package/src/commands/counter.ts +87 -0
- package/src/commands/create-event.ts +544 -0
- package/src/commands/delegates.ts +286 -0
- package/src/commands/delete-event.ts +321 -0
- package/src/commands/drafts.ts +502 -0
- package/src/commands/files.ts +532 -0
- package/src/commands/find.ts +195 -0
- package/src/commands/findtime.ts +270 -0
- package/src/commands/folders.ts +177 -0
- package/src/commands/forward-event.ts +49 -0
- package/src/commands/graph-calendar.ts +217 -0
- package/src/commands/login.ts +195 -0
- package/src/commands/mail.ts +950 -0
- package/src/commands/oof.ts +263 -0
- package/src/commands/outlook-categories.ts +173 -0
- package/src/commands/outlook-graph.ts +880 -0
- package/src/commands/planner.ts +1678 -0
- package/src/commands/respond.ts +291 -0
- package/src/commands/rooms.ts +210 -0
- package/src/commands/rules.ts +511 -0
- package/src/commands/schedule.ts +109 -0
- package/src/commands/send.ts +204 -0
- package/src/commands/serve.ts +14 -0
- package/src/commands/sharepoint.ts +179 -0
- package/src/commands/site-pages.ts +163 -0
- package/src/commands/subscribe.ts +103 -0
- package/src/commands/subscriptions.ts +29 -0
- package/src/commands/suggest.ts +155 -0
- package/src/commands/todo.ts +2092 -0
- package/src/commands/update-event.ts +608 -0
- package/src/commands/update.ts +88 -0
- package/src/commands/verify-token.ts +62 -0
- package/src/commands/whoami.ts +74 -0
- package/src/index.ts +190 -0
- package/src/lib/atomic-write.ts +20 -0
- package/src/lib/attach-link-spec.test.ts +24 -0
- package/src/lib/attach-link-spec.ts +70 -0
- package/src/lib/attachments.ts +79 -0
- package/src/lib/auth.ts +192 -0
- package/src/lib/calendar-range.test.ts +41 -0
- package/src/lib/calendar-range.ts +103 -0
- package/src/lib/dates.test.ts +74 -0
- package/src/lib/dates.ts +137 -0
- package/src/lib/delegate-client.test.ts +74 -0
- package/src/lib/delegate-client.ts +322 -0
- package/src/lib/ews-client.ts +3418 -0
- package/src/lib/git-commit.ts +4 -0
- package/src/lib/glitchtip-eligibility.ts +220 -0
- package/src/lib/glitchtip.ts +253 -0
- package/src/lib/global-env.ts +3 -0
- package/src/lib/graph-auth.ts +223 -0
- package/src/lib/graph-calendar-client.test.ts +118 -0
- package/src/lib/graph-calendar-client.ts +112 -0
- package/src/lib/graph-client.test.ts +107 -0
- package/src/lib/graph-client.ts +1058 -0
- package/src/lib/graph-constants.ts +12 -0
- package/src/lib/graph-directory.ts +116 -0
- package/src/lib/graph-event.ts +134 -0
- package/src/lib/graph-schedule.ts +173 -0
- package/src/lib/graph-subscriptions.ts +94 -0
- package/src/lib/graph-user-path.ts +13 -0
- package/src/lib/jwt-utils.ts +34 -0
- package/src/lib/markdown.test.ts +21 -0
- package/src/lib/markdown.ts +174 -0
- package/src/lib/mime-type.ts +106 -0
- package/src/lib/oof-client.test.ts +59 -0
- package/src/lib/oof-client.ts +122 -0
- package/src/lib/outlook-graph-client.test.ts +146 -0
- package/src/lib/outlook-graph-client.ts +649 -0
- package/src/lib/outlook-master-categories.ts +145 -0
- package/src/lib/package-info.ts +59 -0
- package/src/lib/places-client.ts +144 -0
- package/src/lib/planner-client.ts +1226 -0
- package/src/lib/rules-client.ts +178 -0
- package/src/lib/sharepoint-client.ts +101 -0
- package/src/lib/site-pages-client.ts +73 -0
- package/src/lib/todo-client.test.ts +298 -0
- package/src/lib/todo-client.ts +1309 -0
- package/src/lib/url-validation.ts +40 -0
- package/src/lib/utils.ts +45 -0
- package/src/lib/webhook-server.ts +51 -0
- package/src/test/auth.test.ts +104 -0
- package/src/test/cli.integration.test.ts +1083 -0
- package/src/test/ews-client.test.ts +268 -0
- package/src/test/mocks/index.ts +375 -0
- package/src/test/mocks/responses.ts +861 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { resolveGraphAuth } from '../lib/graph-auth.js';
|
|
3
|
+
import { type AttendeeBase, type FindMeetingTimesRequest, findMeetingTimes } from '../lib/graph-schedule.js';
|
|
4
|
+
|
|
5
|
+
export const suggestCommand = new Command('suggest')
|
|
6
|
+
.description('AI meeting time suggestions')
|
|
7
|
+
.option('--attendees <emails>', 'Comma-separated email addresses to invite')
|
|
8
|
+
.option('--duration <duration>', 'Duration (e.g., 30m, 1h)', '30m')
|
|
9
|
+
.option('--days <days>', 'Number of days to check from now', '5')
|
|
10
|
+
.option('--json', 'Output as JSON')
|
|
11
|
+
.option('--token <token>', 'Graph access token (bypass interactive auth)')
|
|
12
|
+
.option('--identity <name>', 'Graph token cache identity (default: default)')
|
|
13
|
+
.option('--user <email>', 'Mailbox whose calendar is used for findMeetingTimes (delegation)')
|
|
14
|
+
.action(
|
|
15
|
+
async (options: {
|
|
16
|
+
attendees?: string;
|
|
17
|
+
duration: string;
|
|
18
|
+
days: string;
|
|
19
|
+
json?: boolean;
|
|
20
|
+
token?: string;
|
|
21
|
+
identity?: string;
|
|
22
|
+
user?: string;
|
|
23
|
+
}) => {
|
|
24
|
+
const authResult = await resolveGraphAuth({ token: options.token, identity: options.identity });
|
|
25
|
+
if (!authResult.success || !authResult.token) {
|
|
26
|
+
if (options.json) {
|
|
27
|
+
console.log(JSON.stringify({ error: authResult.error }, null, 2));
|
|
28
|
+
} else {
|
|
29
|
+
console.error(`Error: ${authResult.error}`);
|
|
30
|
+
}
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const durationMapping: Record<string, string> = {
|
|
35
|
+
'15m': 'PT15M',
|
|
36
|
+
'30m': 'PT30M',
|
|
37
|
+
'45m': 'PT45M',
|
|
38
|
+
'1h': 'PT1H',
|
|
39
|
+
'2h': 'PT2H'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const durationKey = options.duration.trim().toLowerCase();
|
|
43
|
+
if (!Object.hasOwn(durationMapping, durationKey)) {
|
|
44
|
+
const message = `Invalid duration "${options.duration}". Supported values are: ${Object.keys(durationMapping).join(', ')}.`;
|
|
45
|
+
if (options.json) {
|
|
46
|
+
console.log(JSON.stringify({ error: message }, null, 2));
|
|
47
|
+
} else {
|
|
48
|
+
console.error(`Error: ${message}`);
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const durationStr = durationMapping[durationKey];
|
|
54
|
+
const days = parseInt(options.days, 10) || 5;
|
|
55
|
+
|
|
56
|
+
const startDateTime = new Date();
|
|
57
|
+
const endDateTime = new Date(startDateTime);
|
|
58
|
+
endDateTime.setDate(startDateTime.getDate() + days);
|
|
59
|
+
|
|
60
|
+
// dateTime should not include Z/offset - keep dateTime and timeZone separate
|
|
61
|
+
const startDateTimeISO = startDateTime.toISOString().replace('Z', '');
|
|
62
|
+
const endDateTimeISO = endDateTime.toISOString().replace('Z', '');
|
|
63
|
+
|
|
64
|
+
const attendeesList: AttendeeBase[] = options.attendees
|
|
65
|
+
? options.attendees.split(',').map((email) => ({
|
|
66
|
+
type: 'required' as const,
|
|
67
|
+
emailAddress: {
|
|
68
|
+
address: email.trim()
|
|
69
|
+
}
|
|
70
|
+
}))
|
|
71
|
+
: [];
|
|
72
|
+
|
|
73
|
+
const request: FindMeetingTimesRequest = {
|
|
74
|
+
attendees: attendeesList.length > 0 ? attendeesList : undefined,
|
|
75
|
+
meetingDuration: durationStr,
|
|
76
|
+
timeConstraint: {
|
|
77
|
+
activityDomain: 'work',
|
|
78
|
+
timeSlots: [
|
|
79
|
+
{
|
|
80
|
+
start: {
|
|
81
|
+
dateTime: startDateTimeISO,
|
|
82
|
+
timeZone: 'UTC'
|
|
83
|
+
},
|
|
84
|
+
end: {
|
|
85
|
+
dateTime: endDateTimeISO,
|
|
86
|
+
timeZone: 'UTC'
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
isOrganizerOptional: false,
|
|
92
|
+
returnSuggestionReasons: true,
|
|
93
|
+
minimumAttendeePercentage: 100
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const result = await findMeetingTimes(authResult.token, request, options.user);
|
|
97
|
+
|
|
98
|
+
if (!result.ok || !result.data) {
|
|
99
|
+
if (options.json) {
|
|
100
|
+
console.log(JSON.stringify({ error: result.error }, null, 2));
|
|
101
|
+
} else {
|
|
102
|
+
console.error('Error finding meeting times:', result.error?.message || 'Unknown error');
|
|
103
|
+
}
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (options.json) {
|
|
108
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const { emptySuggestionsReason, meetingTimeSuggestions } = result.data;
|
|
113
|
+
|
|
114
|
+
console.log('\nAI Meeting Time Suggestions:\n');
|
|
115
|
+
|
|
116
|
+
if (emptySuggestionsReason) {
|
|
117
|
+
console.log('No suitable meeting times found for the following reason:');
|
|
118
|
+
console.log(` - ${emptySuggestionsReason}`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!meetingTimeSuggestions || meetingTimeSuggestions.length === 0) {
|
|
123
|
+
console.log('No suggestions found.');
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const suggestion of meetingTimeSuggestions) {
|
|
128
|
+
const start = suggestion.meetingTimeSlot?.start?.dateTime
|
|
129
|
+
? new Date(`${suggestion.meetingTimeSlot.start.dateTime}Z`).toLocaleString()
|
|
130
|
+
: 'Unknown';
|
|
131
|
+
const end = suggestion.meetingTimeSlot?.end?.dateTime
|
|
132
|
+
? new Date(`${suggestion.meetingTimeSlot.end.dateTime}Z`).toLocaleString()
|
|
133
|
+
: 'Unknown';
|
|
134
|
+
|
|
135
|
+
const confidence = suggestion.confidence !== undefined ? `${suggestion.confidence}%` : 'Unknown';
|
|
136
|
+
|
|
137
|
+
console.log(`Suggestion: ${start} - ${end}`);
|
|
138
|
+
console.log(` Confidence: ${confidence}`);
|
|
139
|
+
|
|
140
|
+
if (suggestion.suggestionReason) {
|
|
141
|
+
console.log(` Reason: ${suggestion.suggestionReason}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (suggestion.attendeeAvailability && suggestion.attendeeAvailability.length > 0) {
|
|
145
|
+
console.log(' Attendee Availability:');
|
|
146
|
+
for (const attendee of suggestion.attendeeAvailability) {
|
|
147
|
+
const email = attendee.attendee?.emailAddress?.address || 'Unknown';
|
|
148
|
+
const status = attendee.availability || 'Unknown';
|
|
149
|
+
console.log(` - ${email}: ${status}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
console.log();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
);
|