teams-api 0.7.0 → 0.9.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 (59) hide show
  1. package/dist/actions/conversation-actions.d.ts +10 -0
  2. package/dist/actions/conversation-actions.d.ts.map +1 -0
  3. package/dist/actions/conversation-actions.js +168 -0
  4. package/dist/actions/conversation-actions.js.map +1 -0
  5. package/dist/actions/definitions.d.ts +5 -10
  6. package/dist/actions/definitions.d.ts.map +1 -1
  7. package/dist/actions/definitions.js +22 -813
  8. package/dist/actions/definitions.js.map +1 -1
  9. package/dist/actions/file-actions.d.ts +8 -0
  10. package/dist/actions/file-actions.d.ts.map +1 -0
  11. package/dist/actions/file-actions.js +124 -0
  12. package/dist/actions/file-actions.js.map +1 -0
  13. package/dist/actions/formatters.d.ts +1 -1
  14. package/dist/actions/formatters.d.ts.map +1 -1
  15. package/dist/actions/message-actions.d.ts +11 -0
  16. package/dist/actions/message-actions.d.ts.map +1 -0
  17. package/dist/actions/message-actions.js +453 -0
  18. package/dist/actions/message-actions.js.map +1 -0
  19. package/dist/actions/search-actions.d.ts +9 -0
  20. package/dist/actions/search-actions.d.ts.map +1 -0
  21. package/dist/actions/search-actions.js +148 -0
  22. package/dist/actions/search-actions.js.map +1 -0
  23. package/dist/actions/utility-actions.d.ts +10 -0
  24. package/dist/actions/utility-actions.d.ts.map +1 -0
  25. package/dist/actions/utility-actions.js +200 -0
  26. package/dist/actions/utility-actions.js.map +1 -0
  27. package/dist/api/attachments.d.ts +106 -0
  28. package/dist/api/attachments.d.ts.map +1 -0
  29. package/dist/api/attachments.js +341 -0
  30. package/dist/api/attachments.js.map +1 -0
  31. package/dist/api/chat-service.d.ts +1 -1
  32. package/dist/api/chat-service.d.ts.map +1 -1
  33. package/dist/api/chat-service.js +8 -1
  34. package/dist/api/chat-service.js.map +1 -1
  35. package/dist/auth/auto-login.d.ts.map +1 -1
  36. package/dist/auth/auto-login.js +4 -1
  37. package/dist/auth/auto-login.js.map +1 -1
  38. package/dist/auth/interactive.d.ts.map +1 -1
  39. package/dist/auth/interactive.js +3 -1
  40. package/dist/auth/interactive.js.map +1 -1
  41. package/dist/auth/token-capture.d.ts +3 -0
  42. package/dist/auth/token-capture.d.ts.map +1 -1
  43. package/dist/auth/token-capture.js +67 -0
  44. package/dist/auth/token-capture.js.map +1 -1
  45. package/dist/cli.js +16 -3
  46. package/dist/cli.js.map +1 -1
  47. package/dist/mcp-server.js +9 -0
  48. package/dist/mcp-server.js.map +1 -1
  49. package/dist/teams-client.d.ts +78 -4
  50. package/dist/teams-client.d.ts.map +1 -1
  51. package/dist/teams-client.js +153 -8
  52. package/dist/teams-client.js.map +1 -1
  53. package/dist/token-store.d.ts.map +1 -1
  54. package/dist/token-store.js +6 -0
  55. package/dist/token-store.js.map +1 -1
  56. package/dist/types.d.ts +75 -0
  57. package/dist/types.d.ts.map +1 -1
  58. package/dist/types.js.map +1 -1
  59. package/package.json +1 -1
@@ -1,810 +1,18 @@
1
1
  "use strict";
2
2
  /**
3
- * All action definitions for the Teams API.
3
+ * Action registry the single source of truth for all Teams API operations.
4
4
  *
5
- * This is the single source of truth for all operations. CLI commands,
6
- * MCP tools, and programmatic usage all derive from these definitions.
7
- *
8
- * Each action declares:
9
- * - name, title, description — shared help text and documentation
10
- * - parameters — typed parameter definitions with descriptions and defaults
11
- * - execute — the implementation, calling TeamsClient methods
12
- * - formatResult — human-readable output formatter (CLI without --json)
5
+ * CLI commands, MCP tools, and programmatic usage all derive from these
6
+ * definitions. Individual action definitions live in domain-specific files;
7
+ * this module assembles them into the canonical registry.
13
8
  */
14
9
  Object.defineProperty(exports, "__esModule", { value: true });
15
10
  exports.actions = void 0;
16
- const constants_js_1 = require("../constants.js");
17
- const formatters_js_1 = require("./formatters.js");
18
- const conversation_resolution_js_1 = require("./conversation-resolution.js");
19
- // ── Action definitions ───────────────────────────────────────────────
20
- const listConversations = {
21
- name: "list-conversations",
22
- title: "List Teams Conversations",
23
- description: "List conversations (chats, group chats, meetings, channels). " +
24
- "Returns conversation ID, topic, type, member count, and last message time.",
25
- parameters: [
26
- {
27
- name: "limit",
28
- type: "number",
29
- description: "Maximum number of conversations to return",
30
- required: false,
31
- default: 50,
32
- },
33
- ],
34
- execute: async (client, parameters) => {
35
- const limit = parameters.limit ?? 50;
36
- return client.listConversations({ pageSize: limit });
37
- },
38
- formatResult: (result) => {
39
- const conversations = result;
40
- const lines = [`\n${conversations.length} conversations:\n`];
41
- for (let i = 0; i < conversations.length; i++) {
42
- const conversation = conversations[i];
43
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
44
- const topic = conversation.topic || "(untitled 1:1 chat)";
45
- lines.push(` [${i}] ${conversation.threadType}: "${topic}" ` +
46
- `(members: ${conversation.memberCount ?? "?"}, last: ${lastMessage})`);
47
- }
48
- return lines.join("\n");
49
- },
50
- formatMarkdown: (result) => {
51
- const conversations = result;
52
- const lines = [`## Conversations (${conversations.length})`, ""];
53
- if (conversations.length === 0)
54
- return lines.join("\n");
55
- lines.push("| # | Topic | Type | Members | Last Message |");
56
- lines.push("|---|-------|------|---------|--------------|");
57
- for (let i = 0; i < conversations.length; i++) {
58
- const conversation = conversations[i];
59
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
60
- const topic = conversation.topic || "(untitled 1:1 chat)";
61
- lines.push(`| ${i} | ${topic} | ${conversation.threadType} | ${conversation.memberCount ?? "?"} | ${lastMessage} |`);
62
- }
63
- return lines.join("\n");
64
- },
65
- formatToon: (result) => {
66
- const conversations = result;
67
- const lines = [(0, formatters_js_1.toonHeader)("📋", `${conversations.length} Conversations`)];
68
- for (let i = 0; i < conversations.length; i++) {
69
- const conversation = conversations[i];
70
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
71
- const topic = conversation.topic || "(untitled 1:1 chat)";
72
- lines.push("");
73
- lines.push(` 💬 [${i}] "${topic}"`);
74
- lines.push(` ${conversation.threadType} · ${conversation.memberCount ?? "?"} members · last: ${lastMessage}`);
75
- }
76
- return lines.join("\n");
77
- },
78
- };
79
- const findConversation = {
80
- name: "find-conversation",
81
- title: "Find Teams Conversation",
82
- description: "Find a conversation by topic name (case-insensitive partial match). " +
83
- "When Substrate search is available, also matches by member names. " +
84
- "For 1:1 chats (which have no topic), use find-one-on-one instead. " +
85
- "Use the returned conversation ID for subsequent operations like get-messages or send-message.",
86
- parameters: [
87
- {
88
- name: "query",
89
- type: "string",
90
- description: "Partial topic name to search for",
91
- required: true,
92
- },
93
- ],
94
- execute: async (client, parameters) => {
95
- const query = parameters.query;
96
- return client.findConversation(query);
97
- },
98
- formatResult: (result) => {
99
- if (!result)
100
- return "No conversation found.";
101
- const conversation = result;
102
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
103
- return (`Found: "${conversation.topic}" ` +
104
- `(${conversation.id}, ${conversation.threadType}, ` +
105
- `members: ${conversation.memberCount ?? "?"}, last: ${lastMessage})`);
106
- },
107
- formatMarkdown: (result) => {
108
- if (!result)
109
- return "No conversation found.";
110
- const conversation = result;
111
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
112
- return [
113
- `## Found: "${conversation.topic}"`,
114
- "",
115
- `- **ID:** ${conversation.id}`,
116
- `- **Type:** ${conversation.threadType}`,
117
- `- **Members:** ${conversation.memberCount ?? "?"}`,
118
- `- **Last message:** ${lastMessage}`,
119
- ].join("\n");
120
- },
121
- formatToon: (result) => {
122
- if (!result)
123
- return "\n 🔍 No conversation found.";
124
- const conversation = result;
125
- const lastMessage = conversation.lastMessageTime?.slice(0, 10) ?? "unknown";
126
- return [
127
- (0, formatters_js_1.toonHeader)("🔍", `Found: "${conversation.topic}"`),
128
- ` 🆔 ${conversation.id}`,
129
- ` 📁 ${conversation.threadType} · ${conversation.memberCount ?? "?"} members · last: ${lastMessage}`,
130
- ].join("\n");
131
- },
132
- };
133
- const findOneOnOne = {
134
- name: "find-one-on-one",
135
- title: "Find 1:1 Conversation",
136
- description: "Find a 1:1 conversation with a person by name. " +
137
- "Uses Substrate people/chat search when available, " +
138
- "falls back to scanning message senders. " +
139
- "Also finds the self-chat if the name matches the current user.",
140
- parameters: [
141
- {
142
- name: "personName",
143
- type: "string",
144
- description: "Name of the person to find (case-insensitive partial match)",
145
- required: true,
146
- },
147
- ],
148
- execute: async (client, parameters) => {
149
- const personName = parameters.personName;
150
- return client.findOneOnOneConversation(personName);
151
- },
152
- formatResult: (result) => {
153
- if (!result)
154
- return "No 1:1 conversation found.";
155
- const searchResult = result;
156
- return `Found 1:1 with ${searchResult.memberDisplayName} (${searchResult.conversationId})`;
157
- },
158
- formatMarkdown: (result) => {
159
- if (!result)
160
- return "No 1:1 conversation found.";
161
- const searchResult = result;
162
- return [
163
- `## Found 1:1 with ${searchResult.memberDisplayName}`,
164
- "",
165
- `- **Conversation ID:** ${searchResult.conversationId}`,
166
- ].join("\n");
167
- },
168
- formatToon: (result) => {
169
- if (!result)
170
- return "\n 🔍 No 1:1 conversation found.";
171
- const searchResult = result;
172
- return [
173
- (0, formatters_js_1.toonHeader)("🔍", `Found 1:1 with ${searchResult.memberDisplayName}`),
174
- ` 🆔 ${searchResult.conversationId}`,
175
- ].join("\n");
176
- },
177
- };
178
- const getMessages = {
179
- name: "get-messages",
180
- title: "Get Messages",
181
- description: "Get messages from a conversation. " +
182
- "Identify the conversation by topic name (--chat), " +
183
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
184
- "At least one identifier is required. " +
185
- "Messages include reactions, mentions, followers (thread subscribers), and quoted message references.",
186
- parameters: [
187
- ...conversation_resolution_js_1.conversationParameters,
188
- {
189
- name: "limit",
190
- type: "number",
191
- description: "Maximum number of messages to return. " +
192
- "Omit to fetch the entire conversation history.",
193
- required: false,
194
- },
195
- {
196
- name: "textOnly",
197
- type: "boolean",
198
- description: "Only return text messages, excluding system events (default: true)",
199
- required: false,
200
- default: true,
201
- },
202
- {
203
- name: "order",
204
- type: "string",
205
- description: "Message order: oldest-first (chronological, default) or newest-first",
206
- required: false,
207
- default: "oldest-first",
208
- },
209
- ],
210
- execute: async (client, parameters) => {
211
- const { conversationId } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
212
- const limit = parameters.limit;
213
- const textOnly = parameters.textOnly ?? true;
214
- const onProgress = parameters.onProgress;
215
- let messages = await client.getMessages(conversationId, {
216
- limit,
217
- onProgress,
218
- });
219
- if (textOnly) {
220
- messages = messages.filter((message) => (0, constants_js_1.isTextMessageType)(message.messageType) && !message.isDeleted);
221
- }
222
- const order = parameters.order ?? "oldest-first";
223
- if (order === "oldest-first") {
224
- messages = [...messages].reverse();
225
- }
226
- return messages;
227
- },
228
- formatResult: (result) => {
229
- const messages = result;
230
- const senderLookup = (0, formatters_js_1.buildSenderLookup)(messages);
231
- const lines = [`\n${messages.length} messages:\n`];
232
- for (const message of messages) {
233
- const time = message.originalArrivalTime.slice(0, 19).replace("T", " ");
234
- const sender = message.senderDisplayName || "(system)";
235
- const { quote, body } = (0, formatters_js_1.extractQuote)(message.content);
236
- if (quote && message.quotedMessageId) {
237
- const quotedSender = senderLookup.get(message.quotedMessageId) ?? "unknown";
238
- lines.push(` [${time}] ${sender}:`);
239
- lines.push(` > [replying to ${quotedSender}]: ${quote.slice(0, 80)}`);
240
- lines.push(` ${body.slice(0, 120)}`);
241
- }
242
- else {
243
- lines.push(` [${time}] ${sender}: ${body.slice(0, 120)}`);
244
- }
245
- if (message.followers.length > 0) {
246
- lines.push(` [${message.followers.length} follower(s)]`);
247
- }
248
- }
249
- return lines.join("\n");
250
- },
251
- formatMarkdown: (result) => {
252
- const messages = result;
253
- const senderLookup = (0, formatters_js_1.buildSenderLookup)(messages);
254
- const lines = [`## Messages (${messages.length})`, ""];
255
- let previousSender = "";
256
- for (const message of messages) {
257
- const time = message.originalArrivalTime.slice(0, 19).replace("T", " ");
258
- const sender = message.senderDisplayName || "(system)";
259
- const { quote, body } = (0, formatters_js_1.extractQuote)(message.content);
260
- if (sender === previousSender) {
261
- lines.push(`*${time}*`, "");
262
- }
263
- else {
264
- lines.push(`### ${sender} — ${time}`, "");
265
- previousSender = sender;
266
- }
267
- if (quote && message.quotedMessageId) {
268
- const quotedSender = senderLookup.get(message.quotedMessageId) ?? "unknown";
269
- lines.push(`> **[replying to ${quotedSender}]:** ${quote}`, "");
270
- }
271
- lines.push(body, "");
272
- if (message.followers.length > 0) {
273
- lines.push(`*${message.followers.length} follower(s)*`, "");
274
- }
275
- }
276
- return lines.join("\n");
277
- },
278
- formatToon: (result) => {
279
- const messages = result;
280
- const senderLookup = (0, formatters_js_1.buildSenderLookup)(messages);
281
- const lines = [(0, formatters_js_1.toonHeader)("💬", `${messages.length} Messages`)];
282
- let previousSender = "";
283
- for (const message of messages) {
284
- const time = message.originalArrivalTime.slice(0, 19).replace("T", " ");
285
- const sender = message.senderDisplayName || "(system)";
286
- const { quote, body } = (0, formatters_js_1.extractQuote)(message.content);
287
- lines.push("");
288
- if (sender === previousSender) {
289
- lines.push(` ${time}`);
290
- }
291
- else {
292
- lines.push(` 🗣️ ${sender} · ${time}`);
293
- previousSender = sender;
294
- }
295
- if (quote && message.quotedMessageId) {
296
- const quotedSender = senderLookup.get(message.quotedMessageId) ?? "unknown";
297
- lines.push(` > [replying to ${quotedSender}]: ${quote.slice(0, 80)}`);
298
- }
299
- lines.push(` ${body.slice(0, 120)}`);
300
- if (message.followers.length > 0) {
301
- lines.push(` 👥 ${message.followers.length} follower(s)`);
302
- }
303
- }
304
- return lines.join("\n");
305
- },
306
- };
307
- const sendMessage = {
308
- name: "send-message",
309
- title: "Send Message",
310
- description: "Send a message to a conversation. " +
311
- "Identify the conversation by topic name (--chat), " +
312
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
313
- "At least one identifier is required. " +
314
- "Content is interpreted as Markdown by default and converted to rich HTML.",
315
- parameters: [
316
- ...conversation_resolution_js_1.conversationParameters,
317
- {
318
- name: "content",
319
- type: "string",
320
- description: "Message content to send",
321
- required: true,
322
- },
323
- {
324
- name: "messageFormat",
325
- type: "string",
326
- description: 'Content format: "markdown" (default, converted to HTML), "html" (raw HTML), or "text" (plain text)',
327
- required: false,
328
- default: "markdown",
329
- },
330
- ],
331
- execute: async (client, parameters) => {
332
- const { conversationId, label } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
333
- const content = parameters.content;
334
- const messageFormat = parameters.messageFormat ?? "markdown";
335
- const result = await client.sendMessage(conversationId, content, messageFormat);
336
- return { ...result, conversation: label };
337
- },
338
- formatResult: (result) => {
339
- const { messageId, arrivalTime, conversation } = result;
340
- return [
341
- `Message sent to "${conversation}"`,
342
- ` Message ID: ${messageId}`,
343
- ` Arrival time: ${arrivalTime}`,
344
- ].join("\n");
345
- },
346
- formatMarkdown: (result) => {
347
- const { messageId, arrivalTime, conversation } = result;
348
- return [
349
- "## Message Sent",
350
- "",
351
- `- **To:** ${conversation}`,
352
- `- **Message ID:** ${messageId}`,
353
- `- **Arrival time:** ${arrivalTime}`,
354
- ].join("\n");
355
- },
356
- formatToon: (result) => {
357
- const { messageId, arrivalTime, conversation } = result;
358
- return [
359
- (0, formatters_js_1.toonHeader)("✅", "Message Sent!"),
360
- ` 📨 To: "${conversation}"`,
361
- ` 🆔 ${messageId}`,
362
- ` ⏰ ${arrivalTime}`,
363
- ].join("\n");
364
- },
365
- };
366
- const editMessageAction = {
367
- name: "edit-message",
368
- title: "Edit Message",
369
- description: "Edit an existing message in a conversation. " +
370
- "Identify the conversation by topic name (--chat), " +
371
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
372
- "At least one identifier is required. " +
373
- "The message to edit is identified by --message-id. " +
374
- "Content is interpreted as Markdown by default and converted to rich HTML.",
375
- parameters: [
376
- ...conversation_resolution_js_1.conversationParameters,
377
- {
378
- name: "messageId",
379
- type: "string",
380
- description: "ID of the message to edit",
381
- required: true,
382
- },
383
- {
384
- name: "content",
385
- type: "string",
386
- description: "New message content",
387
- required: true,
388
- },
389
- {
390
- name: "messageFormat",
391
- type: "string",
392
- description: 'Content format: "markdown" (default, converted to HTML), "html" (raw HTML), or "text" (plain text)',
393
- required: false,
394
- default: "markdown",
395
- },
396
- ],
397
- execute: async (client, parameters) => {
398
- const { conversationId, label } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
399
- const messageId = parameters.messageId;
400
- const content = parameters.content;
401
- const messageFormat = parameters.messageFormat ?? "markdown";
402
- const result = await client.editMessage(conversationId, messageId, content, messageFormat);
403
- return { ...result, conversation: label };
404
- },
405
- formatResult: (result) => {
406
- const { messageId, editTime, conversation } = result;
407
- return [
408
- `Message edited in "${conversation}"`,
409
- ` Message ID: ${messageId}`,
410
- ` Edit time: ${editTime}`,
411
- ].join("\n");
412
- },
413
- formatMarkdown: (result) => {
414
- const { messageId, editTime, conversation } = result;
415
- return [
416
- "## Message Edited",
417
- "",
418
- `- **In:** ${conversation}`,
419
- `- **Message ID:** ${messageId}`,
420
- `- **Edit time:** ${editTime}`,
421
- ].join("\n");
422
- },
423
- formatToon: (result) => {
424
- const { messageId, editTime, conversation } = result;
425
- return [
426
- (0, formatters_js_1.toonHeader)("✏️", "Message Edited!"),
427
- ` 💬 In: "${conversation}"`,
428
- ` 🆔 ${messageId}`,
429
- ` ⏰ ${editTime}`,
430
- ].join("\n");
431
- },
432
- };
433
- const deleteMessageAction = {
434
- name: "delete-message",
435
- title: "Delete Message",
436
- description: "Delete a message from a conversation. " +
437
- "Identify the conversation by topic name (--chat), " +
438
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
439
- "At least one identifier is required. " +
440
- "The message to delete is identified by --message-id.",
441
- parameters: [
442
- ...conversation_resolution_js_1.conversationParameters,
443
- {
444
- name: "messageId",
445
- type: "string",
446
- description: "ID of the message to delete",
447
- required: true,
448
- },
449
- ],
450
- execute: async (client, parameters) => {
451
- const { conversationId, label } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
452
- const messageId = parameters.messageId;
453
- const result = await client.deleteMessage(conversationId, messageId);
454
- return { ...result, conversation: label };
455
- },
456
- formatResult: (result) => {
457
- const { messageId, conversation } = result;
458
- return [
459
- `Message deleted from "${conversation}"`,
460
- ` Message ID: ${messageId}`,
461
- ].join("\n");
462
- },
463
- formatMarkdown: (result) => {
464
- const { messageId, conversation } = result;
465
- return [
466
- "## Message Deleted",
467
- "",
468
- `- **From:** ${conversation}`,
469
- `- **Message ID:** ${messageId}`,
470
- ].join("\n");
471
- },
472
- formatToon: (result) => {
473
- const { messageId, conversation } = result;
474
- return [
475
- (0, formatters_js_1.toonHeader)("🗑️", "Message Deleted!"),
476
- ` 💬 From: "${conversation}"`,
477
- ` 🆔 ${messageId}`,
478
- ].join("\n");
479
- },
480
- };
481
- const getMembers = {
482
- name: "get-members",
483
- title: "Get Conversation Members",
484
- description: "List members of a conversation. " +
485
- "Identify the conversation by topic name (--chat), " +
486
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
487
- "At least one identifier is required. " +
488
- "Display names are resolved via the Teams profile API when available, with message history as fallback. " +
489
- "Note: 1:1 chat members may have empty display names if profile resolution is unavailable.",
490
- parameters: [...conversation_resolution_js_1.conversationParameters],
491
- execute: async (client, parameters) => {
492
- const { conversationId } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
493
- return client.getMembers(conversationId);
494
- },
495
- formatResult: (result) => {
496
- const members = result;
497
- const people = members.filter((member) => member.memberType === "person");
498
- const bots = members.filter((member) => member.memberType === "bot");
499
- const lines = [`\n${people.length} people, ${bots.length} bots:\n`];
500
- for (const member of people) {
501
- const name = member.displayName || "(unknown)";
502
- lines.push(` ${name} (${member.role}) — ${member.id}`);
503
- }
504
- if (bots.length > 0) {
505
- lines.push("");
506
- lines.push(" Bots/Apps:");
507
- for (const bot of bots) {
508
- const name = bot.displayName || "(unnamed bot)";
509
- lines.push(` ${name} — ${bot.id}`);
510
- }
511
- }
512
- return lines.join("\n");
513
- },
514
- formatMarkdown: (result) => {
515
- const members = result;
516
- const people = members.filter((member) => member.memberType === "person");
517
- const bots = members.filter((member) => member.memberType === "bot");
518
- const lines = [
519
- `## Members (${people.length} people, ${bots.length} bots)`,
520
- "",
521
- ];
522
- if (people.length > 0) {
523
- lines.push("| Name | Role | ID |");
524
- lines.push("|------|------|----|");
525
- for (const member of people) {
526
- const name = member.displayName || "(unknown)";
527
- lines.push(`| ${name} | ${member.role} | ${member.id} |`);
528
- }
529
- }
530
- if (bots.length > 0) {
531
- lines.push("", "### Bots/Apps", "");
532
- lines.push("| Name | ID |");
533
- lines.push("|------|----|");
534
- for (const bot of bots) {
535
- const name = bot.displayName || "(unnamed bot)";
536
- lines.push(`| ${name} | ${bot.id} |`);
537
- }
538
- }
539
- return lines.join("\n");
540
- },
541
- formatToon: (result) => {
542
- const members = result;
543
- const people = members.filter((member) => member.memberType === "person");
544
- const bots = members.filter((member) => member.memberType === "bot");
545
- const lines = [
546
- (0, formatters_js_1.toonHeader)("👥", `${people.length} People, ${bots.length} Bots`),
547
- ];
548
- for (const member of people) {
549
- const name = member.displayName || "(unknown)";
550
- lines.push("");
551
- lines.push(` 👤 ${name} · ${member.role}`);
552
- lines.push(` ${member.id}`);
553
- }
554
- if (bots.length > 0) {
555
- lines.push("");
556
- lines.push(" 🤖 Bots/Apps:");
557
- for (const bot of bots) {
558
- const name = bot.displayName || "(unnamed bot)";
559
- lines.push(` 🤖 ${name} — ${bot.id}`);
560
- }
561
- }
562
- return lines.join("\n");
563
- },
564
- };
565
- const whoami = {
566
- name: "whoami",
567
- title: "Current User Info",
568
- description: "Get the display name and region of the currently authenticated user.",
569
- parameters: [],
570
- execute: async (client) => {
571
- const displayName = await client.getCurrentUserDisplayName();
572
- const token = client.getToken();
573
- return { displayName, region: token.region };
574
- },
575
- formatResult: (result) => {
576
- const { displayName, region } = result;
577
- return `${displayName} (region: ${region})`;
578
- },
579
- formatMarkdown: (result) => {
580
- const { displayName, region } = result;
581
- return [`## ${displayName}`, "", `- **Region:** ${region}`].join("\n");
582
- },
583
- formatToon: (result) => {
584
- const { displayName, region } = result;
585
- return [(0, formatters_js_1.toonHeader)("🙋", displayName), ` 📍 region: ${region}`].join("\n");
586
- },
587
- };
588
- const getTranscript = {
589
- name: "get-transcript",
590
- title: "Get Meeting Transcript",
591
- description: "Get the meeting transcript from a conversation that contains a recorded meeting. " +
592
- "Identify the conversation by topic name (--chat), " +
593
- "person name for 1:1 chats (--to), or direct ID (--conversation-id). " +
594
- "Use --raw-vtt to get the original VTT file instead of parsed output.",
595
- parameters: [
596
- ...conversation_resolution_js_1.conversationParameters,
597
- {
598
- name: "rawVtt",
599
- type: "boolean",
600
- description: "Return the original VTT file content instead of parsed transcript (default: false)",
601
- required: false,
602
- default: false,
603
- },
604
- ],
605
- execute: async (client, parameters) => {
606
- const { conversationId } = await (0, conversation_resolution_js_1.resolveConversationId)(client, parameters);
607
- const rawVtt = parameters.rawVtt ?? false;
608
- const transcriptResult = await client.getTranscript(conversationId);
609
- if (rawVtt) {
610
- return { rawVtt: transcriptResult.rawVtt, format: "vtt" };
611
- }
612
- return transcriptResult;
613
- },
614
- formatResult: (result) => {
615
- const data = result;
616
- if ("format" in data && data.format === "vtt") {
617
- return data.rawVtt;
618
- }
619
- const transcript = data;
620
- const groups = (0, formatters_js_1.groupBySpeaker)(transcript.entries);
621
- const lines = [
622
- `\nTranscript: ${transcript.meetingTitle} (${transcript.entries.length} segments)\n`,
623
- ];
624
- for (const group of groups) {
625
- const time = (0, formatters_js_1.formatTimestamp)(group.startTime);
626
- lines.push(` [${time}] ${group.speaker}:`);
627
- lines.push(` ${group.segments.join(" ")}`);
628
- }
629
- return lines.join("\n");
630
- },
631
- formatMarkdown: (result) => {
632
- const data = result;
633
- if ("format" in data && data.format === "vtt") {
634
- return ["```vtt", data.rawVtt, "```"].join("\n");
635
- }
636
- const transcript = data;
637
- const groups = (0, formatters_js_1.groupBySpeaker)(transcript.entries);
638
- const lines = [
639
- `## Transcript: ${transcript.meetingTitle}`,
640
- "",
641
- `*${transcript.entries.length} segments*`,
642
- "",
643
- ];
644
- for (const group of groups) {
645
- const time = (0, formatters_js_1.formatTimestamp)(group.startTime);
646
- lines.push(`**${group.speaker}** *(${time})*`, "");
647
- lines.push(group.segments.join(" "), "");
648
- }
649
- return lines.join("\n");
650
- },
651
- formatToon: (result) => {
652
- const data = result;
653
- if ("format" in data && data.format === "vtt") {
654
- return data.rawVtt;
655
- }
656
- const transcript = data;
657
- const groups = (0, formatters_js_1.groupBySpeaker)(transcript.entries);
658
- const lines = [
659
- (0, formatters_js_1.toonHeader)("🎙️", `Transcript: ${transcript.meetingTitle} (${transcript.entries.length} segments)`),
660
- ];
661
- for (const group of groups) {
662
- const time = (0, formatters_js_1.formatTimestamp)(group.startTime);
663
- lines.push("");
664
- lines.push(` 🗣️ ${group.speaker} · ${time}`);
665
- lines.push(` ${group.segments.join(" ")}`);
666
- }
667
- return lines.join("\n");
668
- },
669
- };
670
- const findPeopleAction = {
671
- name: "find-people",
672
- title: "Find People",
673
- description: "Search for people in the organization directory by name. " +
674
- "Uses the Substrate search API (requires authentication via auto-login or interactive). " +
675
- "Returns matching people with emails, job titles, and departments.",
676
- parameters: [
677
- {
678
- name: "query",
679
- type: "string",
680
- description: "Name or partial name to search for",
681
- required: true,
682
- },
683
- {
684
- name: "maxResults",
685
- type: "number",
686
- description: "Maximum results to return (default: 10)",
687
- required: false,
688
- default: 10,
689
- },
690
- ],
691
- execute: async (client, parameters) => {
692
- const query = parameters.query;
693
- const maxResults = parameters.maxResults ?? 10;
694
- return client.findPeople(query, maxResults);
695
- },
696
- formatResult: (result) => {
697
- const people = result;
698
- if (people.length === 0)
699
- return "No people found.";
700
- return people
701
- .map((person) => `${person.displayName} <${person.email}> — ${person.jobTitle || "no title"}, ${person.department || "no department"}`)
702
- .join("\n");
703
- },
704
- formatMarkdown: (result) => {
705
- const people = result;
706
- if (people.length === 0)
707
- return "No people found.";
708
- const lines = [`## People (${people.length} found)`, ""];
709
- for (const person of people) {
710
- lines.push(`### ${person.displayName}`);
711
- lines.push(`- **Email:** ${person.email}`);
712
- if (person.jobTitle)
713
- lines.push(`- **Title:** ${person.jobTitle}`);
714
- if (person.department)
715
- lines.push(`- **Department:** ${person.department}`);
716
- lines.push(`- **MRI:** ${person.mri}`);
717
- lines.push("");
718
- }
719
- return lines.join("\n");
720
- },
721
- formatToon: (result) => {
722
- const people = result;
723
- if (people.length === 0)
724
- return "\n 🔍 No people found.";
725
- const lines = [(0, formatters_js_1.toonHeader)("👥", `Found ${people.length} people`)];
726
- for (const person of people) {
727
- lines.push(` 👤 ${person.displayName}`);
728
- lines.push(` 📧 ${person.email} · ${person.jobTitle || "?"} · ${person.department || "?"}`);
729
- }
730
- return lines.join("\n");
731
- },
732
- };
733
- const findChatsAction = {
734
- name: "find-chats",
735
- title: "Find Chats",
736
- description: "Search for chats by name or member name. " +
737
- "Uses the Substrate search API (requires authentication via auto-login or interactive). " +
738
- "Returns matching chats with member lists and thread IDs.",
739
- parameters: [
740
- {
741
- name: "query",
742
- type: "string",
743
- description: "Chat name or member name to search for",
744
- required: true,
745
- },
746
- {
747
- name: "maxResults",
748
- type: "number",
749
- description: "Maximum results to return (default: 10)",
750
- required: false,
751
- default: 10,
752
- },
753
- ],
754
- execute: async (client, parameters) => {
755
- const query = parameters.query;
756
- const maxResults = parameters.maxResults ?? 10;
757
- return client.findChats(query, maxResults);
758
- },
759
- formatResult: (result) => {
760
- const chats = result;
761
- if (chats.length === 0)
762
- return "No chats found.";
763
- return chats
764
- .map((chat) => {
765
- const name = chat.name || "(untitled)";
766
- const members = chat.matchingMembers
767
- .map((member) => member.displayName)
768
- .join(", ");
769
- return `${name} (${chat.threadType}, ${chat.totalMemberCount} members${members ? `, matched: ${members}` : ""}) — ${chat.threadId}`;
770
- })
771
- .join("\n");
772
- },
773
- formatMarkdown: (result) => {
774
- const chats = result;
775
- if (chats.length === 0)
776
- return "No chats found.";
777
- const lines = [`## Chats (${chats.length} found)`, ""];
778
- for (const chat of chats) {
779
- lines.push(`### ${chat.name || "(untitled)"}`);
780
- lines.push(`- **Thread ID:** ${chat.threadId}`);
781
- lines.push(`- **Type:** ${chat.threadType}`);
782
- lines.push(`- **Members:** ${chat.totalMemberCount}`);
783
- if (chat.matchingMembers.length > 0) {
784
- lines.push(`- **Matched:** ${chat.matchingMembers.map((member) => member.displayName).join(", ")}`);
785
- }
786
- lines.push("");
787
- }
788
- return lines.join("\n");
789
- },
790
- formatToon: (result) => {
791
- const chats = result;
792
- if (chats.length === 0)
793
- return "\n 🔍 No chats found.";
794
- const lines = [(0, formatters_js_1.toonHeader)("💬", `Found ${chats.length} chats`)];
795
- for (const chat of chats) {
796
- lines.push(` 💬 ${chat.name || "(untitled)"}`);
797
- lines.push(` 📁 ${chat.threadType} · ${chat.totalMemberCount} members`);
798
- if (chat.matchingMembers.length > 0) {
799
- const matched = chat.matchingMembers
800
- .map((member) => member.displayName)
801
- .join(", ");
802
- lines.push(` 🎯 Matched: ${matched}`);
803
- }
804
- }
805
- return lines.join("\n");
806
- },
807
- };
11
+ const conversation_actions_js_1 = require("./conversation-actions.js");
12
+ const message_actions_js_1 = require("./message-actions.js");
13
+ const search_actions_js_1 = require("./search-actions.js");
14
+ const utility_actions_js_1 = require("./utility-actions.js");
15
+ const file_actions_js_1 = require("./file-actions.js");
808
16
  // ── Registry ─────────────────────────────────────────────────────────
809
17
  /**
810
18
  * Map-based action registry keyed by action name.
@@ -812,18 +20,19 @@ const findChatsAction = {
812
20
  * accidental omissions from the exported array.
813
21
  */
814
22
  const actionRegistry = new Map([
815
- ["list-conversations", listConversations],
816
- ["find-conversation", findConversation],
817
- ["find-one-on-one", findOneOnOne],
818
- ["find-people", findPeopleAction],
819
- ["find-chats", findChatsAction],
820
- ["get-messages", getMessages],
821
- ["send-message", sendMessage],
822
- ["edit-message", editMessageAction],
823
- ["delete-message", deleteMessageAction],
824
- ["get-members", getMembers],
825
- ["whoami", whoami],
826
- ["get-transcript", getTranscript],
23
+ ["list-conversations", conversation_actions_js_1.listConversations],
24
+ ["find-conversation", conversation_actions_js_1.findConversation],
25
+ ["find-one-on-one", conversation_actions_js_1.findOneOnOne],
26
+ ["find-people", search_actions_js_1.findPeopleAction],
27
+ ["find-chats", search_actions_js_1.findChatsAction],
28
+ ["get-messages", message_actions_js_1.getMessages],
29
+ ["send-message", message_actions_js_1.sendMessage],
30
+ ["edit-message", message_actions_js_1.editMessageAction],
31
+ ["delete-message", message_actions_js_1.deleteMessageAction],
32
+ ["get-members", utility_actions_js_1.getMembers],
33
+ ["whoami", utility_actions_js_1.whoami],
34
+ ["get-transcript", utility_actions_js_1.getTranscript],
35
+ ["download-file", file_actions_js_1.downloadFileAction],
827
36
  ]);
828
37
  /** All registered actions, derived from the registry map. */
829
38
  exports.actions = Array.from(actionRegistry.values());