teams-api 0.5.2 → 0.7.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 (89) hide show
  1. package/README.md +1 -14
  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} +83 -212
  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.d.ts +2 -2
  55. package/dist/cli.js +21 -7
  56. package/dist/cli.js.map +1 -1
  57. package/dist/constants.d.ts +9 -0
  58. package/dist/constants.d.ts.map +1 -0
  59. package/dist/constants.js +14 -0
  60. package/dist/constants.js.map +1 -0
  61. package/dist/html-utils.d.ts +9 -0
  62. package/dist/html-utils.d.ts.map +1 -0
  63. package/dist/html-utils.js +21 -0
  64. package/dist/html-utils.js.map +1 -0
  65. package/dist/mcp-server.js +7 -3
  66. package/dist/mcp-server.js.map +1 -1
  67. package/dist/server-instructions.d.ts +13 -0
  68. package/dist/server-instructions.d.ts.map +1 -0
  69. package/dist/server-instructions.js +60 -0
  70. package/dist/server-instructions.js.map +1 -0
  71. package/dist/teams-client.d.ts +17 -8
  72. package/dist/teams-client.d.ts.map +1 -1
  73. package/dist/teams-client.js +90 -75
  74. package/dist/teams-client.js.map +1 -1
  75. package/dist/types.d.ts +20 -1
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/types.js.map +1 -1
  78. package/package.json +1 -2
  79. package/SKILL.md +0 -135
  80. package/dist/actions.d.ts.map +0 -1
  81. package/dist/actions.js.map +0 -1
  82. package/dist/api.d.ts +0 -126
  83. package/dist/api.d.ts.map +0 -1
  84. package/dist/api.js +0 -702
  85. package/dist/api.js.map +0 -1
  86. package/dist/auth.d.ts +0 -53
  87. package/dist/auth.d.ts.map +0 -1
  88. package/dist/auth.js +0 -491
  89. package/dist/auth.js.map +0 -1
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Teams middle-tier API for profile resolution.
3
+ *
4
+ * HTTP calls to teams.cloud.microsoft/api/mt/{region} for user profiles.
5
+ * Requires an OAuth2 Bearer token (api.spaces.skype.com audience).
6
+ */
7
+ import type { TeamsToken, UserProfile } from "../types.js";
8
+ /**
9
+ * Resolve display names for a batch of MRIs via the Teams middle-tier profile endpoint.
10
+ *
11
+ * Requires a Bearer token (api.spaces.skype.com audience). Throws `ApiAuthError`
12
+ * if the token is unavailable so callers can trigger re-authentication.
13
+ */
14
+ export declare function fetchProfiles(token: TeamsToken, mris: string[]): Promise<UserProfile[]>;
15
+ //# sourceMappingURL=middle-tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middle-tier.d.ts","sourceRoot":"","sources":["../../src/api/middle-tier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK3D;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,WAAW,EAAE,CAAC,CAoDxB"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ /**
3
+ * Teams middle-tier API for profile resolution.
4
+ *
5
+ * HTTP calls to teams.cloud.microsoft/api/mt/{region} for user profiles.
6
+ * Requires an OAuth2 Bearer token (api.spaces.skype.com audience).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.fetchProfiles = fetchProfiles;
10
+ const common_js_1 = require("./common.js");
11
+ const MIDDLE_TIER_BASE = "https://teams.cloud.microsoft/api/mt";
12
+ /**
13
+ * Resolve display names for a batch of MRIs via the Teams middle-tier profile endpoint.
14
+ *
15
+ * Requires a Bearer token (api.spaces.skype.com audience). Throws `ApiAuthError`
16
+ * if the token is unavailable so callers can trigger re-authentication.
17
+ */
18
+ async function fetchProfiles(token, mris) {
19
+ if (mris.length === 0) {
20
+ return [];
21
+ }
22
+ if (!token.bearerToken) {
23
+ throw new common_js_1.ApiAuthError("Bearer token is missing — re-authentication required for profile resolution");
24
+ }
25
+ const url = `${MIDDLE_TIER_BASE}/${token.region}/beta/users/fetchShortProfile?isMailAddress=false&enableGuest=true&skypeTeamsInfo=true`;
26
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ Authorization: `Bearer ${token.bearerToken}`,
31
+ },
32
+ body: JSON.stringify(mris),
33
+ });
34
+ if (!response.ok) {
35
+ if (response.status === 401) {
36
+ throw new common_js_1.ApiAuthError(`Profile resolution authentication failed: ${response.status} ${response.statusText}`);
37
+ }
38
+ if (response.status >= 500) {
39
+ throw new Error(`Profile resolution server error: ${response.status} ${response.statusText}`);
40
+ }
41
+ return [];
42
+ }
43
+ const data = (await response.json());
44
+ return (data.value ?? []).map((profile) => ({
45
+ mri: profile.mri ?? "",
46
+ displayName: profile.displayName ?? "",
47
+ email: profile.email ?? "",
48
+ jobTitle: profile.jobTitle ?? "",
49
+ userType: profile.userType ?? "",
50
+ }));
51
+ }
52
+ //# sourceMappingURL=middle-tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middle-tier.js","sourceRoot":"","sources":["../../src/api/middle-tier.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAaH,sCAuDC;AAjED,2CAA2D;AAE3D,MAAM,gBAAgB,GAAG,sCAAsC,CAAC;AAEhE;;;;;GAKG;AACI,KAAK,UAAU,aAAa,CACjC,KAAiB,EACjB,IAAc;IAEd,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,IAAI,wBAAY,CACpB,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,gBAAgB,IAAI,KAAK,CAAC,MAAM,wFAAwF,CAAC;IAExI,MAAM,QAAQ,GAAG,MAAM,IAAA,0BAAc,EAAC,GAAG,EAAE;QACzC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,CAAC,WAAW,EAAE;SAC7C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,wBAAY,CACpB,6CAA6C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACtF,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,oCAAoC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC7E,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAQlC,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC1C,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;QACtB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;QACtC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;KACjC,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Substrate search API for people and chat discovery.
3
+ *
4
+ * HTTP calls to substrate.office.com for searching people and chats.
5
+ * Requires a Substrate Bearer token (substrate.office.com audience).
6
+ */
7
+ import type { TeamsToken, PersonSearchResult, ChatSearchResult } from "../types.js";
8
+ /**
9
+ * Search for people by name using the Substrate suggestions API.
10
+ *
11
+ * Requires a Substrate Bearer token (substrate.office.com audience).
12
+ * Returns matching people with their MRIs, emails, job titles, etc.
13
+ */
14
+ export declare function searchPeople(token: TeamsToken, query: string, maxResults?: number): Promise<PersonSearchResult[]>;
15
+ /**
16
+ * Search for chats by name or member using the Substrate suggestions API.
17
+ *
18
+ * Requires a Substrate Bearer token (substrate.office.com audience).
19
+ * Returns matching chats with their thread IDs, members, etc.
20
+ */
21
+ export declare function searchChats(token: TeamsToken, query: string, maxResults?: number): Promise<ChatSearchResult[]>;
22
+ //# sourceMappingURL=substrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substrate.d.ts","sourceRoot":"","sources":["../../src/api/substrate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAKrB;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,SAAK,GACd,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA2G/B;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,SAAK,GACd,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAmF7B"}
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * Substrate search API for people and chat discovery.
4
+ *
5
+ * HTTP calls to substrate.office.com for searching people and chats.
6
+ * Requires a Substrate Bearer token (substrate.office.com audience).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.searchPeople = searchPeople;
10
+ exports.searchChats = searchChats;
11
+ const common_js_1 = require("./common.js");
12
+ const SUBSTRATE_SEARCH_BASE = "https://substrate.office.com";
13
+ /**
14
+ * Search for people by name using the Substrate suggestions API.
15
+ *
16
+ * Requires a Substrate Bearer token (substrate.office.com audience).
17
+ * Returns matching people with their MRIs, emails, job titles, etc.
18
+ */
19
+ async function searchPeople(token, query, maxResults = 10) {
20
+ if (!token.substrateToken) {
21
+ throw new common_js_1.ApiAuthError("Substrate token is missing — re-authentication required for people search");
22
+ }
23
+ const url = `${SUBSTRATE_SEARCH_BASE}/search/api/v1/suggestions?scenario=peoplepicker.newChat`;
24
+ const body = {
25
+ EntityRequests: [
26
+ {
27
+ Query: {
28
+ QueryString: query,
29
+ DisplayQueryString: query,
30
+ },
31
+ EntityType: "People",
32
+ Size: maxResults,
33
+ Fields: [
34
+ "Id",
35
+ "MRI",
36
+ "DisplayName",
37
+ "EmailAddresses",
38
+ "PeopleType",
39
+ "PeopleSubtype",
40
+ "UserPrincipalName",
41
+ "GivenName",
42
+ "Surname",
43
+ "JobTitle",
44
+ "Department",
45
+ "ExternalDirectoryObjectId",
46
+ ],
47
+ Filter: {
48
+ And: [
49
+ {
50
+ Or: [
51
+ { Term: { PeopleType: "Person" } },
52
+ { Term: { PeopleType: "Other" } },
53
+ ],
54
+ },
55
+ {
56
+ Or: [
57
+ { Term: { PeopleSubtype: "OrganizationUser" } },
58
+ { Term: { PeopleSubtype: "MTOUser" } },
59
+ { Term: { PeopleSubtype: "Guest" } },
60
+ ],
61
+ },
62
+ { Or: [{ Term: { Flags: "NonHidden" } }] },
63
+ ],
64
+ },
65
+ Provenances: ["Mailbox", "Directory"],
66
+ From: 0,
67
+ },
68
+ ],
69
+ Scenario: { Name: "peoplepicker.newChat" },
70
+ AppName: "Microsoft Teams",
71
+ };
72
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
73
+ method: "POST",
74
+ headers: {
75
+ "Content-Type": "application/json",
76
+ Authorization: `Bearer ${token.substrateToken}`,
77
+ },
78
+ body: JSON.stringify(body),
79
+ });
80
+ if (!response.ok) {
81
+ if (response.status === 401) {
82
+ throw new common_js_1.ApiAuthError(`Substrate search authentication failed: ${response.status} ${response.statusText}`);
83
+ }
84
+ if (response.status >= 500) {
85
+ throw new Error(`Substrate search server error: ${response.status} ${response.statusText}`);
86
+ }
87
+ return [];
88
+ }
89
+ const data = (await response.json());
90
+ const peopleGroup = data.Groups?.find((group) => group.Type === "People");
91
+ if (!peopleGroup?.Suggestions)
92
+ return [];
93
+ return peopleGroup.Suggestions.map((suggestion) => ({
94
+ displayName: suggestion.DisplayName ?? "",
95
+ mri: suggestion.MRI ?? "",
96
+ email: suggestion.EmailAddresses?.[0] ?? suggestion.UserPrincipalName ?? "",
97
+ jobTitle: suggestion.JobTitle ?? "",
98
+ department: suggestion.Department ?? "",
99
+ objectId: suggestion.ExternalDirectoryObjectId ?? "",
100
+ }));
101
+ }
102
+ /**
103
+ * Search for chats by name or member using the Substrate suggestions API.
104
+ *
105
+ * Requires a Substrate Bearer token (substrate.office.com audience).
106
+ * Returns matching chats with their thread IDs, members, etc.
107
+ */
108
+ async function searchChats(token, query, maxResults = 10) {
109
+ if (!token.substrateToken) {
110
+ throw new common_js_1.ApiAuthError("Substrate token is missing — re-authentication required for chat search");
111
+ }
112
+ const url = `${SUBSTRATE_SEARCH_BASE}/search/api/v1/suggestions?scenario=peoplepicker.newChat`;
113
+ const body = {
114
+ EntityRequests: [
115
+ {
116
+ Query: {
117
+ QueryString: query,
118
+ },
119
+ EntityType: "Chat",
120
+ Size: maxResults,
121
+ },
122
+ ],
123
+ Scenario: { Name: "peoplepicker.newChat" },
124
+ AppName: "Microsoft Teams",
125
+ };
126
+ const response = await (0, common_js_1.fetchWithRetry)(url, {
127
+ method: "POST",
128
+ headers: {
129
+ "Content-Type": "application/json",
130
+ Authorization: `Bearer ${token.substrateToken}`,
131
+ },
132
+ body: JSON.stringify(body),
133
+ });
134
+ if (!response.ok) {
135
+ if (response.status === 401) {
136
+ throw new common_js_1.ApiAuthError(`Substrate search authentication failed: ${response.status} ${response.statusText}`);
137
+ }
138
+ if (response.status >= 500) {
139
+ throw new Error(`Substrate search server error: ${response.status} ${response.statusText}`);
140
+ }
141
+ return [];
142
+ }
143
+ const data = (await response.json());
144
+ const chatGroup = data.Groups?.find((group) => group.Type === "Chat");
145
+ if (!chatGroup?.Suggestions)
146
+ return [];
147
+ return chatGroup.Suggestions.map((suggestion) => ({
148
+ name: suggestion.Name ?? "",
149
+ threadId: suggestion.ThreadId ?? "",
150
+ threadType: suggestion.ThreadType ?? "",
151
+ matchingMembers: (suggestion.MatchingMembers ?? []).map((member) => ({
152
+ displayName: member.DisplayName ?? "",
153
+ mri: member.MRI ?? "",
154
+ })),
155
+ chatMembers: (suggestion.ChatMembers ?? []).map((member) => ({
156
+ displayName: member.DisplayName ?? "",
157
+ mri: member.MRI ?? "",
158
+ })),
159
+ totalMemberCount: suggestion.TotalChatMembersCount ?? 0,
160
+ }));
161
+ }
162
+ //# sourceMappingURL=substrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substrate.js","sourceRoot":"","sources":["../../src/api/substrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Transcript fetching and VTT parsing for Teams meetings.
3
+ *
4
+ * Handles extracting transcript URLs from recording messages,
5
+ * fetching VTT content from the AMS (Async Media Service),
6
+ * and parsing VTT into structured entries.
7
+ */
8
+ import type { TeamsToken, TranscriptEntry, TranscriptResult } from "../types.js";
9
+ /**
10
+ * Extract the AMS transcript URL from a `RichText/Media_CallRecording` message.
11
+ *
12
+ * The message content is XML containing `<item type="amsTranscript" uri="...">`.
13
+ * Returns null if no transcript URL is found.
14
+ */
15
+ export declare function extractTranscriptUrl(messageContent: string): string | null;
16
+ /**
17
+ * Extract the meeting title from a `RichText/Media_CallRecording` message.
18
+ *
19
+ * The title is in the `<OriginalName>` element inside the XML content.
20
+ */
21
+ export declare function extractMeetingTitle(messageContent: string): string;
22
+ /**
23
+ * Check whether a `RichText/Media_CallRecording` message represents
24
+ * a successful recording (as opposed to started/failed).
25
+ */
26
+ export declare function isSuccessfulRecording(messageContent: string): boolean;
27
+ /**
28
+ * Parse VTT content into structured transcript entries.
29
+ *
30
+ * Handles the Teams VTT format with `<v Speaker Name>text</v>` tags
31
+ * and HTML entities.
32
+ */
33
+ export declare function parseVtt(vttContent: string): TranscriptEntry[];
34
+ /**
35
+ * Fetch a transcript from the AMS (Async Media Service).
36
+ *
37
+ * Uses `Authorization: skype_token <token>` header (note: different format
38
+ * from the Chat Service `Authentication: skypetoken=<token>` header).
39
+ */
40
+ export declare function fetchTranscriptVtt(token: TeamsToken, amsTranscriptUrl: string): Promise<string>;
41
+ /**
42
+ * Fetch and parse the transcript for a conversation.
43
+ *
44
+ * 1. Fetches messages from the conversation
45
+ * 2. Finds the latest `RichText/Media_CallRecording` message with status="Success"
46
+ * 3. Extracts the AMS transcript URL from the XML content
47
+ * 4. Fetches the VTT content from AMS
48
+ * 5. Parses the VTT into structured entries
49
+ */
50
+ export declare function fetchTranscript(token: TeamsToken, conversationId: string): Promise<TranscriptResult>;
51
+ //# sourceMappingURL=transcripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcripts.d.ts","sourceRoot":"","sources":["../../src/api/transcripts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAKrB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK1E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,EAAE,CAiC9D;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * Transcript fetching and VTT parsing for Teams meetings.
4
+ *
5
+ * Handles extracting transcript URLs from recording messages,
6
+ * fetching VTT content from the AMS (Async Media Service),
7
+ * and parsing VTT into structured entries.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.extractTranscriptUrl = extractTranscriptUrl;
11
+ exports.extractMeetingTitle = extractMeetingTitle;
12
+ exports.isSuccessfulRecording = isSuccessfulRecording;
13
+ exports.parseVtt = parseVtt;
14
+ exports.fetchTranscriptVtt = fetchTranscriptVtt;
15
+ exports.fetchTranscript = fetchTranscript;
16
+ const common_js_1 = require("./common.js");
17
+ const chat_service_js_1 = require("./chat-service.js");
18
+ const html_utils_js_1 = require("../html-utils.js");
19
+ /**
20
+ * Extract the AMS transcript URL from a `RichText/Media_CallRecording` message.
21
+ *
22
+ * The message content is XML containing `<item type="amsTranscript" uri="...">`.
23
+ * Returns null if no transcript URL is found.
24
+ */
25
+ function extractTranscriptUrl(messageContent) {
26
+ const match = messageContent.match(/<item\s+[^>]*type="amsTranscript"[^>]*\buri="([^"]+)"/);
27
+ return match?.[1] ?? null;
28
+ }
29
+ /**
30
+ * Extract the meeting title from a `RichText/Media_CallRecording` message.
31
+ *
32
+ * The title is in the `<OriginalName>` element inside the XML content.
33
+ */
34
+ function extractMeetingTitle(messageContent) {
35
+ const match = messageContent.match(/<OriginalName\b[^>]*v="([^"]*)"[^>]*\/>/);
36
+ return match?.[1] ?? "Unknown Meeting";
37
+ }
38
+ /**
39
+ * Check whether a `RichText/Media_CallRecording` message represents
40
+ * a successful recording (as opposed to started/failed).
41
+ */
42
+ function isSuccessfulRecording(messageContent) {
43
+ return /<RecordingStatus\b[^>]*status="Success"/.test(messageContent);
44
+ }
45
+ /**
46
+ * Parse VTT content into structured transcript entries.
47
+ *
48
+ * Handles the Teams VTT format with `<v Speaker Name>text</v>` tags
49
+ * and HTML entities.
50
+ */
51
+ function parseVtt(vttContent) {
52
+ const entries = [];
53
+ const lines = vttContent.split("\n");
54
+ let currentStartTime = "";
55
+ let currentEndTime = "";
56
+ for (const line of lines) {
57
+ // Match timestamp lines: "00:00:00.000 --> 00:00:05.000"
58
+ const timestampMatch = line.match(/^(\d{2}:\d{2}:\d{2}\.\d{3})\s+-->\s+(\d{2}:\d{2}:\d{2}\.\d{3})/);
59
+ if (timestampMatch) {
60
+ currentStartTime = timestampMatch[1];
61
+ currentEndTime = timestampMatch[2];
62
+ continue;
63
+ }
64
+ // Match speaker lines: "<v Speaker Name>text</v>"
65
+ const speakerMatch = line.match(/^<v\s+([^>]+)>(.+)<\/v>\s*$/);
66
+ if (speakerMatch && currentStartTime) {
67
+ entries.push({
68
+ speaker: (0, html_utils_js_1.decodeHtmlEntities)(speakerMatch[1]),
69
+ startTime: currentStartTime,
70
+ endTime: currentEndTime,
71
+ text: (0, html_utils_js_1.decodeHtmlEntities)(speakerMatch[2]),
72
+ });
73
+ currentStartTime = "";
74
+ currentEndTime = "";
75
+ }
76
+ }
77
+ return entries;
78
+ }
79
+ /**
80
+ * Fetch a transcript from the AMS (Async Media Service).
81
+ *
82
+ * Uses `Authorization: skype_token <token>` header (note: different format
83
+ * from the Chat Service `Authentication: skypetoken=<token>` header).
84
+ */
85
+ async function fetchTranscriptVtt(token, amsTranscriptUrl) {
86
+ const response = await (0, common_js_1.fetchWithRetry)(amsTranscriptUrl, {
87
+ headers: {
88
+ Authorization: `skype_token ${token.skypeToken}`,
89
+ },
90
+ });
91
+ if (!response.ok) {
92
+ if (response.status === 401) {
93
+ throw new common_js_1.ApiAuthError(`Transcript fetch authentication failed: ${response.status} ${response.statusText}`);
94
+ }
95
+ throw new Error(`Failed to fetch transcript: ${response.status} ${response.statusText}`);
96
+ }
97
+ return response.text();
98
+ }
99
+ /**
100
+ * Fetch and parse the transcript for a conversation.
101
+ *
102
+ * 1. Fetches messages from the conversation
103
+ * 2. Finds the latest `RichText/Media_CallRecording` message with status="Success"
104
+ * 3. Extracts the AMS transcript URL from the XML content
105
+ * 4. Fetches the VTT content from AMS
106
+ * 5. Parses the VTT into structured entries
107
+ */
108
+ async function fetchTranscript(token, conversationId) {
109
+ // Fetch messages to find the recording message
110
+ const pageSize = 200;
111
+ const maxPages = 20;
112
+ let backwardLink;
113
+ let amsTranscriptUrl = null;
114
+ let meetingTitle = "Unknown Meeting";
115
+ for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {
116
+ const page = await (0, chat_service_js_1.fetchMessagesPage)(token, conversationId, pageSize, backwardLink);
117
+ for (const message of page.messages) {
118
+ if (message.messageType === "RichText/Media_CallRecording" &&
119
+ isSuccessfulRecording(message.content)) {
120
+ const transcriptUrl = extractTranscriptUrl(message.content);
121
+ if (transcriptUrl) {
122
+ amsTranscriptUrl = transcriptUrl;
123
+ meetingTitle = extractMeetingTitle(message.content);
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ if (amsTranscriptUrl || !page.backwardLink)
129
+ break;
130
+ backwardLink = page.backwardLink;
131
+ }
132
+ if (!amsTranscriptUrl) {
133
+ throw new Error("No meeting transcript found in this conversation. " +
134
+ "Make sure the conversation contains a recorded meeting with a transcript.");
135
+ }
136
+ const rawVtt = await fetchTranscriptVtt(token, amsTranscriptUrl);
137
+ const entries = parseVtt(rawVtt);
138
+ return { meetingTitle, rawVtt, entries };
139
+ }
140
+ //# sourceMappingURL=transcripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcripts.js","sourceRoot":"","sources":["../../src/api/transcripts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Automatic FIDO2 passkey login for Teams.
3
+ *
4
+ * Launches system Chrome with a fresh profile, completes the Microsoft
5
+ * Entra ID FIDO2 login flow using a platform authenticator, and captures
6
+ * the skype token from network requests. macOS only.
7
+ */
8
+ import type { TeamsToken, AutoLoginOptions } from "../types.js";
9
+ /**
10
+ * Acquire a Teams skype token with zero user interaction.
11
+ *
12
+ * Launches system Chrome with a fresh profile, navigates to Teams,
13
+ * enters the corporate email, lets the platform authenticator complete
14
+ * the FIDO2 passkey challenge, then intercepts the skype token from
15
+ * the authenticated network requests.
16
+ *
17
+ * Requirements:
18
+ * - macOS with a FIDO2 platform authenticator (e.g. Intune/Company Portal)
19
+ * - System Chrome installed (or custom chromePath)
20
+ * - playwright package
21
+ */
22
+ export declare function acquireTokenViaAutoLogin(options: AutoLoginOptions): Promise<TeamsToken>;
23
+ //# sourceMappingURL=auto-login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-login.d.ts","sourceRoot":"","sources":["../../src/auth/auto-login.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAiBhE;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA4IrB"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Automatic FIDO2 passkey login for Teams.
4
+ *
5
+ * Launches system Chrome with a fresh profile, completes the Microsoft
6
+ * Entra ID FIDO2 login flow using a platform authenticator, and captures
7
+ * the skype token from network requests. macOS only.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.acquireTokenViaAutoLogin = acquireTokenViaAutoLogin;
11
+ const region_js_1 = require("../region.js");
12
+ const page_diagnostics_js_1 = require("./page-diagnostics.js");
13
+ const token_capture_js_1 = require("./token-capture.js");
14
+ const TEAMS_URL = "https://teams.cloud.microsoft/";
15
+ const DEFAULT_SYSTEM_CHROME_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
16
+ const DEFAULT_PROFILE_DIRECTORY = "/tmp/teams-api-chrome-profile";
17
+ const AUTO_LOGIN_TIMEOUT = 2 * 60 * 1_000;
18
+ const BROWSER_LAUNCH_TIMEOUT = 30 * 1_000;
19
+ /**
20
+ * Acquire a Teams skype token with zero user interaction.
21
+ *
22
+ * Launches system Chrome with a fresh profile, navigates to Teams,
23
+ * enters the corporate email, lets the platform authenticator complete
24
+ * the FIDO2 passkey challenge, then intercepts the skype token from
25
+ * the authenticated network requests.
26
+ *
27
+ * Requirements:
28
+ * - macOS with a FIDO2 platform authenticator (e.g. Intune/Company Portal)
29
+ * - System Chrome installed (or custom chromePath)
30
+ * - playwright package
31
+ */
32
+ async function acquireTokenViaAutoLogin(options) {
33
+ const { chromium } = await import("playwright");
34
+ const chromePath = options.chromePath ?? DEFAULT_SYSTEM_CHROME_PATH;
35
+ const profileDirectory = options.profileDirectory ?? DEFAULT_PROFILE_DIRECTORY;
36
+ const headless = options.headless ?? true;
37
+ const log = options.verbose
38
+ ? console.log.bind(console)
39
+ : () => { };
40
+ // Clean up any previous profile to ensure a fresh session
41
+ const { execSync } = await import("node:child_process");
42
+ execSync(`rm -rf "${profileDirectory}"`);
43
+ log("Launching Chrome with fresh profile...");
44
+ const launchPromise = chromium.launchPersistentContext(profileDirectory, {
45
+ headless,
46
+ executablePath: chromePath,
47
+ args: [
48
+ "--disable-blink-features=AutomationControlled",
49
+ "--disable-features=VirtualAuthenticators",
50
+ "--enable-features=WebAuthenticationMacPlatform",
51
+ "--no-first-run",
52
+ "--no-default-browser-check",
53
+ ],
54
+ ignoreDefaultArgs: ["--disable-component-extensions-with-background-pages"],
55
+ });
56
+ const context = await Promise.race([
57
+ launchPromise,
58
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Chrome launch timed out after ${BROWSER_LAUNCH_TIMEOUT / 1_000}s`)), BROWSER_LAUNCH_TIMEOUT)),
59
+ ]);
60
+ log("Chrome launched successfully");
61
+ try {
62
+ const page = context.pages()[0] || (await context.newPage());
63
+ log("Navigating to Teams...");
64
+ await page.goto(TEAMS_URL, {
65
+ waitUntil: "domcontentloaded",
66
+ timeout: AUTO_LOGIN_TIMEOUT,
67
+ });
68
+ // Wait for Entra ID login page
69
+ log(`Current URL: ${page.url()}`);
70
+ log("Waiting for Entra ID login page...");
71
+ await page
72
+ .waitForURL(/login\.microsoftonline\.com|login\.microsoft\.com/, {
73
+ timeout: AUTO_LOGIN_TIMEOUT,
74
+ })
75
+ .catch(() => {
76
+ log("Did not reach login page (may already be at Teams)");
77
+ });
78
+ // If at the login page, enter email and submit
79
+ if (page.url().includes("login.microsoftonline.com") ||
80
+ page.url().includes("login.microsoft.com")) {
81
+ log("At login page, entering email...");
82
+ const emailInput = await page
83
+ .waitForSelector('#i0116, input[name="loginfmt"], input[type="email"]', { timeout: 15_000 })
84
+ .catch(() => null);
85
+ if (emailInput) {
86
+ await emailInput.fill(options.email);
87
+ const nextButton = await page
88
+ .waitForSelector("#idSIButton9", { timeout: 5_000 })
89
+ .catch(() => null);
90
+ if (nextButton) {
91
+ log("Submitting email...");
92
+ await nextButton.click();
93
+ }
94
+ }
95
+ // Wait for login flow to complete, polling page state for diagnostics
96
+ log("Waiting for authentication to complete...");
97
+ const loginDeadline = Date.now() + AUTO_LOGIN_TIMEOUT;
98
+ while (Date.now() < loginDeadline) {
99
+ const state = await (0, page_diagnostics_js_1.diagnosePageState)(page);
100
+ if (state.phase === "teams-loaded" || state.phase === "teams-loading") {
101
+ log(`Reached Teams: ${state.detail}`);
102
+ break;
103
+ }
104
+ log(`Login progress: ${state.detail}`);
105
+ await new Promise((resolve) => setTimeout(resolve, token_capture_js_1.PAGE_STATE_POLL_INTERVAL));
106
+ }
107
+ // Final check after poll loop
108
+ if (!page.url().includes("teams.cloud.microsoft") &&
109
+ !page.url().includes("teams.microsoft.com")) {
110
+ const state = await (0, page_diagnostics_js_1.diagnosePageState)(page);
111
+ throw new Error(`Login did not complete within ${AUTO_LOGIN_TIMEOUT / 1_000}s. ` +
112
+ `Current state: ${state.phase} — ${state.detail} (URL: ${state.url})`);
113
+ }
114
+ }
115
+ log(`Login flow finished. URL: ${page.url()}`);
116
+ // Capture tokens via shared helper
117
+ log("Capturing tokens...");
118
+ const { skypeToken, region, bearerToken, substrateToken } = await (0, token_capture_js_1.captureTokensFromPage)(page, log, token_capture_js_1.TOKEN_INTERCEPT_TIMEOUT);
119
+ return {
120
+ skypeToken,
121
+ region: (0, region_js_1.resolveTeamsRegion)(options.region, region),
122
+ bearerToken,
123
+ substrateToken,
124
+ };
125
+ }
126
+ finally {
127
+ await context.close();
128
+ try {
129
+ execSync(`rm -rf "${profileDirectory}"`);
130
+ }
131
+ catch {
132
+ // Best-effort cleanup
133
+ }
134
+ }
135
+ }
136
+ //# sourceMappingURL=auto-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-login.js","sourceRoot":"","sources":["../../src/auth/auto-login.ts"],"names":[],"mappings":"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"}