@openclaw/msteams 2026.5.28-beta.2 → 2026.5.28-beta.4

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-C-uCiIKh.js";
2
- import { t as msteamsPlugin } from "./channel-C_AMaSpi.js";
1
+ import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-C9IApOv3.js";
2
+ import { t as msteamsPlugin } from "./channel-2_L55KDI.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-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";
2
+ import { y as resolveMSTeamsCredentials } from "./errors-DZGI_mqq.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-C9IApOv3.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-BJJ1R1iY.js"), "msTeamsChannelRuntime");
333
+ const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-CxxY1xk6.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-Cc3f8Zi2.js");
1119
+ const { monitorMSTeamsProvider } = await import("./src-D_rcW2Zm.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-C_AMaSpi.js";
1
+ import { t as msteamsPlugin } from "./channel-2_L55KDI.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-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";
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-DZGI_mqq.js";
3
+ import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel-2_L55KDI.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-BoUA5GpA.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,5 +1,5 @@
1
1
  import { M as getMSTeamsRuntime, h as fetchWithSsrFGuard$1 } from "./runtime-api-BlvMnDKz.js";
2
- import { c as createMSTeamsHttpError, n as refreshMSTeamsDelegatedTokens } from "./oauth.token-5ygi8ycy.js";
2
+ import { c as createMSTeamsHttpError, n as refreshMSTeamsDelegatedTokens } from "./oauth.token-BKzEFepQ.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
5
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -11,6 +11,7 @@ import * as fs from "node:fs";
11
11
  import { readFileSync } from "node:fs";
12
12
  import path, { basename, dirname } from "node:path";
13
13
  import { privateFileStoreSync } from "openclaw/plugin-sdk/security-runtime";
14
+ import { asFiniteNumberInRange, parseStrictFiniteNumber } from "openclaw/plugin-sdk/number-runtime";
14
15
  import { hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
15
16
  //#region extensions/msteams/src/attachments/shared.ts
16
17
  const IMAGE_EXT_RE = /\.(avif|bmp|gif|heic|heif|jpe?g|png|tiff?|webp)$/i;
@@ -1032,6 +1033,7 @@ async function searchGraphUsers(params) {
1032
1033
  }
1033
1034
  //#endregion
1034
1035
  //#region extensions/msteams/src/errors.ts
1036
+ const MAX_SAFE_RETRY_AFTER_SECONDS = Number.MAX_SAFE_INTEGER / 1e3;
1035
1037
  function formatUnknownError(err) {
1036
1038
  if (err instanceof Error) return err.message;
1037
1039
  if (typeof err === "string") return err;
@@ -1082,13 +1084,20 @@ function extractErrorCode(err) {
1082
1084
  }
1083
1085
  function extractRetryAfterMs(err) {
1084
1086
  if (!isRecord(err)) return null;
1085
- const direct = err.retryAfterMs ?? err.retry_after_ms;
1086
- if (typeof direct === "number" && Number.isFinite(direct) && direct >= 0) return direct;
1087
+ const directMs = asFiniteNumberInRange(err.retryAfterMs ?? err.retry_after_ms, {
1088
+ min: 0,
1089
+ max: Number.MAX_SAFE_INTEGER
1090
+ });
1091
+ if (directMs !== void 0) return directMs;
1087
1092
  const retryAfter = err.retryAfter ?? err.retry_after;
1088
- if (typeof retryAfter === "number" && Number.isFinite(retryAfter)) return retryAfter >= 0 ? retryAfter * 1e3 : null;
1093
+ const retryAfterSeconds = asFiniteNumberInRange(retryAfter, {
1094
+ min: 0,
1095
+ max: MAX_SAFE_RETRY_AFTER_SECONDS
1096
+ });
1097
+ if (retryAfterSeconds !== void 0) return retryAfterSeconds * 1e3;
1089
1098
  if (typeof retryAfter === "string") {
1090
1099
  const parsed = parseNonNegativeRetryAfterSeconds(retryAfter);
1091
- if (Number.isFinite(parsed) && parsed >= 0) return parsed * 1e3;
1100
+ if (parsed !== void 0) return parsed * 1e3;
1092
1101
  }
1093
1102
  const response = err.response;
1094
1103
  if (!isRecord(response)) return null;
@@ -1098,22 +1107,25 @@ function extractRetryAfterMs(err) {
1098
1107
  const raw = headers["retry-after"] ?? headers["Retry-After"];
1099
1108
  if (typeof raw === "string") {
1100
1109
  const parsed = parseNonNegativeRetryAfterSeconds(raw);
1101
- if (Number.isFinite(parsed) && parsed >= 0) return parsed * 1e3;
1110
+ if (parsed !== void 0) return parsed * 1e3;
1102
1111
  }
1103
1112
  }
1104
1113
  if (typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function") {
1105
1114
  const raw = headers.get("retry-after");
1106
1115
  if (raw) {
1107
1116
  const parsed = parseNonNegativeRetryAfterSeconds(raw);
1108
- if (Number.isFinite(parsed) && parsed >= 0) return parsed * 1e3;
1117
+ if (parsed !== void 0) return parsed * 1e3;
1109
1118
  }
1110
1119
  }
1111
1120
  return null;
1112
1121
  }
1113
1122
  function parseNonNegativeRetryAfterSeconds(raw) {
1114
1123
  const trimmed = raw.trim();
1115
- if (!/^\d+(?:\.\d+)?$/.test(trimmed)) return NaN;
1116
- return Number(trimmed);
1124
+ if (!/^\d+(?:\.\d+)?$/.test(trimmed)) return;
1125
+ return asFiniteNumberInRange(parseStrictFiniteNumber(trimmed), {
1126
+ min: 0,
1127
+ max: MAX_SAFE_RETRY_AFTER_SECONDS
1128
+ });
1117
1129
  }
1118
1130
  /**
1119
1131
  * Classify outbound send errors for safe retries and actionable logs.
@@ -1,4 +1,4 @@
1
- import { a as MSTEAMS_OAUTH_CALLBACK_PORT, i as MSTEAMS_OAUTH_CALLBACK_PATH, o as MSTEAMS_OAUTH_REDIRECT_URI, r as MSTEAMS_DEFAULT_DELEGATED_SCOPES, s as buildMSTeamsAuthEndpoint, t as exchangeMSTeamsCodeForTokens } from "./oauth.token-5ygi8ycy.js";
1
+ import { a as MSTEAMS_OAUTH_CALLBACK_PORT, i as MSTEAMS_OAUTH_CALLBACK_PATH, o as MSTEAMS_OAUTH_REDIRECT_URI, r as MSTEAMS_DEFAULT_DELEGATED_SCOPES, s as buildMSTeamsAuthEndpoint, t as exchangeMSTeamsCodeForTokens } from "./oauth.token-BKzEFepQ.js";
2
2
  import { generateHexPkceVerifierChallenge } from "openclaw/plugin-sdk/provider-auth";
3
3
  import { generateOAuthState, parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
4
4
  import { isWSL2Sync } from "openclaw/plugin-sdk/runtime-env";
@@ -1,5 +1,6 @@
1
1
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
2
2
  import { createProviderHttpError, readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
3
+ import { resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
3
4
  //#region extensions/msteams/src/http-error.ts
4
5
  async function createMSTeamsHttpError(response, label, options) {
5
6
  return await createProviderHttpError(response, label, options);
@@ -36,6 +37,19 @@ function createMSTeamsTokenBody(params) {
36
37
  for (const [key, value] of Object.entries(params.values ?? {})) body.set(key, value);
37
38
  return body;
38
39
  }
40
+ function resolveMSTeamsTokenExpiresAt(value) {
41
+ return resolveExpiresAtMsFromDurationSeconds(value, { bufferMs: EXPIRY_BUFFER_MS });
42
+ }
43
+ function parseMSTeamsTokenResponse(data, failureLabel) {
44
+ const expiresAt = resolveMSTeamsTokenExpiresAt(data.expires_in);
45
+ if (typeof data.access_token !== "string" || !data.access_token || expiresAt === void 0 || data.refresh_token !== void 0 && typeof data.refresh_token !== "string" || data.scope !== void 0 && typeof data.scope !== "string") throw new Error(`MSTeams ${failureLabel} failed: invalid token response fields`);
46
+ return {
47
+ access_token: data.access_token,
48
+ refresh_token: data.refresh_token,
49
+ expiresAt,
50
+ scope: data.scope
51
+ };
52
+ }
39
53
  async function fetchMSTeamsTokens(params) {
40
54
  const currentFetch = globalThis.fetch;
41
55
  const { response, release } = await fetchWithSsrFGuard({
@@ -54,7 +68,7 @@ async function fetchMSTeamsTokens(params) {
54
68
  });
55
69
  try {
56
70
  if (!response.ok) throw await createMSTeamsHttpError(response, `MSTeams ${params.failureLabel} failed`);
57
- return await readProviderJsonResponse(response, `MSTeams ${params.failureLabel} failed`);
71
+ return parseMSTeamsTokenResponse(await readProviderJsonResponse(response, `MSTeams ${params.failureLabel} failed`), params.failureLabel);
58
72
  } finally {
59
73
  await release();
60
74
  }
@@ -77,7 +91,7 @@ async function requestMSTeamsDelegatedTokens(params) {
77
91
  return {
78
92
  accessToken: data.access_token,
79
93
  refreshToken: params.resolveRefreshToken(data),
80
- expiresAt: Date.now() + data.expires_in * 1e3 - EXPIRY_BUFFER_MS,
94
+ expiresAt: data.expiresAt,
81
95
  scopes: data.scope ? data.scope.split(" ") : [...scopes]
82
96
  };
83
97
  }
@@ -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-B4snzfP5.js";
3
- import { c as createMSTeamsHttpError } from "./oauth.token-5ygi8ycy.js";
4
- import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-C_AMaSpi.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-DZGI_mqq.js";
3
+ import { c as createMSTeamsHttpError } from "./oauth.token-BKzEFepQ.js";
4
+ import { a as resolveMSTeamsReplyPolicy, o as resolveMSTeamsRouteConfig } from "./channel-2_L55KDI.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";
@@ -11,6 +11,7 @@ import { lookup } from "node:dns/promises";
11
11
  import { isPrivateIpAddress } from "openclaw/plugin-sdk/ssrf-policy";
12
12
  import path from "node:path";
13
13
  import { pathExists } from "openclaw/plugin-sdk/security-runtime";
14
+ import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
14
15
  import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
15
16
  import crypto from "node:crypto";
16
17
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
@@ -324,10 +325,7 @@ function pruneToLimit$1(polls) {
324
325
  }
325
326
  function normalizeMSTeamsPollSelections(poll, selections) {
326
327
  const maxSelections = Math.max(1, poll.maxSelections);
327
- const mapped = selections.map((entry) => {
328
- const trimmed = entry.trim();
329
- return /^\d+$/.test(trimmed) ? Number(trimmed) : NaN;
330
- }).filter((value) => Number.isSafeInteger(value)).filter((value) => value >= 0 && value < poll.options.length).map((value) => String(value));
328
+ const mapped = selections.map((entry) => parseStrictNonNegativeInteger(entry)).filter((value) => value !== void 0).filter((value) => value >= 0 && value < poll.options.length).map((value) => String(value));
331
329
  return uniqueStrings(maxSelections > 1 ? mapped.slice(0, maxSelections) : mapped.slice(0, 1));
332
330
  }
333
331
  function createMSTeamsPollStoreFs(params) {
@@ -1,5 +1,5 @@
1
- import { y as resolveMSTeamsCredentials } from "./errors-B4snzfP5.js";
2
- import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-C-uCiIKh.js";
1
+ import { y as resolveMSTeamsCredentials } from "./errors-DZGI_mqq.js";
2
+ import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-C9IApOv3.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-B4snzfP5.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-DZGI_mqq.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";
@@ -489,7 +489,7 @@ const msteamsSetupWizard = {
489
489
  }
490
490
  };
491
491
  try {
492
- const { loginMSTeamsDelegated } = await import("./oauth-BrKjrCNK.js");
492
+ const { loginMSTeamsDelegated } = await import("./oauth-ei63gdyS.js");
493
493
  const progress = params.prompter.progress(t("wizard.msteams.delegatedOAuthProgress"));
494
494
  saveDelegatedTokens(await loginMSTeamsDelegated({
495
495
  isRemote: true,
@@ -1,12 +1,12 @@
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-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";
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-DZGI_mqq.js";
3
+ import { d as resolveMSTeamsUserAllowlist, u as resolveMSTeamsChannelAllowlist } from "./setup-surface-C9IApOv3.js";
4
+ import { a as resolveMSTeamsReplyPolicy, i as resolveMSTeamsAllowlistMatch, o as resolveMSTeamsRouteConfig } from "./channel-2_L55KDI.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-BoUA5GpA.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";
9
- import { saveResponseMedia } from "openclaw/plugin-sdk/media-runtime";
9
+ import { parseMediaContentLength, saveResponseMedia } from "openclaw/plugin-sdk/media-runtime";
10
10
  import { buildChannelInboundEventContext, dispatchReplyFromConfigWithSettledDispatcher, hasFinalInboundReplyDispatch, logInboundDrop, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveInboundSessionEnvelopeContext } from "openclaw/plugin-sdk/channel-inbound";
11
11
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
12
12
  import path from "node:path";
@@ -548,8 +548,15 @@ async function saveBotFrameworkAttachmentView(params) {
548
548
  params.logger?.warn?.("msteams botFramework attachmentView non-ok", { status: response.status });
549
549
  return;
550
550
  }
551
- const contentLength = response.headers.get("content-length");
552
- if (contentLength && Number(contentLength) > params.maxBytes) {
551
+ let contentLength;
552
+ try {
553
+ contentLength = parseMediaContentLength(response.headers.get("content-length"));
554
+ } catch (err) {
555
+ await response.body?.cancel();
556
+ params.logger?.warn?.("msteams botFramework attachmentView invalid content-length", { error: err instanceof Error ? err.message : String(err) });
557
+ return;
558
+ }
559
+ if (contentLength !== null && contentLength > params.maxBytes) {
553
560
  await response.body?.cancel();
554
561
  return;
555
562
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/msteams",
3
- "version": "2026.5.28-beta.2",
3
+ "version": "2026.5.28-beta.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/msteams",
9
- "version": "2026.5.28-beta.2",
9
+ "version": "2026.5.28-beta.4",
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.2"
18
+ "openclaw": ">=2026.5.28-beta.4"
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.2",
3
+ "version": "2026.5.28-beta.4",
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.2"
18
+ "openclaw": ">=2026.5.28-beta.4"
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.2"
54
+ "pluginApi": ">=2026.5.28-beta.4"
55
55
  },
56
56
  "build": {
57
- "openclawVersion": "2026.5.28-beta.2"
57
+ "openclawVersion": "2026.5.28-beta.4"
58
58
  },
59
59
  "release": {
60
60
  "publishToClawHub": true,