@openclaw/msteams 2026.5.28-beta.1 → 2026.5.28-beta.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.
package/dist/api.js CHANGED
@@ -1,3 +1,3 @@
1
- import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-Byk8kgPH.js";
2
- import { t as msteamsPlugin } from "./channel-C4ifQ0RF.js";
1
+ import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-C-uCiIKh.js";
2
+ import { t as msteamsPlugin } from "./channel-C_AMaSpi.js";
3
3
  export { createMSTeamsSetupWizardBase, msteamsPlugin, msteamsSetupAdapter, msteamsSetupWizard, openDelegatedOAuthUrl };
@@ -1,6 +1,6 @@
1
1
  import { O as resolveNestedAllowlistDecision, S as normalizeChannelSlug, T as resolveChannelEntryMatchWithFallback, _ as isDangerousNameMatchingEnabled, i as buildChannelKeyCandidates, k as resolveToolsBySender, o as buildProbeChannelStatusSummary, r as PAIRING_APPROVED_MESSAGE, s as chunkTextForOutbound, t as DEFAULT_ACCOUNT_ID, u as createDefaultChannelRuntimeState, w as resolveAllowlistMatchSimple } from "./runtime-api-BlvMnDKz.js";
2
- import { y as resolveMSTeamsCredentials } from "./errors-BevpsEsu.js";
3
- import { a as looksLikeMSTeamsTargetId, c as parseMSTeamsConversationId, d as resolveMSTeamsUserAllowlist, i as msteamsSetupAdapter, l as parseMSTeamsTeamChannelInput, o as normalizeMSTeamsMessagingTarget, s as normalizeMSTeamsUserInput, t as msteamsSetupWizard, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-Byk8kgPH.js";
2
+ import { y as resolveMSTeamsCredentials } from "./errors-B4snzfP5.js";
3
+ import { a as looksLikeMSTeamsTargetId, c as parseMSTeamsConversationId, d as resolveMSTeamsUserAllowlist, i as msteamsSetupAdapter, l as parseMSTeamsTeamChannelInput, o as normalizeMSTeamsMessagingTarget, s as normalizeMSTeamsUserInput, t as msteamsSetupWizard, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-C-uCiIKh.js";
4
4
  import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
5
5
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
6
6
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
@@ -330,7 +330,7 @@ const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarning
330
330
  resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
331
331
  collect: ({ groupPolicy }) => groupPolicy === "open" ? ["- MS Teams groups: groupPolicy=\"open\" allows any member to trigger (mention-gated). Set channels.msteams.groupPolicy=\"allowlist\" + channels.msteams.groupAllowFrom to restrict senders."] : []
332
332
  });
333
- const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-Cl_OVKBH.js"), "msTeamsChannelRuntime");
333
+ const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BJJ1R1iY.js"), "msTeamsChannelRuntime");
334
334
  const resolveMSTeamsChannelConfig = (cfg) => ({
335
335
  allowFrom: cfg.channels?.msteams?.allowFrom,
336
336
  defaultTo: cfg.channels?.msteams?.defaultTo
@@ -1116,7 +1116,7 @@ const msteamsPlugin = createChatChannelPlugin({
1116
1116
  })
1117
1117
  }),
1118
1118
  gateway: { startAccount: async (ctx) => {
1119
- const { monitorMSTeamsProvider } = await import("./src-W5GVJcCN.js");
1119
+ const { monitorMSTeamsProvider } = await import("./src-Cc3f8Zi2.js");
1120
1120
  const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1121
1121
  ctx.setStatus({
1122
1122
  accountId: ctx.accountId,
@@ -1,2 +1,2 @@
1
- import { t as msteamsPlugin } from "./channel-C4ifQ0RF.js";
1
+ import { t as msteamsPlugin } from "./channel-C_AMaSpi.js";
2
2
  export { msteamsPlugin };
@@ -1,7 +1,7 @@
1
1
  import { C as normalizeStringEntries$1, s as chunkTextForOutbound } from "./runtime-api-BlvMnDKz.js";
2
- import { a as searchGraphUsers, c as fetchGraphAbsoluteUrl, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, h as postGraphJson, l as fetchGraphJson, m as postGraphBetaJson, o as deleteGraphRequest, p as patchGraphJson, s as escapeOData, u as listChannelsForTeam } from "./errors-BevpsEsu.js";
3
- import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel-C4ifQ0RF.js";
4
- import { S as createMSTeamsConversationStoreFs, a as sendMessageMSTeams, b as createMSTeamsPollStoreFs, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-C9cvgEV9.js";
2
+ import { a as searchGraphUsers, c as fetchGraphAbsoluteUrl, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, h as postGraphJson, l as fetchGraphJson, m as postGraphBetaJson, o as deleteGraphRequest, p as patchGraphJson, s as escapeOData, u as listChannelsForTeam } from "./errors-B4snzfP5.js";
3
+ import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel-C_AMaSpi.js";
4
+ import { S as createMSTeamsConversationStoreFs, a as sendMessageMSTeams, b as createMSTeamsPollStoreFs, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-DRwI-ZqW.js";
5
5
  import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
6
6
  import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { resolvePayloadMediaUrls, resolveTextChunksWithFallback, sendPayloadMediaSequence } from "openclaw/plugin-sdk/reply-payload";
@@ -1,7 +1,8 @@
1
- import { M as getMSTeamsRuntime, h as fetchWithSsrFGuard } from "./runtime-api-BlvMnDKz.js";
1
+ import { M as getMSTeamsRuntime, h as fetchWithSsrFGuard$1 } from "./runtime-api-BlvMnDKz.js";
2
2
  import { c as createMSTeamsHttpError, n as refreshMSTeamsDelegatedTokens } from "./oauth.token-5ygi8ycy.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { isRecord, isRecord as isRecord$1, normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
5
6
  import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
6
7
  import { Buffer } from "node:buffer";
7
8
  import { lookup } from "node:dns/promises";
@@ -292,6 +293,20 @@ function resolveAllowedHosts(input) {
292
293
  function resolveAuthAllowedHosts(input) {
293
294
  return normalizeHostnameSuffixAllowlist(input, DEFAULT_MEDIA_AUTH_HOST_ALLOWLIST);
294
295
  }
296
+ function isMockFetchFn(fetchFn) {
297
+ const candidate = fetchFn;
298
+ return Boolean(candidate.mock || Object.prototype.hasOwnProperty.call(candidate, "_isMockFunction"));
299
+ }
300
+ function resolveGuardedFetchImpl(params) {
301
+ if (!params.fetchFn) return;
302
+ if (params.fetchFnSupportsDispatcher === true || params.fetchFn === fetch || params.fetchFn === globalThis.fetch || isMockFetchFn(params.fetchFn)) return params.fetchFn;
303
+ throw new Error("MSTeams attachment fetchFn must set fetchFnSupportsDispatcher to use guarded DNS pinning");
304
+ }
305
+ function resolveRetainedAuthorizationRedirectHostnameAllowlist(input) {
306
+ if (!input) return;
307
+ if (input.includes("*")) return ["*"];
308
+ return resolveMediaSsrfPolicy(input)?.hostnameAllowlist;
309
+ }
295
310
  function resolveAttachmentFetchPolicy(params) {
296
311
  return {
297
312
  allowHosts: resolveAllowedHosts(params?.allowHosts),
@@ -341,6 +356,50 @@ async function resolveAndValidateIP(hostname, resolveFn) {
341
356
  }
342
357
  /** Maximum number of redirects to follow in safeFetch. */
343
358
  const MAX_SAFE_REDIRECTS = 5;
359
+ const NULL_BODY_STATUSES$1 = new Set([
360
+ 101,
361
+ 204,
362
+ 205,
363
+ 304
364
+ ]);
365
+ function responseWithRelease(response, release) {
366
+ let released = false;
367
+ const releaseOnce = async () => {
368
+ if (released) return;
369
+ released = true;
370
+ await release();
371
+ };
372
+ if (!response.body || NULL_BODY_STATUSES$1.has(response.status)) {
373
+ releaseOnce();
374
+ return response;
375
+ }
376
+ const reader = response.body.getReader();
377
+ const body = new ReadableStream({
378
+ async pull(controller) {
379
+ try {
380
+ const next = await reader.read();
381
+ if (next.done) {
382
+ controller.close();
383
+ await releaseOnce();
384
+ return;
385
+ }
386
+ controller.enqueue(next.value);
387
+ } catch (err) {
388
+ await releaseOnce();
389
+ throw err;
390
+ }
391
+ },
392
+ async cancel(reason) {
393
+ reader.cancel(reason).catch(() => {});
394
+ await releaseOnce();
395
+ }
396
+ });
397
+ return new Response(body, {
398
+ status: response.status,
399
+ statusText: response.statusText,
400
+ headers: response.headers
401
+ });
402
+ }
344
403
  /**
345
404
  * Fetch a URL with redirect: "manual", validating each redirect target
346
405
  * against the hostname allowlist and optional DNS-resolved IP (anti-SSRF).
@@ -350,13 +409,32 @@ const MAX_SAFE_REDIRECTS = 5;
350
409
  * - DNS rebinding attacks when a lookup function is provided
351
410
  */
352
411
  async function safeFetch(params) {
353
- const fetchFn = params.fetchFn ?? fetch;
354
412
  const resolveFn = params.resolveFn ?? lookup;
355
413
  const hasDispatcher = Boolean(params.requestInit && typeof params.requestInit === "object" && "dispatcher" in params.requestInit);
356
414
  const currentHeaders = new Headers(params.requestInit?.headers);
357
415
  let currentUrl = params.url;
358
416
  if (!isUrlAllowed(currentUrl, params.allowHosts)) throw new Error(`Initial download URL blocked: ${currentUrl}`);
359
417
  if (currentHeaders.has("authorization") && params.authorizationAllowHosts && !isUrlAllowed(currentUrl, params.authorizationAllowHosts)) currentHeaders.delete("authorization");
418
+ if (!hasDispatcher) {
419
+ const guarded = await fetchWithSsrFGuard({
420
+ url: currentUrl,
421
+ fetchImpl: resolveGuardedFetchImpl({
422
+ fetchFn: params.fetchFn,
423
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher
424
+ }),
425
+ init: {
426
+ ...params.requestInit,
427
+ headers: currentHeaders
428
+ },
429
+ maxRedirects: MAX_SAFE_REDIRECTS,
430
+ requireHttps: true,
431
+ policy: resolveMediaSsrfPolicy(params.allowHosts),
432
+ lookupFn: resolveFn,
433
+ retainAuthorizationRedirectHostnameAllowlist: resolveRetainedAuthorizationRedirectHostnameAllowlist(params.authorizationAllowHosts),
434
+ auditContext: "msteams.attachment"
435
+ });
436
+ return responseWithRelease(guarded.response, guarded.release);
437
+ }
360
438
  if (resolveFn) try {
361
439
  const initialHost = new URL(currentUrl).hostname;
362
440
  await resolveAndValidateIP(initialHost, resolveFn);
@@ -364,7 +442,7 @@ async function safeFetch(params) {
364
442
  throw new Error(`Initial download URL blocked: ${currentUrl}`);
365
443
  }
366
444
  for (let i = 0; i <= MAX_SAFE_REDIRECTS; i++) {
367
- const res = await fetchFn(currentUrl, {
445
+ const res = await (params.fetchFn ?? fetch)(currentUrl, {
368
446
  ...params.requestInit,
369
447
  headers: currentHeaders,
370
448
  redirect: "manual"
@@ -401,6 +479,7 @@ async function safeFetchWithPolicy(params) {
401
479
  allowHosts: params.policy.allowHosts,
402
480
  authorizationAllowHosts: params.policy.authAllowHosts,
403
481
  fetchFn: params.fetchFn,
482
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
404
483
  requestInit: params.requestInit,
405
484
  resolveFn: params.resolveFn
406
485
  });
@@ -761,7 +840,7 @@ async function requestGraph(params) {
761
840
  const hasBody = params.body !== void 0;
762
841
  const url = `${params.root ?? "https://graph.microsoft.com/v1.0"}${params.path}`;
763
842
  const currentFetch = globalThis.fetch;
764
- const { response, release } = await fetchWithSsrFGuard({
843
+ const { response, release } = await fetchWithSsrFGuard$1({
765
844
  url,
766
845
  fetchImpl: async (input, guardedInit) => await currentFetch(input, guardedInit),
767
846
  init: {
@@ -806,7 +885,7 @@ async function fetchGraphJson(params) {
806
885
  * pagination URLs) without prepending GRAPH_ROOT.
807
886
  */
808
887
  async function fetchGraphAbsoluteUrl(params) {
809
- const { response, release } = await fetchWithSsrFGuard({
888
+ const { response, release } = await fetchWithSsrFGuard$1({
810
889
  url: params.url,
811
890
  init: { headers: {
812
891
  "User-Agent": buildUserAgent(),
@@ -1,7 +1,7 @@
1
1
  import { C as normalizeStringEntries$1, E as resolveChannelMediaMaxBytes, M as getMSTeamsRuntime, d as detectMime, g as getFileExtension, m as extractOriginalFilename, p as extensionForMime, y as loadOutboundMediaFromUrl } from "./runtime-api-BlvMnDKz.js";
2
- import { A as isAllowedBotFrameworkServiceUrl, C as readAccessToken, D as buildUserAgent, E as loadMSTeamsSdkWithAuth, N as resolveMSTeamsSdkCloudOptions, P as validateMSTeamsProactiveServiceUrlBoundary, T as createMSTeamsTokenProvider, i as isRevokedProxyError, j as normalizeBotFrameworkServiceUrl, k as describeBotFrameworkServiceUrlHost, n as formatMSTeamsSendErrorHint, r as formatUnknownError, t as classifyMSTeamsSendError, v as loadDelegatedTokens, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials } from "./errors-BevpsEsu.js";
2
+ import { A as isAllowedBotFrameworkServiceUrl, C as readAccessToken, D as buildUserAgent, E as loadMSTeamsSdkWithAuth, N as resolveMSTeamsSdkCloudOptions, P as validateMSTeamsProactiveServiceUrlBoundary, T as createMSTeamsTokenProvider, i as isRevokedProxyError, j as normalizeBotFrameworkServiceUrl, k as describeBotFrameworkServiceUrlHost, n as formatMSTeamsSendErrorHint, r as formatUnknownError, t as classifyMSTeamsSendError, v as loadDelegatedTokens, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials } from "./errors-B4snzfP5.js";
3
3
  import { c as createMSTeamsHttpError } from "./oauth.token-5ygi8ycy.js";
4
- import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-C4ifQ0RF.js";
4
+ import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-C_AMaSpi.js";
5
5
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
6
6
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { withFileLock } from "openclaw/plugin-sdk/file-lock";
@@ -1,5 +1,5 @@
1
- import { y as resolveMSTeamsCredentials } from "./errors-BevpsEsu.js";
2
- import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-Byk8kgPH.js";
1
+ import { y as resolveMSTeamsCredentials } from "./errors-B4snzfP5.js";
2
+ import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-C-uCiIKh.js";
3
3
  import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
4
4
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
5
5
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
@@ -1,4 +1,4 @@
1
- import { S as normalizeSecretInputString, _ as hasConfiguredMSTeamsCredentials, a as searchGraphUsers, b as saveDelegatedTokens, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, r as formatUnknownError, u as listChannelsForTeam, y as resolveMSTeamsCredentials } from "./errors-BevpsEsu.js";
1
+ import { S as normalizeSecretInputString, _ as hasConfiguredMSTeamsCredentials, a as searchGraphUsers, b as saveDelegatedTokens, d as listTeamsByName, f as normalizeQuery, g as resolveGraphToken, r as formatUnknownError, u as listChannelsForTeam, y as resolveMSTeamsCredentials } from "./errors-B4snzfP5.js";
2
2
  import { mapAllowlistResolutionInputs } from "openclaw/plugin-sdk/allow-from";
3
3
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { DEFAULT_ACCOUNT_ID, createSetupTranslator, createStandardChannelSetupStatus, createTopLevelChannelAllowFromSetter, createTopLevelChannelDmPolicy, createTopLevelChannelGroupPolicySetter, mergeAllowFromEntries, splitSetupEntries } from "openclaw/plugin-sdk/setup";
@@ -1,8 +1,8 @@
1
1
  import { A as summarizeMapping, D as resolveDefaultGroupPolicy, E as resolveChannelMediaMaxBytes, M as getMSTeamsRuntime, N as getOptionalMSTeamsRuntime, _ as isDangerousNameMatchingEnabled, a as buildMediaPayload, b as logTypingFailure, c as createChannelMessageReplyPipeline, f as dispatchReplyFromConfigWithSettledDispatcher$1, l as createChannelPairingController, n as DEFAULT_WEBHOOK_MAX_BODY_BYTES, t as DEFAULT_ACCOUNT_ID, v as keepHttpServerTaskAlive, x as mergeAllowlist } from "./runtime-api-BlvMnDKz.js";
2
- import { $ as safeFetchWithPolicy, B as estimateBase64DecodedBytes, E as loadMSTeamsSdkWithAuth, F as ATTACHMENT_TAG_RE, G as isLikelyImageAttachment, H as extractInlineImageCandidates, I as GRAPH_ROOT, J as normalizeContentType, K as isRecord$1, L as IMG_SRC_RE, M as tryNormalizeBotFrameworkServiceUrl, N as resolveMSTeamsSdkCloudOptions, O as ensureUserAgentHeader, Q as resolveRequestUrl, R as applyAuthorizationHeaderForUrl, T as createMSTeamsTokenProvider, U as inferPlaceholder, V as extractHtmlFromAttachment, W as isDownloadableAttachment, X as resolveAttachmentFetchPolicy, Y as readNestedString, Z as resolveMediaSsrfPolicy, et as safeHostForUrl, l as fetchGraphJson, n as formatMSTeamsSendErrorHint, q as isUrlAllowed, r as formatUnknownError, t as classifyMSTeamsSendError, tt as tryBuildGraphSharesUrlForSharedLink, w as createMSTeamsExpressAdapter, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials, z as encodeGraphShareId } from "./errors-BevpsEsu.js";
3
- import { d as resolveMSTeamsUserAllowlist, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-Byk8kgPH.js";
4
- import { a as resolveMSTeamsReplyPolicy, i as resolveMSTeamsAllowlistMatch, o as resolveMSTeamsRouteConfig } from "./channel-C4ifQ0RF.js";
5
- import { C as readJsonFile, S as createMSTeamsConversationStoreFs, T as writeJsonFile, _ as buildFileInfoCard, b as createMSTeamsPollStoreFs, c as renderReplyPayloadsToMessages, d as withRevokedProxyFallback, f as resolveGraphChatId, g as removePendingUploadFs, h as getPendingUploadFs, l as sendMSTeamsMessages, m as removePendingUpload, p as getPendingUpload, s as buildConversationReference, u as sendMSTeamsActivityWithReference, v as parseFileConsentInvoke, w as withFileLock, x as extractMSTeamsPollVote, y as uploadToConsentUrl } from "./probe-C9cvgEV9.js";
2
+ import { $ as safeFetchWithPolicy, B as estimateBase64DecodedBytes, E as loadMSTeamsSdkWithAuth, F as ATTACHMENT_TAG_RE, G as isLikelyImageAttachment, H as extractInlineImageCandidates, I as GRAPH_ROOT, J as normalizeContentType, K as isRecord$1, L as IMG_SRC_RE, M as tryNormalizeBotFrameworkServiceUrl, N as resolveMSTeamsSdkCloudOptions, O as ensureUserAgentHeader, Q as resolveRequestUrl, R as applyAuthorizationHeaderForUrl, T as createMSTeamsTokenProvider, U as inferPlaceholder, V as extractHtmlFromAttachment, W as isDownloadableAttachment, X as resolveAttachmentFetchPolicy, Y as readNestedString, Z as resolveMediaSsrfPolicy, et as safeHostForUrl, l as fetchGraphJson, n as formatMSTeamsSendErrorHint, q as isUrlAllowed, r as formatUnknownError, t as classifyMSTeamsSendError, tt as tryBuildGraphSharesUrlForSharedLink, w as createMSTeamsExpressAdapter, x as resolveMSTeamsStorePath, y as resolveMSTeamsCredentials, z as encodeGraphShareId } from "./errors-B4snzfP5.js";
3
+ import { d as resolveMSTeamsUserAllowlist, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-C-uCiIKh.js";
4
+ import { a as resolveMSTeamsReplyPolicy, i as resolveMSTeamsAllowlistMatch, o as resolveMSTeamsRouteConfig } from "./channel-C_AMaSpi.js";
5
+ import { C as readJsonFile, S as createMSTeamsConversationStoreFs, T as writeJsonFile, _ as buildFileInfoCard, b as createMSTeamsPollStoreFs, c as renderReplyPayloadsToMessages, d as withRevokedProxyFallback, f as resolveGraphChatId, g as removePendingUploadFs, h as getPendingUploadFs, l as sendMSTeamsMessages, m as removePendingUpload, p as getPendingUpload, s as buildConversationReference, u as sendMSTeamsActivityWithReference, v as parseFileConsentInvoke, w as withFileLock, x as extractMSTeamsPollVote, y as uploadToConsentUrl } from "./probe-DRwI-ZqW.js";
6
6
  import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/allow-from";
7
7
  import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelProgressDraftGate, formatChannelProgressDraftText, isChannelProgressDraftWorkToolName, mergeChannelProgressDraftLine, normalizeChannelProgressDraftLineIdentity, resolveChannelPreviewStreamMode, resolveChannelProgressDraftMaxLines, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
8
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -499,6 +499,7 @@ async function fetchBotFrameworkAttachmentInfo(params) {
499
499
  url,
500
500
  policy: params.policy,
501
501
  fetchFn: params.fetchFn,
502
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
502
503
  resolveFn: params.resolveFn,
503
504
  requestInit: { headers: buildBotFrameworkAttachmentHeaders({
504
505
  url,
@@ -511,6 +512,7 @@ async function fetchBotFrameworkAttachmentInfo(params) {
511
512
  return;
512
513
  }
513
514
  if (!response.ok) {
515
+ await response.body?.cancel();
514
516
  params.logger?.warn?.("msteams botFramework attachmentInfo non-ok", { status: response.status });
515
517
  return;
516
518
  }
@@ -529,6 +531,7 @@ async function saveBotFrameworkAttachmentView(params) {
529
531
  url,
530
532
  policy: params.policy,
531
533
  fetchFn: params.fetchFn,
534
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
532
535
  resolveFn: params.resolveFn,
533
536
  requestInit: { headers: buildBotFrameworkAttachmentHeaders({
534
537
  url,
@@ -541,11 +544,15 @@ async function saveBotFrameworkAttachmentView(params) {
541
544
  return;
542
545
  }
543
546
  if (!response.ok) {
547
+ await response.body?.cancel();
544
548
  params.logger?.warn?.("msteams botFramework attachmentView non-ok", { status: response.status });
545
549
  return;
546
550
  }
547
551
  const contentLength = response.headers.get("content-length");
548
- if (contentLength && Number(contentLength) > params.maxBytes) return;
552
+ if (contentLength && Number(contentLength) > params.maxBytes) {
553
+ await response.body?.cancel();
554
+ return;
555
+ }
549
556
  try {
550
557
  return await getMSTeamsRuntime().channel.media.saveResponseMedia(response, {
551
558
  sourceUrl: url,
@@ -587,6 +594,7 @@ async function downloadMSTeamsBotFrameworkAttachment(params) {
587
594
  accessToken,
588
595
  policy,
589
596
  fetchFn: params.fetchFn,
597
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
590
598
  resolveFn: params.resolveFn,
591
599
  logger: params.logger
592
600
  });
@@ -609,6 +617,7 @@ async function downloadMSTeamsBotFrameworkAttachment(params) {
609
617
  preserveFilenames: params.preserveFilenames,
610
618
  policy,
611
619
  fetchFn: params.fetchFn,
620
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
612
621
  resolveFn: params.resolveFn,
613
622
  logger: params.logger
614
623
  });
@@ -652,6 +661,7 @@ async function downloadMSTeamsBotFrameworkAttachments(params) {
652
661
  allowHosts: params.allowHosts,
653
662
  authAllowHosts: params.authAllowHosts,
654
663
  fetchFn: params.fetchFn,
664
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
655
665
  resolveFn: params.resolveFn,
656
666
  fileNameHint: params.fileNameHint,
657
667
  contentTypeHint: params.contentTypeHint,
@@ -673,17 +683,9 @@ async function downloadMSTeamsBotFrameworkAttachments(params) {
673
683
  //#endregion
674
684
  //#region extensions/msteams/src/attachments/remote-media.ts
675
685
  /**
676
- * Direct fetch path used when the caller's `fetchImpl` has already validated
677
- * the URL against a hostname allowlist (for example `safeFetchWithPolicy`).
678
- *
679
- * Bypasses the strict SSRF dispatcher on `readRemoteMediaBuffer` because:
680
- * 1. The pinned undici dispatcher used by `readRemoteMediaBuffer` is incompatible
681
- * with Node 24+'s built-in undici v7 (fails with "invalid onRequestStart
682
- * method"), which silently breaks SharePoint/OneDrive downloads. See
683
- * issue #63396.
684
- * 2. SSRF protection is already enforced by the caller's `fetchImpl`
685
- * (`safeFetch` validates every redirect hop against the hostname
686
- * allowlist before following).
686
+ * Direct save path used when the caller supplies the already-guarded fetch
687
+ * implementation. This lets Teams-specific auth fallback own the request
688
+ * sequence while keeping redirect and DNS pinning inside `safeFetchWithPolicy`.
687
689
  */
688
690
  async function saveRemoteMediaDirect(params) {
689
691
  return await saveResponseMedia(await params.fetchImpl(params.url, { redirect: "follow" }), {
@@ -783,6 +785,7 @@ async function fetchWithAuthFallback(params) {
783
785
  url: params.url,
784
786
  policy: params.policy,
785
787
  fetchFn: params.fetchFn,
788
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
786
789
  requestInit: params.requestInit,
787
790
  resolveFn: params.resolveFn
788
791
  });
@@ -790,6 +793,7 @@ async function fetchWithAuthFallback(params) {
790
793
  if (!params.tokenProvider) return firstAttempt;
791
794
  if (firstAttempt.status !== 401 && firstAttempt.status !== 403) return firstAttempt;
792
795
  if (!isUrlAllowed(params.url, params.policy.authAllowHosts)) return firstAttempt;
796
+ await firstAttempt.body?.cancel();
793
797
  const scopes = scopeCandidatesForUrl(params.url);
794
798
  const fetchFn = params.fetchFn ?? fetch;
795
799
  for (const scope of scopes) try {
@@ -800,6 +804,7 @@ async function fetchWithAuthFallback(params) {
800
804
  url: params.url,
801
805
  policy: params.policy,
802
806
  fetchFn,
807
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
803
808
  requestInit: {
804
809
  ...params.requestInit,
805
810
  headers: authHeaders
@@ -808,7 +813,11 @@ async function fetchWithAuthFallback(params) {
808
813
  });
809
814
  if (authAttempt.ok) return authAttempt;
810
815
  if (isRedirectStatus(authAttempt.status)) return authAttempt;
811
- if (authAttempt.status !== 401 && authAttempt.status !== 403) continue;
816
+ if (authAttempt.status !== 401 && authAttempt.status !== 403) {
817
+ await authAttempt.body?.cancel();
818
+ continue;
819
+ }
820
+ await authAttempt.body?.cancel();
812
821
  } catch {}
813
822
  return firstAttempt;
814
823
  }
@@ -876,6 +885,7 @@ async function downloadMSTeamsAttachments(params) {
876
885
  url: resolveRequestUrl(input),
877
886
  tokenProvider: params.tokenProvider,
878
887
  fetchFn: params.fetchFn,
888
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
879
889
  requestInit: init,
880
890
  resolveFn: params.resolveFn,
881
891
  policy
@@ -1144,6 +1154,7 @@ async function downloadMSTeamsGraphMedia(params) {
1144
1154
  url: requestUrl,
1145
1155
  policy,
1146
1156
  fetchFn,
1157
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
1147
1158
  requestInit: {
1148
1159
  ...init,
1149
1160
  headers
@@ -1200,6 +1211,7 @@ async function downloadMSTeamsGraphMedia(params) {
1200
1211
  allowHosts: policy.allowHosts,
1201
1212
  authAllowHosts: policy.authAllowHosts,
1202
1213
  fetchFn: params.fetchFn,
1214
+ fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
1203
1215
  resolveFn: params.resolveFn,
1204
1216
  preserveFilenames: params.preserveFilenames,
1205
1217
  logger: params.logger
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/msteams",
3
- "version": "2026.5.28-beta.1",
3
+ "version": "2026.5.28-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/msteams",
9
- "version": "2026.5.28-beta.1",
9
+ "version": "2026.5.28-beta.2",
10
10
  "dependencies": {
11
11
  "@azure/identity": "4.13.1",
12
12
  "@microsoft/teams.api": "2.0.12",
@@ -15,7 +15,7 @@
15
15
  "typebox": "1.1.38"
16
16
  },
17
17
  "peerDependencies": {
18
- "openclaw": ">=2026.5.28-beta.1"
18
+ "openclaw": ">=2026.5.28-beta.2"
19
19
  },
20
20
  "peerDependenciesMeta": {
21
21
  "openclaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/msteams",
3
- "version": "2026.5.28-beta.1",
3
+ "version": "2026.5.28-beta.2",
4
4
  "description": "OpenClaw Microsoft Teams channel plugin for bot conversations.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,7 +15,7 @@
15
15
  "typebox": "1.1.38"
16
16
  },
17
17
  "peerDependencies": {
18
- "openclaw": ">=2026.5.28-beta.1"
18
+ "openclaw": ">=2026.5.28-beta.2"
19
19
  },
20
20
  "peerDependenciesMeta": {
21
21
  "openclaw": {
@@ -51,10 +51,10 @@
51
51
  "minHostVersion": ">=2026.4.10"
52
52
  },
53
53
  "compat": {
54
- "pluginApi": ">=2026.5.28-beta.1"
54
+ "pluginApi": ">=2026.5.28-beta.2"
55
55
  },
56
56
  "build": {
57
- "openclawVersion": "2026.5.28-beta.1"
57
+ "openclawVersion": "2026.5.28-beta.2"
58
58
  },
59
59
  "release": {
60
60
  "publishToClawHub": true,