@openclaw/msteams 2026.8.1-beta.3 → 2026.8.2

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 (28) hide show
  1. package/dist/{adapter.runtime-8g-MOPfb.cjs → adapter.runtime-DDuc7sKJ.cjs} +1 -1
  2. package/dist/api.cjs +2 -2
  3. package/dist/approval-card-BEblaIto.cjs +303 -0
  4. package/dist/approval-handler.runtime-C0AWNWXk.cjs +107 -0
  5. package/dist/{channel-KpWENcgK.cjs → channel-DLn4b6Qi.cjs} +168 -53
  6. package/dist/channel-config-api.cjs +1 -1
  7. package/dist/channel-plugin-api.cjs +1 -1
  8. package/dist/{channel.runtime-Bkzj8jZ0.cjs → channel.runtime-1mH99ZAm.cjs} +49 -608
  9. package/dist/{channel.setup-mOFtsfYz.cjs → channel.setup-BRbhaigB.cjs} +29 -18
  10. package/dist/{config-schema-C4CszdDi.cjs → config-schema-MyN2lamA.cjs} +12 -11
  11. package/dist/configured-state.cjs +20 -0
  12. package/dist/directory-contract-api.cjs +1 -1
  13. package/dist/doctor-contract-api.cjs +79 -42
  14. package/dist/{messenger-IISPSOvj.cjs → messenger-flkiAkkB.cjs} +29 -171
  15. package/dist/{oauth-C9So7uld.cjs → oauth-Bctn-WPI.cjs} +4 -3
  16. package/dist/{polls-DvuJvaDG.cjs → polls-P86qBpeV.cjs} +5 -4
  17. package/dist/qa-runner-api.cjs +1 -1
  18. package/dist/reaction-types-CL79V_5D.cjs +150 -0
  19. package/dist/{resolve-allowlist-CIfWUwuc.cjs → resolve-allowlist-BrdWKHE-.cjs} +26 -51
  20. package/dist/{rolldown-runtime-D6vf50IK.cjs → rolldown-runtime-VH7oDXx4.cjs} +1 -1
  21. package/dist/runtime-api.cjs +2 -1
  22. package/dist/secret-input-C65t6kjM.cjs +1 -0
  23. package/dist/send-C4BjzS1F.cjs +631 -0
  24. package/dist/setup-plugin-api.cjs +1 -1
  25. package/dist/{src-C127-DcQ.cjs → src-RSjkJRjI.cjs} +237 -99
  26. package/dist/{sso-token-store-ChhO1f4i.cjs → sso-token-store-CNbRhz-A.cjs} +1 -1
  27. package/dist/thread-session-DxOri69r.cjs +63 -0
  28. package/package.json +13 -11
@@ -1,9 +1,9 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
1
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
2
  const require_runtime = require("./runtime-gZTAuFux.cjs");
3
3
  require("./runtime-api.cjs");
4
- const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
5
- const require_channel_setup = require("./channel.setup-mOFtsfYz.cjs");
6
- const require_polls = require("./polls-DvuJvaDG.cjs");
4
+ const require_resolve_allowlist = require("./resolve-allowlist-BrdWKHE-.cjs");
5
+ const require_channel_setup = require("./channel.setup-BRbhaigB.cjs");
6
+ const require_polls = require("./polls-P86qBpeV.cjs");
7
7
  let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
8
8
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
9
9
  let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
@@ -12,123 +12,17 @@ let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunki
12
12
  let node_dns_promises = require("node:dns/promises");
13
13
  let openclaw_plugin_sdk_ssrf_policy = require("openclaw/plugin-sdk/ssrf-policy");
14
14
  let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text-utility-runtime");
15
- let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
16
15
  let openclaw_plugin_sdk_retry_runtime = require("openclaw/plugin-sdk/retry-runtime");
17
16
  let node_crypto = require("node:crypto");
18
17
  node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
19
18
  let node_path = require("node:path");
20
19
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
20
+ let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
21
21
  let openclaw_plugin_sdk_global_singleton = require("openclaw/plugin-sdk/global-singleton");
22
22
  let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
23
23
  let openclaw_plugin_sdk_reply_chunking = require("openclaw/plugin-sdk/reply-chunking");
24
- let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
25
24
  let openclaw_plugin_sdk_web_media = require("openclaw/plugin-sdk/web-media");
26
25
  let openclaw_plugin_sdk_media_runtime = require("openclaw/plugin-sdk/media-runtime");
27
- //#region extensions/msteams/src/graph-thread.ts
28
- /**
29
- * Strip HTML tags from Teams message content, preserving @mention display names.
30
- * Teams wraps mentions in <at>Name</at> tags.
31
- */
32
- function stripHtmlFromTeamsMessage(html) {
33
- let text = html.replace(/<at[^>]*>(.*?)<\/at>/gi, "@$1");
34
- text = text.replace(/<[^>]*>/g, " ");
35
- text = (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(text).replaceAll("\xA0", " ");
36
- return text.replace(/\s+/g, " ").trim();
37
- }
38
- /**
39
- * Fetch a single channel message (the parent/root of a thread).
40
- * Returns undefined on error so callers can degrade gracefully.
41
- */
42
- async function fetchChannelMessage(token, groupId, channelId, messageId, deadline) {
43
- const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}?$select=id,from,body,createdDateTime`;
44
- try {
45
- return await require_resolve_allowlist.fetchGraphJson({
46
- token,
47
- path,
48
- ...deadline ? { deadline } : {}
49
- });
50
- } catch {
51
- return;
52
- }
53
- }
54
- /**
55
- * Fetch a single chat message's full text via Graph and return plain text.
56
- *
57
- * Used to recover the complete quoted message for Teams quote replies: the
58
- * inbound blockquote only carries a Teams-truncated `preview` snippet. The
59
- * app-only `GET /chats/{chatId}/messages/{messageId}` endpoint IS permitted
60
- * with the `Chat.Read.All` application permission.
61
- *
62
- * Returns undefined on any failure so callers degrade to the truncated preview.
63
- */
64
- async function fetchChatMessageText(token, chatId, messageId, deadline) {
65
- const path = `/chats/${encodeURIComponent(chatId)}/messages/${encodeURIComponent(messageId)}`;
66
- try {
67
- const msg = await require_resolve_allowlist.fetchGraphJson({
68
- token,
69
- path,
70
- ...deadline ? { deadline } : {}
71
- });
72
- const raw = msg.body?.content ?? "";
73
- return (msg.body?.contentType === "html" ? stripHtmlFromTeamsMessage(raw) : raw.trim()) || void 0;
74
- } catch {
75
- return;
76
- }
77
- }
78
- /**
79
- * Fetch thread replies for a channel message, ordered chronologically.
80
- *
81
- * **Limitation:** The Graph API replies endpoint (`/messages/{id}/replies`) does not
82
- * support `$orderby`, so results are always returned in ascending (oldest-first) order.
83
- * Combined with the `$top` cap of 50, this means only the **oldest 50 replies** are
84
- * returned for long threads — newer replies are silently omitted. There is currently no
85
- * Graph API workaround for this; pagination via `@odata.nextLink` can retrieve more
86
- * replies but still in ascending order only.
87
- */
88
- async function fetchThreadReplies(token, groupId, channelId, messageId, limit = 50, deadline) {
89
- return (await require_resolve_allowlist.fetchGraphJson({
90
- token,
91
- path: `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top=${Math.min(Math.max(limit, 1), 50)}&$select=id,from,body,createdDateTime`,
92
- ...deadline ? { deadline } : {}
93
- })).value ?? [];
94
- }
95
- /**
96
- * Format thread messages into a context string for the agent.
97
- * Skips the current message (by id) and blank messages.
98
- */
99
- function formatThreadContext(messages, currentMessageId) {
100
- const lines = [];
101
- for (const msg of messages) {
102
- if (msg.id && msg.id === currentMessageId) continue;
103
- const sender = msg.from?.user?.displayName ?? msg.from?.application?.displayName ?? "unknown";
104
- const contentType = msg.body?.contentType ?? "text";
105
- const rawContent = msg.body?.content ?? "";
106
- const content = contentType === "html" ? stripHtmlFromTeamsMessage(rawContent) : rawContent.trim();
107
- if (!content) continue;
108
- lines.push(`${sender}: ${content}`);
109
- }
110
- return lines.join("\n");
111
- }
112
- //#endregion
113
- //#region extensions/msteams/src/reaction-types.ts
114
- const TEAMS_REACTION_EMOJI = {
115
- like: "👍",
116
- heart: "❤️",
117
- laugh: "😆",
118
- surprised: "😮",
119
- sad: "😢",
120
- angry: "😡"
121
- };
122
- const TEAMS_REACTION_TYPES = Object.keys(TEAMS_REACTION_EMOJI);
123
- function getMSTeamsReactionEmoji(raw) {
124
- return TEAMS_REACTION_EMOJI[raw.trim().toLowerCase()];
125
- }
126
- function resolveMSTeamsReactionEmoji(raw) {
127
- const normalized = raw.trim();
128
- if (!normalized) throw new Error(`Reaction type is required. Common types: ${TEAMS_REACTION_TYPES.join(", ")}`);
129
- return getMSTeamsReactionEmoji(normalized) ?? normalized;
130
- }
131
- //#endregion
132
26
  //#region extensions/msteams/src/file-consent.ts
133
27
  /**
134
28
  * FileConsentCard utilities for MS Teams large file uploads (>4MB) in personal chats.
@@ -267,12 +161,12 @@ async function uploadToConsentUrl(params) {
267
161
  //#endregion
268
162
  //#region extensions/msteams/src/pending-uploads-fs.ts
269
163
  /** TTL for persisted pending uploads (matches in-memory store). */
270
- const PENDING_UPLOAD_TTL_MS$1 = 300 * 1e3;
164
+ const PENDING_UPLOAD_TTL_MS$1 = 3e5;
271
165
  /** Cap to avoid unbounded growth if a process crashes mid-flow. */
272
166
  const MAX_PENDING_UPLOADS = 100;
273
167
  const MAX_CHUNKS_PER_UPLOAD = 3072;
274
168
  const MAX_PENDING_UPLOAD_CHUNK_ROWS = 45e3;
275
- const RAW_CHUNK_BYTES = 36 * 1024;
169
+ const RAW_CHUNK_BYTES = 36864;
276
170
  const PENDING_UPLOAD_META_MAX_ENTRIES = 200;
277
171
  const PENDING_UPLOAD_META_NAMESPACE = "pending-uploads";
278
172
  const PENDING_UPLOAD_CHUNKS_NAMESPACE = "pending-upload-chunks";
@@ -463,7 +357,7 @@ const { pendingUploads, pendingUploadTimers } = (0, openclaw_plugin_sdk_global_s
463
357
  state.pendingUploads.clear();
464
358
  });
465
359
  /** TTL for pending uploads: 5 minutes */
466
- const PENDING_UPLOAD_TTL_MS = 300 * 1e3;
360
+ const PENDING_UPLOAD_TTL_MS = 3e5;
467
361
  /**
468
362
  * Store a file pending user consent.
469
363
  * Returns the upload ID to include in the FileConsentCard context.
@@ -993,14 +887,16 @@ function formatMSTeamsMarkdown(markdown, tableMode) {
993
887
  const mentions = [];
994
888
  const entities = [];
995
889
  const tokenPrefix = createTokenPrefix(markdown, "msteamsformat");
996
- const tableInput = (0, openclaw_plugin_sdk_text_chunking.convertMarkdownTables)(protectMSTeamsMentions(protectMarkdownImages(markdown.replace(MARKDOWN_ENTITY_RE, (entity) => {
890
+ const mentionsProtected = protectMSTeamsMentions(protectMarkdownImages(markdown.replace(MARKDOWN_ENTITY_RE, (entity) => {
997
891
  const index = entities.push(entity) - 1;
998
892
  return `${tokenPrefix}h${index}${TOKEN_END}`;
999
- }), tokenPrefix, images), tokenPrefix, mentions), tableMode);
1000
- let restored = restoreTokens((0, openclaw_plugin_sdk_text_chunking.renderMarkdownWithMarkers)(prefixMSTeamsBlockquotes(protectMSTeamsCode((0, openclaw_plugin_sdk_text_chunking.markdownToIR)((tableMode === "off" ? protectRawTablesOutsideFences(tableInput, tokenPrefix, rawTables) : tableInput).replace(ESCAPED_MARKDOWN_RE, (escaped) => {
893
+ }), tokenPrefix, images), tokenPrefix, mentions);
894
+ const tableInput = (0, openclaw_plugin_sdk_text_chunking.convertMarkdownTables)(mentionsProtected, tableMode);
895
+ const protectedMarkdown = (tableMode === "off" ? protectRawTablesOutsideFences(tableInput, tokenPrefix, rawTables) : tableInput).replace(ESCAPED_MARKDOWN_RE, (escaped) => {
1001
896
  const index = escapedMarkdown.push(escaped) - 1;
1002
897
  return `${tokenPrefix}e${index}${TOKEN_END}`;
1003
- }), {
898
+ });
899
+ const ir = prefixMSTeamsBlockquotes(protectMSTeamsCode((0, openclaw_plugin_sdk_text_chunking.markdownToIR)(protectedMarkdown, {
1004
900
  autolink: false,
1005
901
  enableSpoilers: true,
1006
902
  enableTaskLists: true,
@@ -1028,7 +924,8 @@ function formatMSTeamsMarkdown(markdown, tableMode) {
1028
924
  prefix: `${tokenPrefix}h`,
1029
925
  values: entities
1030
926
  }
1031
- ])), {
927
+ ]));
928
+ let restored = restoreTokens((0, openclaw_plugin_sdk_text_chunking.renderMarkdownWithMarkers)(ir, {
1032
929
  styleMarkers: MSTEAMS_MARKERS,
1033
930
  escapeText: (text) => text,
1034
931
  buildLink: (link) => ({
@@ -1174,7 +1071,10 @@ async function getChatMembers(params) {
1174
1071
  },
1175
1072
  signal
1176
1073
  });
1177
- if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, res.status === 403 ? "Get chat members failed; verify Graph chat-member permissions and tenant access policies" : "Get chat members failed");
1074
+ if (!res.ok) {
1075
+ const message = res.status === 403 ? "Get chat members failed; verify Graph chat-member permissions and tenant access policies" : "Get chat members failed";
1076
+ throw await require_resolve_allowlist.createMSTeamsHttpError(res, message);
1077
+ }
1178
1078
  return ((await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getChatMembers")).value ?? []).map((member) => ({ aadObjectId: member.userId ?? "" })).filter((member) => member.aadObjectId);
1179
1079
  }
1180
1080
  });
@@ -1394,10 +1294,9 @@ async function withRevokedProxyFallback(params) {
1394
1294
  }
1395
1295
  //#endregion
1396
1296
  //#region extensions/msteams/src/sdk-proactive.ts
1397
- const loadMSTeamsApiClient = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api").then((api) => ({ Client: api.Client })));
1398
- const loadMSTeamsQuoteModule = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api/dist/activities/message/message.js").then((message) => ({ MessageActivityInput: message.MessageActivityInput })));
1297
+ const loadMSTeamsApiModule = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api"));
1399
1298
  async function quoteMSTeamsActivity(activity, messageId) {
1400
- const { MessageActivityInput } = await loadMSTeamsQuoteModule();
1299
+ const { MessageActivityInput } = await loadMSTeamsApiModule();
1401
1300
  if (typeof activity === "string") return new MessageActivityInput(activity).prependQuote(messageId);
1402
1301
  if (activity.type !== "message") return activity;
1403
1302
  return MessageActivityInput.from(activity).prependQuote(messageId);
@@ -1466,7 +1365,7 @@ async function getApiClientForReference(app, ref) {
1466
1365
  const appInternals = app;
1467
1366
  const httpClient = appInternals.api?.http ?? appInternals.client;
1468
1367
  if (!httpClient) return api;
1469
- const { Client } = await loadMSTeamsApiClient();
1368
+ const { Client } = await loadMSTeamsApiModule();
1470
1369
  return new Client(ref.serviceUrl, httpClient);
1471
1370
  }
1472
1371
  function mergeReferenceIntoActivity(activity, ref) {
@@ -1530,12 +1429,12 @@ async function deleteMSTeamsActivityWithReference(app, source, activityId, optio
1530
1429
  * MSTeams-specific media size limit (100MB).
1531
1430
  * Higher than the default to support Teams file-consent and SharePoint uploads.
1532
1431
  */
1533
- const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
1432
+ const MSTEAMS_MAX_MEDIA_BYTES = 104857600;
1534
1433
  /**
1535
1434
  * Threshold for large files that require FileConsentCard flow in personal chats.
1536
1435
  * Files >= 4MB use consent flow; smaller images can use inline base64.
1537
1436
  */
1538
- const FILE_CONSENT_THRESHOLD_BYTES = 4 * 1024 * 1024;
1437
+ const FILE_CONSENT_THRESHOLD_BYTES = 4194304;
1539
1438
  function normalizeConversationId(rawId) {
1540
1439
  return rawId.split(";")[0] ?? rawId;
1541
1440
  }
@@ -1747,13 +1646,14 @@ async function sendMSTeamsMessages(params) {
1747
1646
  };
1748
1647
  let providerDispatchStarted = false;
1749
1648
  const sendMessageInContext = async (sendFn, message, messageIndex) => {
1649
+ let activity;
1750
1650
  let pendingUploadId;
1751
1651
  let response;
1752
1652
  try {
1753
1653
  response = await sendWithRetry(async () => {
1754
- const activity = await buildActivity(message, params.conversationRef, params.tokenProvider, params.sharePointSiteId, params.mediaMaxBytes, { feedbackLoopEnabled: params.feedbackLoopEnabled });
1755
- pendingUploadId = typeof activity["_pendingUploadId"] === "string" ? activity["_pendingUploadId"] : void 0;
1756
- if (pendingUploadId) delete activity["_pendingUploadId"];
1654
+ activity ??= await buildActivity(message, params.conversationRef, params.tokenProvider, params.sharePointSiteId, params.mediaMaxBytes, { feedbackLoopEnabled: params.feedbackLoopEnabled });
1655
+ pendingUploadId ??= typeof activity["_pendingUploadId"] === "string" ? activity["_pendingUploadId"] : void 0;
1656
+ delete activity["_pendingUploadId"];
1757
1657
  providerDispatchStarted = true;
1758
1658
  return await sendFn(activity);
1759
1659
  }, {
@@ -1852,48 +1752,18 @@ Object.defineProperty(exports, "extractMessageId", {
1852
1752
  return extractMessageId;
1853
1753
  }
1854
1754
  });
1855
- Object.defineProperty(exports, "fetchChannelMessage", {
1856
- enumerable: true,
1857
- get: function() {
1858
- return fetchChannelMessage;
1859
- }
1860
- });
1861
- Object.defineProperty(exports, "fetchChatMessageText", {
1862
- enumerable: true,
1863
- get: function() {
1864
- return fetchChatMessageText;
1865
- }
1866
- });
1867
- Object.defineProperty(exports, "fetchThreadReplies", {
1868
- enumerable: true,
1869
- get: function() {
1870
- return fetchThreadReplies;
1871
- }
1872
- });
1873
1755
  Object.defineProperty(exports, "formatMSTeamsMarkdown", {
1874
1756
  enumerable: true,
1875
1757
  get: function() {
1876
1758
  return formatMSTeamsMarkdown;
1877
1759
  }
1878
1760
  });
1879
- Object.defineProperty(exports, "formatThreadContext", {
1880
- enumerable: true,
1881
- get: function() {
1882
- return formatThreadContext;
1883
- }
1884
- });
1885
1761
  Object.defineProperty(exports, "getDriveItemProperties", {
1886
1762
  enumerable: true,
1887
1763
  get: function() {
1888
1764
  return getDriveItemProperties;
1889
1765
  }
1890
1766
  });
1891
- Object.defineProperty(exports, "getMSTeamsReactionEmoji", {
1892
- enumerable: true,
1893
- get: function() {
1894
- return getMSTeamsReactionEmoji;
1895
- }
1896
- });
1897
1767
  Object.defineProperty(exports, "getPendingUpload", {
1898
1768
  enumerable: true,
1899
1769
  get: function() {
@@ -1948,12 +1818,6 @@ Object.defineProperty(exports, "requiresFileConsent", {
1948
1818
  return requiresFileConsent;
1949
1819
  }
1950
1820
  });
1951
- Object.defineProperty(exports, "resolveMSTeamsReactionEmoji", {
1952
- enumerable: true,
1953
- get: function() {
1954
- return resolveMSTeamsReactionEmoji;
1955
- }
1956
- });
1957
1821
  Object.defineProperty(exports, "sendMSTeamsActivityWithReference", {
1958
1822
  enumerable: true,
1959
1823
  get: function() {
@@ -1978,12 +1842,6 @@ Object.defineProperty(exports, "setPendingUploadActivityIdFs", {
1978
1842
  return setPendingUploadActivityIdFs;
1979
1843
  }
1980
1844
  });
1981
- Object.defineProperty(exports, "stripHtmlFromTeamsMessage", {
1982
- enumerable: true,
1983
- get: function() {
1984
- return stripHtmlFromTeamsMessage;
1985
- }
1986
- });
1987
1845
  Object.defineProperty(exports, "updateMSTeamsActivityWithReference", {
1988
1846
  enumerable: true,
1989
1847
  get: function() {
@@ -1,4 +1,4 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-BrdWKHE-.cjs");
2
2
  let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
3
3
  let openclaw_plugin_sdk_provider_auth = require("openclaw/plugin-sdk/provider-auth");
4
4
  let openclaw_plugin_sdk_provider_auth_runtime = require("openclaw/plugin-sdk/provider-auth-runtime");
@@ -52,7 +52,7 @@ async function loginMSTeamsDelegated(ctx, params) {
52
52
  try {
53
53
  const { code } = await (0, openclaw_plugin_sdk_provider_auth_runtime.waitForLocalOAuthCallback)({
54
54
  expectedState: state,
55
- timeoutMs: 300 * 1e3,
55
+ timeoutMs: 3e5,
56
56
  port: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT,
57
57
  callbackPath: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PATH,
58
58
  redirectUri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
@@ -81,7 +81,8 @@ async function manualFlow(ctx, authUrl, state, verifier, params, cause) {
81
81
  ctx.progress.update("OAuth URL ready");
82
82
  ctx.log(`\nOpen this URL in your LOCAL browser:\n\n${authUrl}\n`);
83
83
  ctx.progress.update("Waiting for you to paste the callback URL...");
84
- const parsed = (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(await ctx.prompt("Paste the redirect URL here: "), {
84
+ const callbackInput = await ctx.prompt("Paste the redirect URL here: ");
85
+ const parsed = (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(callbackInput, {
85
86
  missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
86
87
  invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
87
88
  });
@@ -1,4 +1,4 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
1
+ const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
2
  const require_runtime = require("./runtime-gZTAuFux.cjs");
3
3
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
4
4
  let openclaw_plugin_sdk_file_lock = require("openclaw/plugin-sdk/file-lock");
@@ -96,7 +96,7 @@ const MSTEAMS_CONVERSATIONS_LEGACY_FILENAME = "msteams-conversations.json";
96
96
  const MSTEAMS_CONVERSATIONS_NAMESPACE = "conversations";
97
97
  const MSTEAMS_MAX_CONVERSATIONS = 1e3;
98
98
  const MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS = 2e3;
99
- const MSTEAMS_CONVERSATION_TTL_MS = 365 * 24 * 60 * 60 * 1e3;
99
+ const MSTEAMS_CONVERSATION_TTL_MS = 31536e6;
100
100
  const CONVERSATION_MUTATION_KEY = "conversations";
101
101
  function createConversationStateStore(params) {
102
102
  return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
@@ -226,7 +226,7 @@ const MSTEAMS_MAX_POLLS = 1e3;
226
226
  const MSTEAMS_SQLITE_MAX_POLL_ROWS = 2e3;
227
227
  const MSTEAMS_POLL_VOTE_BUCKET_COUNT = 32;
228
228
  const MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS = 1001 * MSTEAMS_POLL_VOTE_BUCKET_COUNT;
229
- const MSTEAMS_POLL_TTL_MS = 720 * 60 * 60 * 1e3;
229
+ const MSTEAMS_POLL_TTL_MS = 2592e6;
230
230
  const POLL_MUTATION_KEY = "polls";
231
231
  function normalizeChoiceValue(value) {
232
232
  if (typeof value === "string") {
@@ -379,7 +379,8 @@ function selectRetainedMSTeamsPolls(polls) {
379
379
  }
380
380
  function normalizeMSTeamsPollSelections(poll, selections) {
381
381
  const maxSelections = Math.max(1, poll.maxSelections);
382
- return (0, openclaw_plugin_sdk_string_coerce_runtime.uniqueStrings)(selections.map((entry) => (0, openclaw_plugin_sdk_number_runtime.parseStrictNonNegativeInteger)(entry)).filter((value) => value !== void 0).filter((value) => value >= 0 && value < poll.options.length).map((value) => String(value))).slice(0, maxSelections);
382
+ const mapped = selections.map((entry) => (0, openclaw_plugin_sdk_number_runtime.parseStrictNonNegativeInteger)(entry)).filter((value) => value !== void 0).filter((value) => value >= 0 && value < poll.options.length).map((value) => String(value));
383
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.uniqueStrings)(mapped).slice(0, maxSelections);
383
384
  }
384
385
  function splitMSTeamsPoll(poll) {
385
386
  const { votes, ...metadata } = poll;
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let openclaw_plugin_sdk_qa_runner_runtime = require("openclaw/plugin-sdk/qa-runner-runtime");
3
3
  //#region extensions/msteams/src/qa/cli.ts
4
4
  const DEFAULT_MSTEAMS_QA_SCENARIOS = ["channel-canary"];
5
- const loadMSTeamsQaAdapterRuntime = (0, openclaw_plugin_sdk_qa_runner_runtime.createLazyCliRuntimeLoader)(() => Promise.resolve().then(() => require("./adapter.runtime-8g-MOPfb.cjs")));
5
+ const loadMSTeamsQaAdapterRuntime = (0, openclaw_plugin_sdk_qa_runner_runtime.createLazyCliRuntimeLoader)(() => Promise.resolve().then(() => require("./adapter.runtime-DDuc7sKJ.cjs")));
6
6
  async function runQaMSTeams(options) {
7
7
  await (0, openclaw_plugin_sdk_qa_runner_runtime.runLiveTransportQaSuiteCommand)({
8
8
  channelId: "msteams",
@@ -0,0 +1,150 @@
1
+ const require_resolve_allowlist = require("./resolve-allowlist-BrdWKHE-.cjs");
2
+ let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
3
+ //#region extensions/msteams/src/graph-thread.ts
4
+ /**
5
+ * Strip HTML tags from Teams message content, preserving @mention display names.
6
+ * Teams wraps mentions in <at>Name</at> tags.
7
+ */
8
+ function stripHtmlFromTeamsMessage(html) {
9
+ let text = html.replace(/<at[^>]*>(.*?)<\/at>/gi, "@$1");
10
+ text = text.replace(/<[^>]*>/g, " ");
11
+ text = (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(text).replaceAll("\xA0", " ");
12
+ return text.replace(/\s+/g, " ").trim();
13
+ }
14
+ /**
15
+ * Fetch a single channel message (the parent/root of a thread).
16
+ * Returns undefined on error so callers can degrade gracefully.
17
+ */
18
+ async function fetchChannelMessage(token, groupId, channelId, messageId, deadline) {
19
+ const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}`;
20
+ try {
21
+ return await require_resolve_allowlist.fetchGraphJson({
22
+ token,
23
+ path,
24
+ ...deadline ? { deadline } : {}
25
+ });
26
+ } catch {
27
+ return;
28
+ }
29
+ }
30
+ /**
31
+ * Fetch a single chat message's full text via Graph and return plain text.
32
+ *
33
+ * Used to recover the complete quoted message for Teams quote replies: the
34
+ * inbound blockquote only carries a Teams-truncated `preview` snippet. The
35
+ * app-only `GET /chats/{chatId}/messages/{messageId}` endpoint IS permitted
36
+ * with the `Chat.Read.All` application permission.
37
+ *
38
+ * Returns undefined on any failure so callers degrade to the truncated preview.
39
+ */
40
+ async function fetchChatMessageText(token, chatId, messageId, deadline) {
41
+ const path = `/chats/${encodeURIComponent(chatId)}/messages/${encodeURIComponent(messageId)}`;
42
+ try {
43
+ const msg = await require_resolve_allowlist.fetchGraphJson({
44
+ token,
45
+ path,
46
+ ...deadline ? { deadline } : {}
47
+ });
48
+ const raw = msg.body?.content ?? "";
49
+ return (msg.body?.contentType === "html" ? stripHtmlFromTeamsMessage(raw) : raw.trim()) || void 0;
50
+ } catch {
51
+ return;
52
+ }
53
+ }
54
+ /**
55
+ * Fetch thread replies for a channel message, ordered chronologically.
56
+ *
57
+ * **Limitation:** The Graph API replies endpoint (`/messages/{id}/replies`) does not
58
+ * support `$orderby`, so results are always returned in ascending (oldest-first) order.
59
+ * Combined with the `$top` cap of 50, this means only the **oldest 50 replies** are
60
+ * returned for long threads — newer replies are silently omitted. There is currently no
61
+ * Graph API workaround for this; pagination via `@odata.nextLink` can retrieve more
62
+ * replies but still in ascending order only.
63
+ */
64
+ async function fetchThreadReplies(token, groupId, channelId, messageId, limit = 50, deadline) {
65
+ const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top=${Math.min(Math.max(limit, 1), 50)}`;
66
+ return (await require_resolve_allowlist.fetchGraphJson({
67
+ token,
68
+ path,
69
+ ...deadline ? { deadline } : {}
70
+ })).value ?? [];
71
+ }
72
+ /**
73
+ * Format thread messages into a context string for the agent.
74
+ * Skips the current message (by id) and blank messages.
75
+ */
76
+ function formatThreadContext(messages, currentMessageId) {
77
+ const lines = [];
78
+ for (const msg of messages) {
79
+ if (msg.id && msg.id === currentMessageId) continue;
80
+ const sender = msg.from?.user?.displayName ?? msg.from?.application?.displayName ?? "unknown";
81
+ const contentType = msg.body?.contentType ?? "text";
82
+ const rawContent = msg.body?.content ?? "";
83
+ const content = contentType === "html" ? stripHtmlFromTeamsMessage(rawContent) : rawContent.trim();
84
+ if (!content) continue;
85
+ lines.push(`${sender}: ${content}`);
86
+ }
87
+ return lines.join("\n");
88
+ }
89
+ //#endregion
90
+ //#region extensions/msteams/src/reaction-types.ts
91
+ const TEAMS_REACTION_EMOJI = {
92
+ like: "👍",
93
+ heart: "❤️",
94
+ laugh: "😆",
95
+ surprised: "😮",
96
+ sad: "😢",
97
+ angry: "😡"
98
+ };
99
+ const TEAMS_REACTION_TYPES = Object.keys(TEAMS_REACTION_EMOJI);
100
+ function getMSTeamsReactionEmoji(raw) {
101
+ return TEAMS_REACTION_EMOJI[raw.trim().toLowerCase()];
102
+ }
103
+ function resolveMSTeamsReactionEmoji(raw) {
104
+ const normalized = raw.trim();
105
+ if (!normalized) throw new Error(`Reaction type is required. Common types: ${TEAMS_REACTION_TYPES.join(", ")}`);
106
+ return getMSTeamsReactionEmoji(normalized) ?? normalized;
107
+ }
108
+ //#endregion
109
+ Object.defineProperty(exports, "fetchChannelMessage", {
110
+ enumerable: true,
111
+ get: function() {
112
+ return fetchChannelMessage;
113
+ }
114
+ });
115
+ Object.defineProperty(exports, "fetchChatMessageText", {
116
+ enumerable: true,
117
+ get: function() {
118
+ return fetchChatMessageText;
119
+ }
120
+ });
121
+ Object.defineProperty(exports, "fetchThreadReplies", {
122
+ enumerable: true,
123
+ get: function() {
124
+ return fetchThreadReplies;
125
+ }
126
+ });
127
+ Object.defineProperty(exports, "formatThreadContext", {
128
+ enumerable: true,
129
+ get: function() {
130
+ return formatThreadContext;
131
+ }
132
+ });
133
+ Object.defineProperty(exports, "getMSTeamsReactionEmoji", {
134
+ enumerable: true,
135
+ get: function() {
136
+ return getMSTeamsReactionEmoji;
137
+ }
138
+ });
139
+ Object.defineProperty(exports, "resolveMSTeamsReactionEmoji", {
140
+ enumerable: true,
141
+ get: function() {
142
+ return resolveMSTeamsReactionEmoji;
143
+ }
144
+ });
145
+ Object.defineProperty(exports, "stripHtmlFromTeamsMessage", {
146
+ enumerable: true,
147
+ get: function() {
148
+ return stripHtmlFromTeamsMessage;
149
+ }
150
+ });