teams-api 0.5.2 → 0.6.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 (83) hide show
  1. package/SKILL.md +1 -1
  2. package/dist/actions/conversation-resolution.d.ts +26 -0
  3. package/dist/actions/conversation-resolution.d.ts.map +1 -0
  4. package/dist/actions/conversation-resolution.js +81 -0
  5. package/dist/actions/conversation-resolution.js.map +1 -0
  6. package/dist/actions/definitions.d.ts +16 -0
  7. package/dist/actions/definitions.d.ts.map +1 -0
  8. package/dist/{actions.js → actions/definitions.js} +77 -209
  9. package/dist/actions/definitions.js.map +1 -0
  10. package/dist/{actions.d.ts → actions/formatters.d.ts} +24 -13
  11. package/dist/actions/formatters.d.ts.map +1 -0
  12. package/dist/actions/formatters.js +86 -0
  13. package/dist/actions/formatters.js.map +1 -0
  14. package/dist/api/chat-service.d.ts +54 -0
  15. package/dist/api/chat-service.d.ts.map +1 -0
  16. package/dist/api/chat-service.js +327 -0
  17. package/dist/api/chat-service.js.map +1 -0
  18. package/dist/api/common.d.ts +21 -0
  19. package/dist/api/common.d.ts.map +1 -0
  20. package/dist/api/common.js +65 -0
  21. package/dist/api/common.js.map +1 -0
  22. package/dist/api/middle-tier.d.ts +15 -0
  23. package/dist/api/middle-tier.d.ts.map +1 -0
  24. package/dist/api/middle-tier.js +52 -0
  25. package/dist/api/middle-tier.js.map +1 -0
  26. package/dist/api/substrate.d.ts +22 -0
  27. package/dist/api/substrate.d.ts.map +1 -0
  28. package/dist/api/substrate.js +162 -0
  29. package/dist/api/substrate.js.map +1 -0
  30. package/dist/api/transcripts.d.ts +51 -0
  31. package/dist/api/transcripts.d.ts.map +1 -0
  32. package/dist/api/transcripts.js +140 -0
  33. package/dist/api/transcripts.js.map +1 -0
  34. package/dist/auth/auto-login.d.ts +23 -0
  35. package/dist/auth/auto-login.d.ts.map +1 -0
  36. package/dist/auth/auto-login.js +136 -0
  37. package/dist/auth/auto-login.js.map +1 -0
  38. package/dist/auth/debug-session.d.ts +20 -0
  39. package/dist/auth/debug-session.d.ts.map +1 -0
  40. package/dist/auth/debug-session.js +121 -0
  41. package/dist/auth/debug-session.js.map +1 -0
  42. package/dist/auth/interactive.d.ts +21 -0
  43. package/dist/auth/interactive.d.ts.map +1 -0
  44. package/dist/auth/interactive.js +90 -0
  45. package/dist/auth/interactive.js.map +1 -0
  46. package/dist/auth/page-diagnostics.d.ts +21 -0
  47. package/dist/auth/page-diagnostics.d.ts.map +1 -0
  48. package/dist/auth/page-diagnostics.js +65 -0
  49. package/dist/auth/page-diagnostics.js.map +1 -0
  50. package/dist/auth/token-capture.d.ts +24 -0
  51. package/dist/auth/token-capture.d.ts.map +1 -0
  52. package/dist/auth/token-capture.js +123 -0
  53. package/dist/auth/token-capture.js.map +1 -0
  54. package/dist/cli.js +11 -5
  55. package/dist/cli.js.map +1 -1
  56. package/dist/constants.d.ts +9 -0
  57. package/dist/constants.d.ts.map +1 -0
  58. package/dist/constants.js +14 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/html-utils.d.ts +9 -0
  61. package/dist/html-utils.d.ts.map +1 -0
  62. package/dist/html-utils.js +21 -0
  63. package/dist/html-utils.js.map +1 -0
  64. package/dist/mcp-server.js +4 -3
  65. package/dist/mcp-server.js.map +1 -1
  66. package/dist/teams-client.d.ts +17 -8
  67. package/dist/teams-client.d.ts.map +1 -1
  68. package/dist/teams-client.js +90 -75
  69. package/dist/teams-client.js.map +1 -1
  70. package/dist/types.d.ts +20 -1
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js.map +1 -1
  73. package/package.json +1 -1
  74. package/dist/actions.d.ts.map +0 -1
  75. package/dist/actions.js.map +0 -1
  76. package/dist/api.d.ts +0 -126
  77. package/dist/api.d.ts.map +0 -1
  78. package/dist/api.js +0 -702
  79. package/dist/api.js.map +0 -1
  80. package/dist/auth.d.ts +0 -53
  81. package/dist/auth.d.ts.map +0 -1
  82. package/dist/auth.js +0 -491
  83. package/dist/auth.js.map +0 -1
@@ -1,16 +1,10 @@
1
1
  /**
2
- * Unified action definitions for the Teams API.
2
+ * Shared formatting utilities for action output.
3
3
  *
4
- * This is the single source of truth for all operations. CLI commands,
5
- * MCP tools, and programmatic usage all derive from these definitions.
6
- *
7
- * Each action declares:
8
- * - name, title, description — shared help text and documentation
9
- * - parameters — typed parameter definitions with descriptions and defaults
10
- * - execute — the implementation, calling TeamsClient methods
11
- * - formatResult — human-readable output formatter (CLI without --json)
4
+ * Contains HTML cleaning, quote extraction, message formatting helpers,
5
+ * transcript grouping, and output format dispatch.
12
6
  */
13
- import type { TeamsClient } from "./teams-client.js";
7
+ import type { Message, TranscriptEntry } from "../types.js";
14
8
  export interface ActionParameter {
15
9
  /** Parameter name in camelCase (CLI flags auto-converted to kebab-case). */
16
10
  name: string;
@@ -33,7 +27,7 @@ export interface ActionDefinition {
33
27
  /** Typed parameter definitions. */
34
28
  parameters: ActionParameter[];
35
29
  /** Execute the action against a TeamsClient. */
36
- execute: (client: TeamsClient, parameters: Record<string, unknown>) => Promise<unknown>;
30
+ execute: (client: import("../teams-client.js").TeamsClient, parameters: Record<string, unknown>) => Promise<unknown>;
37
31
  /** Format result as human-readable text (CLI output without --json). */
38
32
  formatResult: (result: unknown) => string;
39
33
  /** Format result as Markdown. */
@@ -45,5 +39,22 @@ export type OutputFormat = "json" | "text" | "md" | "toon";
45
39
  export type MessageOrder = "newest-first" | "oldest-first";
46
40
  /** Format an action result in the specified output format. */
47
41
  export declare function formatOutput(action: ActionDefinition, result: unknown, format?: OutputFormat): string;
48
- export declare const actions: ActionDefinition[];
49
- //# sourceMappingURL=actions.d.ts.map
42
+ export declare function toonHeader(emoji: string, text: string): string;
43
+ /** Strip HTML tags and decode entities from message content. */
44
+ export declare function cleanContent(content: string): string;
45
+ /** Extract quoted text from HTML blockquotes, returning quote and body separately. */
46
+ export declare function extractQuote(content: string): {
47
+ quote: string | null;
48
+ body: string;
49
+ };
50
+ /** Build a map from message ID to sender display name. */
51
+ export declare function buildSenderLookup(messages: Message[]): Map<string, string>;
52
+ /** Format a VTT timestamp (HH:MM:SS.mmm) as a compact time string. */
53
+ export declare function formatTimestamp(timestamp: string): string;
54
+ /** Group consecutive entries by the same speaker for more readable output. */
55
+ export declare function groupBySpeaker(entries: TranscriptEntry[]): Array<{
56
+ speaker: string;
57
+ startTime: string;
58
+ segments: string[];
59
+ }>;
60
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/actions/formatters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAK5D,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtC,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gDAAgD;IAChD,OAAO,EAAE,CACP,MAAM,EAAE,OAAO,oBAAoB,EAAE,WAAW,EAChD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAChC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,wEAAwE;IACxE,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC1C,iCAAiC;IACjC,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,kDAAkD;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAC3D,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;AAI3D,8DAA8D;AAC9D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,OAAO,EACf,MAAM,GAAE,YAAqB,GAC5B,MAAM,CAWR;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAC7C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAWA;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAM1E;AAID,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,eAAe,EAAE,GACzB,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqBnE"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /**
3
+ * Shared formatting utilities for action output.
4
+ *
5
+ * Contains HTML cleaning, quote extraction, message formatting helpers,
6
+ * transcript grouping, and output format dispatch.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.formatOutput = formatOutput;
10
+ exports.toonHeader = toonHeader;
11
+ exports.cleanContent = cleanContent;
12
+ exports.extractQuote = extractQuote;
13
+ exports.buildSenderLookup = buildSenderLookup;
14
+ exports.formatTimestamp = formatTimestamp;
15
+ exports.groupBySpeaker = groupBySpeaker;
16
+ const html_utils_js_1 = require("../html-utils.js");
17
+ // ── Output format dispatch ───────────────────────────────────────────
18
+ /** Format an action result in the specified output format. */
19
+ function formatOutput(action, result, format = "json") {
20
+ switch (format) {
21
+ case "json":
22
+ return JSON.stringify(result, null, 2);
23
+ case "text":
24
+ return action.formatResult(result);
25
+ case "md":
26
+ return action.formatMarkdown(result);
27
+ case "toon":
28
+ return action.formatToon(result);
29
+ }
30
+ }
31
+ // ── Shared formatting helpers ────────────────────────────────────────
32
+ function toonHeader(emoji, text) {
33
+ const separator = "─".repeat(40);
34
+ return `\n ${emoji} ${text}\n ${separator}`;
35
+ }
36
+ /** Strip HTML tags and decode entities from message content. */
37
+ function cleanContent(content) {
38
+ return (0, html_utils_js_1.decodeHtmlEntities)(content.replace(/<[^>]*>/g, "")).trim();
39
+ }
40
+ /** Extract quoted text from HTML blockquotes, returning quote and body separately. */
41
+ function extractQuote(content) {
42
+ for (const tag of ["blockquote", "quote"]) {
43
+ const pattern = new RegExp(`<${tag}[^>]*>[\\s\\S]*?<\\/${tag}>`, "i");
44
+ const match = content.match(pattern);
45
+ if (match) {
46
+ const quote = cleanContent(match[0]);
47
+ const remainder = content.replace(pattern, "");
48
+ return { quote: quote || null, body: cleanContent(remainder) };
49
+ }
50
+ }
51
+ return { quote: null, body: cleanContent(content) };
52
+ }
53
+ /** Build a map from message ID to sender display name. */
54
+ function buildSenderLookup(messages) {
55
+ const lookup = new Map();
56
+ for (const message of messages) {
57
+ lookup.set(message.id, message.senderDisplayName || "(system)");
58
+ }
59
+ return lookup;
60
+ }
61
+ // ── Transcript formatting helpers ────────────────────────────────────
62
+ /** Format a VTT timestamp (HH:MM:SS.mmm) as a compact time string. */
63
+ function formatTimestamp(timestamp) {
64
+ // Strip leading "00:" hours if zero, and trim milliseconds
65
+ const withoutMilliseconds = timestamp.replace(/\.\d+$/, "");
66
+ return withoutMilliseconds.replace(/^00:/, "");
67
+ }
68
+ /** Group consecutive entries by the same speaker for more readable output. */
69
+ function groupBySpeaker(entries) {
70
+ const groups = [];
71
+ for (const entry of entries) {
72
+ const lastGroup = groups[groups.length - 1];
73
+ if (lastGroup && lastGroup.speaker === entry.speaker) {
74
+ lastGroup.segments.push(entry.text);
75
+ }
76
+ else {
77
+ groups.push({
78
+ speaker: entry.speaker,
79
+ startTime: entry.startTime,
80
+ segments: [entry.text],
81
+ });
82
+ }
83
+ }
84
+ return groups;
85
+ }
86
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/actions/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * REST API layer for the Teams Chat Service.
3
+ *
4
+ * All HTTP calls to {region}.ng.msg.teams.microsoft.com/v1 are here.
5
+ * This module is stateless — every function takes a TeamsToken explicitly.
6
+ */
7
+ import type { TeamsToken, Conversation, Message, MessageFormat, MessagesPage, Member, SentMessage, EditedMessage, DeletedMessage } from "../types.js";
8
+ /**
9
+ * Fetch conversations from the Teams Chat Service.
10
+ * Returns one page of conversations (no built-in pagination).
11
+ */
12
+ export declare function fetchConversations(token: TeamsToken, pageSize: number): Promise<Conversation[]>;
13
+ /**
14
+ * Fetch one page of messages from a conversation.
15
+ */
16
+ export declare function fetchMessagesPage(token: TeamsToken, conversationId: string, pageSize: number, backwardLink?: string): Promise<MessagesPage>;
17
+ /**
18
+ * Fetch members of a conversation.
19
+ */
20
+ export declare function fetchMembers(token: TeamsToken, conversationId: string): Promise<Member[]>;
21
+ /**
22
+ * Send a message to a conversation.
23
+ *
24
+ * The `format` parameter controls how `content` is interpreted:
25
+ * - `"text"` — plain text, sent as-is
26
+ * - `"markdown"` (default) — converted from Markdown to HTML
27
+ * - `"html"` — raw HTML, sent as-is
28
+ */
29
+ export declare function postMessage(token: TeamsToken, conversationId: string, content: string, senderDisplayName: string, format?: MessageFormat): Promise<SentMessage>;
30
+ /**
31
+ * Edit an existing message in a conversation.
32
+ *
33
+ * The `format` parameter controls how `content` is interpreted:
34
+ * - `"text"` — plain text, sent as-is
35
+ * - `"markdown"` (default) — converted from Markdown to HTML
36
+ * - `"html"` — raw HTML, sent as-is
37
+ */
38
+ export declare function editMessage(token: TeamsToken, conversationId: string, messageId: string, content: string, senderDisplayName: string, format?: MessageFormat): Promise<EditedMessage>;
39
+ /**
40
+ * Delete a message from a conversation.
41
+ *
42
+ * Sends a DELETE to the Chat Service; handles empty response body.
43
+ */
44
+ export declare function deleteMessage(token: TeamsToken, conversationId: string, messageId: string): Promise<DeletedMessage>;
45
+ /**
46
+ * Fetch user properties for the authenticated user.
47
+ * Returns raw properties — display name may or may not be present.
48
+ */
49
+ export declare function fetchUserProperties(token: TeamsToken): Promise<Record<string, unknown>>;
50
+ /**
51
+ * Parse a raw API message object into the public Message type.
52
+ */
53
+ export declare function parseRawMessage(raw: Record<string, unknown>): Message;
54
+ //# sourceMappingURL=chat-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-service.d.ts","sourceRoot":"","sources":["../../src/api/chat-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,OAAO,EACP,aAAa,EACb,YAAY,EACZ,MAAM,EAIN,WAAW,EACX,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAerB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAyCzB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CA+BnB;AAqCD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,EACzB,MAAM,GAAE,aAA0B,GACjC,OAAO,CAAC,WAAW,CAAC,CAkDtB;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,EACzB,MAAM,GAAE,aAA0B,GACjC,OAAO,CAAC,aAAa,CAAC,CAmDxB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC,CAqBzB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgBlC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAsCrE"}
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ /**
3
+ * REST API layer for the Teams Chat Service.
4
+ *
5
+ * All HTTP calls to {region}.ng.msg.teams.microsoft.com/v1 are here.
6
+ * This module is stateless — every function takes a TeamsToken explicitly.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.fetchConversations = fetchConversations;
13
+ exports.fetchMessagesPage = fetchMessagesPage;
14
+ exports.fetchMembers = fetchMembers;
15
+ exports.postMessage = postMessage;
16
+ exports.editMessage = editMessage;
17
+ exports.deleteMessage = deleteMessage;
18
+ exports.fetchUserProperties = fetchUserProperties;
19
+ exports.parseRawMessage = parseRawMessage;
20
+ const common_js_1 = require("./common.js");
21
+ const markdown_it_1 = __importDefault(require("markdown-it"));
22
+ const markdownRenderer = new markdown_it_1.default({ html: true, breaks: true });
23
+ const chatServiceBase = (region) => `https://${region}.ng.msg.teams.microsoft.com/v1`;
24
+ function authHeaders(token) {
25
+ return {
26
+ Authentication: `skypetoken=${token.skypeToken}`,
27
+ };
28
+ }
29
+ /**
30
+ * Fetch conversations from the Teams Chat Service.
31
+ * Returns one page of conversations (no built-in pagination).
32
+ */
33
+ async function fetchConversations(token, pageSize) {
34
+ const url = `${chatServiceBase(token.region)}/users/ME/conversations?view=mychats&pageSize=${pageSize}`;
35
+ const response = await (0, common_js_1.fetchWithRetry)(url, { headers: authHeaders(token) });
36
+ if (!response.ok) {
37
+ if (response.status === 401) {
38
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
39
+ }
40
+ throw new Error(`Failed to fetch conversations: ${response.status} ${response.statusText}`);
41
+ }
42
+ const data = (await response.json());
43
+ return (data.conversations ?? []).map((conversation) => ({
44
+ id: conversation.id,
45
+ topic: conversation.threadProperties?.topic ??
46
+ conversation.properties?.displayName ??
47
+ "",
48
+ threadType: conversation.threadProperties?.threadType ?? "chat",
49
+ version: conversation.version,
50
+ lastMessageTime: conversation.properties?.lastimreceivedtime ?? null,
51
+ memberCount: conversation.threadProperties?.memberCount
52
+ ? Number(conversation.threadProperties.memberCount)
53
+ : null,
54
+ }));
55
+ }
56
+ /**
57
+ * Fetch one page of messages from a conversation.
58
+ */
59
+ async function fetchMessagesPage(token, conversationId, pageSize, backwardLink) {
60
+ const url = backwardLink ??
61
+ `${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages?pageSize=${pageSize}`;
62
+ const response = await (0, common_js_1.fetchWithRetry)(url, { headers: authHeaders(token) });
63
+ if (!response.ok) {
64
+ if (response.status === 401) {
65
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
66
+ }
67
+ throw new Error(`Failed to fetch messages: ${response.status} ${response.statusText}`);
68
+ }
69
+ const data = (await response.json());
70
+ const messages = (data.messages ?? []).map(parseRawMessage);
71
+ return {
72
+ messages,
73
+ backwardLink: data._metadata?.backwardLink ?? null,
74
+ syncState: data._metadata?.syncState ?? null,
75
+ };
76
+ }
77
+ /**
78
+ * Fetch members of a conversation.
79
+ */
80
+ async function fetchMembers(token, conversationId) {
81
+ const url = `${chatServiceBase(token.region)}/threads/${encodeURIComponent(conversationId)}/members`;
82
+ const response = await (0, common_js_1.fetchWithRetry)(url, { headers: authHeaders(token) });
83
+ if (!response.ok) {
84
+ if (response.status === 401) {
85
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
86
+ }
87
+ throw new Error(`Failed to fetch members: ${response.status} ${response.statusText}`);
88
+ }
89
+ const data = (await response.json());
90
+ return (data.members ?? []).map((member) => ({
91
+ id: member.id,
92
+ displayName: member.userDisplayName ?? "",
93
+ role: member.role ?? "member",
94
+ memberType: member.id.startsWith("28:")
95
+ ? "bot"
96
+ : "person",
97
+ }));
98
+ }
99
+ /**
100
+ * Convert content to the appropriate format for the Teams API.
101
+ *
102
+ * - "text": sent as-is with messagetype "Text"
103
+ * - "markdown": converted from Markdown to HTML, sent as "RichText/Html"
104
+ * - "html": sent as-is with messagetype "RichText/Html"
105
+ */
106
+ function resolveMessageContent(content, format) {
107
+ switch (format) {
108
+ case "text":
109
+ return {
110
+ resolvedContent: content,
111
+ messagetype: "Text",
112
+ contenttype: "text",
113
+ };
114
+ case "html":
115
+ return {
116
+ resolvedContent: content,
117
+ messagetype: "RichText/Html",
118
+ contenttype: "text",
119
+ };
120
+ case "markdown": {
121
+ const htmlContent = markdownRenderer.render(content);
122
+ return {
123
+ resolvedContent: htmlContent,
124
+ messagetype: "RichText/Html",
125
+ contenttype: "text",
126
+ };
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Send a message to a conversation.
132
+ *
133
+ * The `format` parameter controls how `content` is interpreted:
134
+ * - `"text"` — plain text, sent as-is
135
+ * - `"markdown"` (default) — converted from Markdown to HTML
136
+ * - `"html"` — raw HTML, sent as-is
137
+ */
138
+ async function postMessage(token, conversationId, content, senderDisplayName, format = "markdown") {
139
+ const url = `${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages`;
140
+ const clientMessageId = String(Date.now());
141
+ const { resolvedContent, messagetype, contenttype } = resolveMessageContent(content, format);
142
+ const body = {
143
+ content: resolvedContent,
144
+ messagetype,
145
+ contenttype,
146
+ clientmessageid: clientMessageId,
147
+ imdisplayname: senderDisplayName,
148
+ properties: {
149
+ importance: "",
150
+ subject: null,
151
+ },
152
+ };
153
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
154
+ method: "POST",
155
+ headers: {
156
+ ...authHeaders(token),
157
+ "Content-Type": "application/json",
158
+ },
159
+ body: JSON.stringify(body),
160
+ });
161
+ if (!response.ok) {
162
+ if (response.status === 401) {
163
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
164
+ }
165
+ const errorText = await response.text();
166
+ throw new Error(`Failed to send message: ${response.status} ${response.statusText} — ${errorText}`);
167
+ }
168
+ const data = (await response.json());
169
+ return {
170
+ messageId: String(data.OriginalArrivalTime),
171
+ arrivalTime: data.OriginalArrivalTime,
172
+ };
173
+ }
174
+ /**
175
+ * Edit an existing message in a conversation.
176
+ *
177
+ * The `format` parameter controls how `content` is interpreted:
178
+ * - `"text"` — plain text, sent as-is
179
+ * - `"markdown"` (default) — converted from Markdown to HTML
180
+ * - `"html"` — raw HTML, sent as-is
181
+ */
182
+ async function editMessage(token, conversationId, messageId, content, senderDisplayName, format = "markdown") {
183
+ const url = `${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages/${encodeURIComponent(messageId)}`;
184
+ const { resolvedContent, messagetype, contenttype } = resolveMessageContent(content, format);
185
+ const body = {
186
+ content: resolvedContent,
187
+ messagetype,
188
+ contenttype,
189
+ skypeeditedid: messageId,
190
+ imdisplayname: senderDisplayName,
191
+ };
192
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
193
+ method: "PUT",
194
+ headers: {
195
+ ...authHeaders(token),
196
+ "Content-Type": "application/json",
197
+ },
198
+ body: JSON.stringify(body),
199
+ });
200
+ if (!response.ok) {
201
+ if (response.status === 401) {
202
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
203
+ }
204
+ const errorText = await response.text();
205
+ throw new Error(`Failed to edit message: ${response.status} ${response.statusText} — ${errorText}`);
206
+ }
207
+ const responseText = await response.text();
208
+ let editTime;
209
+ if (responseText) {
210
+ const data = JSON.parse(responseText);
211
+ editTime = data.edittime ?? new Date().toISOString();
212
+ }
213
+ else {
214
+ editTime = new Date().toISOString();
215
+ }
216
+ return {
217
+ messageId,
218
+ editTime,
219
+ };
220
+ }
221
+ /**
222
+ * Delete a message from a conversation.
223
+ *
224
+ * Sends a DELETE to the Chat Service; handles empty response body.
225
+ */
226
+ async function deleteMessage(token, conversationId, messageId) {
227
+ const url = `${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages/${encodeURIComponent(messageId)}`;
228
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
229
+ method: "DELETE",
230
+ headers: authHeaders(token),
231
+ });
232
+ if (!response.ok) {
233
+ if (response.status === 401) {
234
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
235
+ }
236
+ const errorText = await response.text();
237
+ throw new Error(`Failed to delete message: ${response.status} ${response.statusText} — ${errorText}`);
238
+ }
239
+ return { messageId };
240
+ }
241
+ /**
242
+ * Fetch user properties for the authenticated user.
243
+ * Returns raw properties — display name may or may not be present.
244
+ */
245
+ async function fetchUserProperties(token) {
246
+ const url = `${chatServiceBase(token.region)}/users/ME/properties`;
247
+ const response = await (0, common_js_1.fetchWithRetry)(url, { headers: authHeaders(token) });
248
+ if (!response.ok) {
249
+ if (response.status === 401) {
250
+ throw new common_js_1.ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
251
+ }
252
+ throw new Error(`Failed to fetch user properties: ${response.status} ${response.statusText}`);
253
+ }
254
+ return (await response.json());
255
+ }
256
+ /**
257
+ * Parse a raw API message object into the public Message type.
258
+ */
259
+ function parseRawMessage(raw) {
260
+ const properties = (raw.properties ?? {});
261
+ const allEmotions = parseEmotions(properties.emotions);
262
+ const reactions = allEmotions.filter((emotion) => emotion.key !== "follow");
263
+ const followEntry = allEmotions.find((emotion) => emotion.key === "follow");
264
+ const followers = (followEntry?.users ?? [])
265
+ .filter((user) => String(user.value) === "0")
266
+ .map((user) => ({ mri: user.mri, time: user.time }));
267
+ const mentions = parseMentions(properties.mentions);
268
+ let quotedMessageId = null;
269
+ const content = String(raw.content ?? "");
270
+ const quoteMatch = content.match(/itemtype="http:\/\/schema\.skype\.com\/Reply"\s+itemid="(\d+)"/);
271
+ if (quoteMatch) {
272
+ quotedMessageId = quoteMatch[1];
273
+ }
274
+ return {
275
+ id: String(raw.id ?? ""),
276
+ messageType: String(raw.messagetype ?? ""),
277
+ senderMri: String(raw.from ?? ""),
278
+ senderDisplayName: String(raw.imdisplayname ?? ""),
279
+ content,
280
+ originalArrivalTime: String(raw.originalarrivaltime ?? ""),
281
+ composeTime: String(raw.composetime ?? ""),
282
+ editTime: properties.edittime ? String(properties.edittime) : null,
283
+ subject: properties.subject ? String(properties.subject) : null,
284
+ isDeleted: raw.messagetype === "MessageDelete" ||
285
+ String(properties.deletetime ?? "") !== "",
286
+ reactions,
287
+ followers,
288
+ mentions,
289
+ quotedMessageId,
290
+ };
291
+ }
292
+ function parseEmotions(rawEmotions) {
293
+ if (typeof rawEmotions === "string") {
294
+ try {
295
+ return JSON.parse(rawEmotions);
296
+ }
297
+ catch {
298
+ return [];
299
+ }
300
+ }
301
+ if (Array.isArray(rawEmotions)) {
302
+ return rawEmotions;
303
+ }
304
+ return [];
305
+ }
306
+ function parseMentions(rawMentions) {
307
+ let parsed;
308
+ if (typeof rawMentions === "string") {
309
+ try {
310
+ parsed = JSON.parse(rawMentions);
311
+ }
312
+ catch {
313
+ return [];
314
+ }
315
+ }
316
+ else if (Array.isArray(rawMentions)) {
317
+ parsed = rawMentions;
318
+ }
319
+ else {
320
+ return [];
321
+ }
322
+ return parsed.map((mention) => ({
323
+ id: mention.id ?? "",
324
+ displayName: mention.displayName ?? "",
325
+ }));
326
+ }
327
+ //# sourceMappingURL=chat-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-service.js","sourceRoot":"","sources":["../../src/api/chat-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Common utilities shared across API modules.
3
+ *
4
+ * Contains error classes, retry logic, and shared helpers
5
+ * used by chat-service, middle-tier, substrate, and transcript modules.
6
+ */
7
+ export declare class ApiAuthError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ export declare class ApiRateLimitError extends Error {
11
+ readonly retryAfterMilliseconds: number;
12
+ constructor(message: string, retryAfterMilliseconds: number);
13
+ }
14
+ /**
15
+ * Wrapper around `fetch` that automatically retries on 429 (rate limit) responses.
16
+ *
17
+ * Uses the `Retry-After` header when present; otherwise applies exponential backoff
18
+ * starting at 2 seconds. Retries up to 5 times before throwing `ApiRateLimitError`.
19
+ */
20
+ export declare function fetchWithRetry(input: string | URL | Request, init?: RequestInit): Promise<Response>;
21
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/api/common.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,SAAgB,sBAAsB,EAAE,MAAM,CAAC;gBAEnC,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM;CAK5D;AAqBD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,QAAQ,CAAC,CAsBnB"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Common utilities shared across API modules.
4
+ *
5
+ * Contains error classes, retry logic, and shared helpers
6
+ * used by chat-service, middle-tier, substrate, and transcript modules.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ApiRateLimitError = exports.ApiAuthError = void 0;
10
+ exports.fetchWithRetry = fetchWithRetry;
11
+ class ApiAuthError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "ApiAuthError";
15
+ }
16
+ }
17
+ exports.ApiAuthError = ApiAuthError;
18
+ class ApiRateLimitError extends Error {
19
+ retryAfterMilliseconds;
20
+ constructor(message, retryAfterMilliseconds) {
21
+ super(message);
22
+ this.name = "ApiRateLimitError";
23
+ this.retryAfterMilliseconds = retryAfterMilliseconds;
24
+ }
25
+ }
26
+ exports.ApiRateLimitError = ApiRateLimitError;
27
+ const MAX_RETRY_ATTEMPTS = 5;
28
+ const INITIAL_BACKOFF_MILLISECONDS = 2_000;
29
+ function parseRetryAfter(response) {
30
+ const retryAfterHeader = response.headers.get("Retry-After");
31
+ if (!retryAfterHeader) {
32
+ return INITIAL_BACKOFF_MILLISECONDS;
33
+ }
34
+ const seconds = Number(retryAfterHeader);
35
+ if (!Number.isNaN(seconds) && seconds > 0) {
36
+ return seconds * 1_000;
37
+ }
38
+ return INITIAL_BACKOFF_MILLISECONDS;
39
+ }
40
+ function delay(milliseconds) {
41
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
42
+ }
43
+ /**
44
+ * Wrapper around `fetch` that automatically retries on 429 (rate limit) responses.
45
+ *
46
+ * Uses the `Retry-After` header when present; otherwise applies exponential backoff
47
+ * starting at 2 seconds. Retries up to 5 times before throwing `ApiRateLimitError`.
48
+ */
49
+ async function fetchWithRetry(input, init) {
50
+ for (let attempt = 0; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
51
+ const response = await fetch(input, init);
52
+ if (response.status !== 429) {
53
+ return response;
54
+ }
55
+ if (attempt === MAX_RETRY_ATTEMPTS) {
56
+ const errorText = await response.text();
57
+ throw new ApiRateLimitError(`Rate limit exceeded after ${MAX_RETRY_ATTEMPTS + 1} attempts: ${response.status} ${errorText}`, parseRetryAfter(response));
58
+ }
59
+ const retryAfterMilliseconds = parseRetryAfter(response);
60
+ const backoffMilliseconds = retryAfterMilliseconds * Math.pow(2, attempt);
61
+ await delay(backoffMilliseconds);
62
+ }
63
+ throw new Error("Unreachable: fetchWithRetry loop exited unexpectedly");
64
+ }
65
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/api/common.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AA4CH,wCAyBC;AAnED,MAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AALD,oCAKC;AAED,MAAa,iBAAkB,SAAQ,KAAK;IAC1B,sBAAsB,CAAS;IAE/C,YAAY,OAAe,EAAE,sBAA8B;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;IACvD,CAAC;CACF;AARD,8CAQC;AAED,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,4BAA4B,GAAG,KAAK,CAAC;AAE3C,SAAS,eAAe,CAAC,QAAkB;IACzC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7D,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,4BAA4B,CAAC;IACtC,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IACD,OAAO,4BAA4B,CAAC;AACtC,CAAC;AAED,SAAS,KAAK,CAAC,YAAoB;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,cAAc,CAClC,KAA6B,EAC7B,IAAkB;IAElB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,OAAO,KAAK,kBAAkB,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,iBAAiB,CACzB,6BAA6B,kBAAkB,GAAG,CAAC,cAAc,QAAQ,CAAC,MAAM,IAAI,SAAS,EAAE,EAC/F,eAAe,CAAC,QAAQ,CAAC,CAC1B,CAAC;QACJ,CAAC;QAED,MAAM,sBAAsB,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,mBAAmB,GAAG,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC1E,MAAM,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC"}