@openclaw/msteams 2026.7.2-beta.1 → 2026.7.2-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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./channel-BSyPdpGN.cjs");
3
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
2
+ const require_channel = require("./channel-BKc8zroK.cjs");
3
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
4
4
  exports.createMSTeamsSetupWizardBase = require_setup_surface.createMSTeamsSetupWizardBase;
5
5
  exports.msteamsPlugin = require_channel.msteamsPlugin;
6
6
  exports.msteamsSetupAdapter = require_setup_surface.msteamsSetupAdapter;
@@ -1,7 +1,7 @@
1
1
  require("./runtime-api.cjs");
2
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
3
3
  const require_config_schema = require("./config-schema-BSNLJUta.cjs");
4
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
4
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
5
5
  let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
6
6
  let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
7
7
  let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
@@ -55,28 +55,19 @@ const msTeamsApprovalAuth = (0, openclaw_plugin_sdk_approval_auth_runtime.create
55
55
  }).approvalAuth;
56
56
  //#endregion
57
57
  //#region extensions/msteams/src/doctor.ts
58
- function isMSTeamsMutableAllowEntry(raw) {
59
- const text = raw.trim();
60
- if (!text || text === "*") return false;
61
- const withoutPrefix = text.replace(/^(msteams|user):/i, "").trim();
62
- return /\s/.test(withoutPrefix) || withoutPrefix.includes("@");
63
- }
58
+ const isMSTeamsMutableAllowEntry = (0, openclaw_plugin_sdk_channel_policy.buildMutableAllowEntryDetector)({
59
+ prefixes: ["msteams:", "user:"],
60
+ stableIdPattern: /^[^\s@]+$/
61
+ });
64
62
  const collectMSTeamsMutableAllowlistWarnings = (0, openclaw_plugin_sdk_channel_policy.createDangerousNameMatchingMutableAllowlistWarningCollector)({
65
63
  channel: "msteams",
66
64
  detector: isMSTeamsMutableAllowEntry,
67
- collectLists: (scope) => [{
68
- pathLabel: `${scope.prefix}.allowFrom`,
69
- list: scope.account.allowFrom
70
- }, {
71
- pathLabel: `${scope.prefix}.groupAllowFrom`,
72
- list: scope.account.groupAllowFrom
73
- }]
65
+ collectLists: (scope) => (0, openclaw_plugin_sdk_channel_policy.collectStandardAllowlistLists)(scope)
74
66
  });
75
67
  //#endregion
76
68
  //#region extensions/msteams/src/policy.ts
77
- const encodeScopeSegment = (value) => `${value.length}:${value}`;
78
- const teamScopeKey = (teamKey) => `team:${encodeScopeSegment(teamKey)}`;
79
- const channelScopeKey = (teamKey, channelKey) => `${teamScopeKey(teamKey)}/channel:${encodeScopeSegment(channelKey)}`;
69
+ const teamScopeKey = (teamKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey]);
70
+ const channelScopeKey = (teamKey, channelKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey], ["channel", channelKey]);
80
71
  function buildMSTeamsToolPolicyTree(teams) {
81
72
  const scopes = {};
82
73
  for (const [teamKey, team] of Object.entries(teams ?? {})) {
@@ -288,10 +279,12 @@ function buildMSTeamsPresentationCard(params) {
288
279
  if (block.type === "buttons") for (const button of block.buttons) {
289
280
  const action = (0, openclaw_plugin_sdk_interactive_runtime.resolveMessagePresentationButtonAction)(button);
290
281
  if (action?.type === "url" || action?.type === "web-app") {
282
+ const url = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(action.url);
283
+ if (!url) continue;
291
284
  actions.push({
292
285
  type: "Action.OpenUrl",
293
286
  title: button.label,
294
- url: action.url
287
+ url
295
288
  });
296
289
  continue;
297
290
  }
@@ -678,7 +671,7 @@ const collectMSTeamsSecurityWarnings = (0, openclaw_plugin_sdk_channel_policy.cr
678
671
  resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
679
672
  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."] : []
680
673
  });
681
- const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-DQTOzzet.cjs")), "msTeamsChannelRuntime");
674
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-hd1Zsoo2.cjs")), "msTeamsChannelRuntime");
682
675
  const resolveMSTeamsChannelConfig = (cfg) => ({
683
676
  allowFrom: cfg.channels?.msteams?.allowFrom,
684
677
  defaultTo: cfg.channels?.msteams?.defaultTo
@@ -974,6 +967,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
974
967
  setup: require_setup_surface.msteamsSetupAdapter,
975
968
  messaging: {
976
969
  targetPrefixes: ["msteams", "teams"],
970
+ directTargetStyle: "user-prefixed",
977
971
  normalizeTarget: require_resolve_allowlist.normalizeMSTeamsMessagingTarget,
978
972
  resolveOutboundSessionRoute: (params) => resolveMSTeamsOutboundSessionRoute(params),
979
973
  targetResolver: {
@@ -1571,7 +1565,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1571
1565
  })
1572
1566
  }),
1573
1567
  gateway: { startAccount: async (ctx) => {
1574
- const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-CUMz2B6f.cjs"));
1568
+ const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-20YasZEp.cjs"));
1575
1569
  const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1576
1570
  ctx.setStatus({
1577
1571
  accountId: ctx.accountId,
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./channel-BSyPdpGN.cjs");
2
+ const require_channel = require("./channel-BKc8zroK.cjs");
3
3
  exports.msteamsPlugin = require_channel.msteamsPlugin;
@@ -1,10 +1,10 @@
1
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
2
2
  require("./runtime-api.cjs");
3
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
4
- const require_channel = require("./channel-BSyPdpGN.cjs");
5
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
3
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
4
+ const require_channel = require("./channel-BKc8zroK.cjs");
5
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
6
6
  const require_polls = require("./polls-BhoI4VaN.cjs");
7
- const require_messenger = require("./messenger-DtS9gqkV.cjs");
7
+ const require_messenger = require("./messenger-BVcKl6dv.cjs");
8
8
  let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
9
9
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
10
10
  let openclaw_plugin_sdk_reply_payload = require("openclaw/plugin-sdk/reply-payload");
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
3
3
  let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
4
4
  const msteamsDirectoryContractPlugin = {
5
5
  id: "msteams",
@@ -1,8 +1,8 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
2
2
  const require_runtime = require("./runtime-gZTAuFux.cjs");
3
3
  require("./runtime-api.cjs");
4
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
5
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
4
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
5
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
6
6
  const require_polls = require("./polls-BhoI4VaN.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");
@@ -632,6 +632,15 @@ function requireMSTeamsSharePointSiteId(siteId) {
632
632
  if (!normalized) throw new Error("channels.msteams.sharePointSiteId is required to send files to group chats or channels");
633
633
  return normalized;
634
634
  }
635
+ const SHAREPOINT_REQUEST_TIMEOUT_LABEL = "MS Teams SharePoint request";
636
+ const SHAREPOINT_UPLOAD_TIMEOUT_LABEL = "MS Teams SharePoint upload";
637
+ const GRAPH_TOKEN_TIMEOUT_LABEL = "MS Teams Graph token acquisition";
638
+ async function getGraphAccessToken(tokenProvider) {
639
+ return await require_resolve_allowlist.withMSTeamsRequestDeadline({
640
+ label: GRAPH_TOKEN_TIMEOUT_LABEL,
641
+ work: async () => await tokenProvider.getAccessToken(GRAPH_SCOPE)
642
+ });
643
+ }
635
644
  /**
636
645
  * Upload a file to a SharePoint site.
637
646
  * This is used for group chats and channels where /me/drive doesn't work for bots.
@@ -640,19 +649,26 @@ function requireMSTeamsSharePointSiteId(siteId) {
640
649
  */
641
650
  async function uploadToSharePoint(params) {
642
651
  const fetchFn = params.fetchFn ?? fetch;
643
- const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
644
652
  const uploadPath = `/OpenClawShared/${encodeURIComponent(params.filename)}`;
645
- const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content`, {
646
- method: "PUT",
647
- headers: {
648
- "User-Agent": require_resolve_allowlist.buildUserAgent(),
649
- Authorization: `Bearer ${token}`,
650
- "Content-Type": params.contentType ?? "application/octet-stream"
651
- },
652
- body: new Uint8Array(params.buffer)
653
+ const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
654
+ label: SHAREPOINT_UPLOAD_TIMEOUT_LABEL,
655
+ timeoutMs: require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length),
656
+ work: async (signal) => {
657
+ const token = await getGraphAccessToken(params.tokenProvider);
658
+ const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content`, {
659
+ method: "PUT",
660
+ headers: {
661
+ "User-Agent": require_resolve_allowlist.buildUserAgent(),
662
+ Authorization: `Bearer ${token}`,
663
+ "Content-Type": params.contentType ?? "application/octet-stream"
664
+ },
665
+ body: new Uint8Array(params.buffer),
666
+ signal
667
+ });
668
+ if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "SharePoint upload failed");
669
+ return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.uploadSharePointFile");
670
+ }
653
671
  });
654
- if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "SharePoint upload failed");
655
- const data = await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.uploadSharePointFile");
656
672
  if (!data.id || !data.webUrl || !data.name) throw new Error("SharePoint upload response missing required fields");
657
673
  return {
658
674
  id: data.id,
@@ -669,13 +685,21 @@ async function uploadToSharePoint(params) {
669
685
  */
670
686
  async function getDriveItemProperties(params) {
671
687
  const fetchFn = params.fetchFn ?? fetch;
672
- const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
673
- const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/items/${params.itemId}?$select=eTag,webDavUrl,name`, { headers: {
674
- "User-Agent": require_resolve_allowlist.buildUserAgent(),
675
- Authorization: `Bearer ${token}`
676
- } });
677
- if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Get driveItem properties failed");
678
- const data = await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getDriveItemProperties");
688
+ const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
689
+ label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
690
+ work: async (signal) => {
691
+ const token = await getGraphAccessToken(params.tokenProvider);
692
+ const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/items/${params.itemId}?$select=eTag,webDavUrl,name`, {
693
+ headers: {
694
+ "User-Agent": require_resolve_allowlist.buildUserAgent(),
695
+ Authorization: `Bearer ${token}`
696
+ },
697
+ signal
698
+ });
699
+ if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Get driveItem properties failed");
700
+ return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getDriveItemProperties");
701
+ }
702
+ });
679
703
  if (!data.eTag || !data.webDavUrl || !data.name) throw new Error("DriveItem response missing required properties (eTag, webDavUrl, or name)");
680
704
  return {
681
705
  eTag: data.eTag,
@@ -689,13 +713,21 @@ async function getDriveItemProperties(params) {
689
713
  */
690
714
  async function getChatMembers(params) {
691
715
  const fetchFn = params.fetchFn ?? fetch;
692
- const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
693
- const res = await fetchFn(`${GRAPH_ROOT}/chats/${params.chatId}/members`, { headers: {
694
- "User-Agent": require_resolve_allowlist.buildUserAgent(),
695
- Authorization: `Bearer ${token}`
696
- } });
697
- if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Get chat members failed");
698
- return ((await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getChatMembers")).value ?? []).map((m) => ({ aadObjectId: m.userId ?? "" })).filter((m) => m.aadObjectId);
716
+ return await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
717
+ label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
718
+ work: async (signal) => {
719
+ const token = await getGraphAccessToken(params.tokenProvider);
720
+ const res = await fetchFn(`${GRAPH_ROOT}/chats/${params.chatId}/members`, {
721
+ headers: {
722
+ "User-Agent": require_resolve_allowlist.buildUserAgent(),
723
+ Authorization: `Bearer ${token}`
724
+ },
725
+ signal
726
+ });
727
+ 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");
728
+ return ((await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getChatMembers")).value ?? []).map((member) => ({ aadObjectId: member.userId ?? "" })).filter((member) => member.aadObjectId);
729
+ }
730
+ });
699
731
  }
700
732
  /**
701
733
  * Create a sharing link for a SharePoint drive item.
@@ -704,7 +736,6 @@ async function getChatMembers(params) {
704
736
  */
705
737
  async function createSharePointSharingLink(params) {
706
738
  const fetchFn = params.fetchFn ?? fetch;
707
- const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
708
739
  const scope = params.scope ?? "organization";
709
740
  const apiRoot = scope === "users" ? GRAPH_BETA : GRAPH_ROOT;
710
741
  const body = {
@@ -712,17 +743,24 @@ async function createSharePointSharingLink(params) {
712
743
  scope: scope === "users" ? "users" : "organization"
713
744
  };
714
745
  if (scope === "users" && params.recipientObjectIds?.length) body.recipients = params.recipientObjectIds.map((id) => ({ objectId: id }));
715
- const res = await fetchFn(`${apiRoot}/sites/${params.siteId}/drive/items/${params.itemId}/createLink`, {
716
- method: "POST",
717
- headers: {
718
- "User-Agent": require_resolve_allowlist.buildUserAgent(),
719
- Authorization: `Bearer ${token}`,
720
- "Content-Type": "application/json"
721
- },
722
- body: JSON.stringify(body)
746
+ const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
747
+ label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
748
+ work: async (signal) => {
749
+ const token = await getGraphAccessToken(params.tokenProvider);
750
+ const res = await fetchFn(`${apiRoot}/sites/${params.siteId}/drive/items/${params.itemId}/createLink`, {
751
+ method: "POST",
752
+ headers: {
753
+ "User-Agent": require_resolve_allowlist.buildUserAgent(),
754
+ Authorization: `Bearer ${token}`,
755
+ "Content-Type": "application/json"
756
+ },
757
+ body: JSON.stringify(body),
758
+ signal
759
+ });
760
+ if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Create SharePoint sharing link failed");
761
+ return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.createSharePointSharingLink");
762
+ }
723
763
  });
724
- if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Create SharePoint sharing link failed");
725
- const data = await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.createSharePointSharingLink");
726
764
  if (!data.link?.webUrl) throw new Error("Create SharePoint sharing link response missing webUrl");
727
765
  return { webUrl: data.link.webUrl };
728
766
  }
@@ -734,7 +772,7 @@ async function createSharePointSharingLink(params) {
734
772
  *
735
773
  * @param params.siteId - SharePoint site ID
736
774
  * @param params.chatId - Optional chat ID for per-user sharing (group chats)
737
- * @param params.usePerUserSharing - Whether to use per-user sharing (requires beta API + Chat.Read.All)
775
+ * @param params.usePerUserSharing - Whether to use per-user sharing (requires beta API + chat-member read access)
738
776
  */
739
777
  async function uploadAndShareSharePoint(params) {
740
778
  const uploaded = await uploadToSharePoint({
@@ -747,17 +785,16 @@ async function uploadAndShareSharePoint(params) {
747
785
  });
748
786
  let scope = "organization";
749
787
  let recipientObjectIds;
750
- if (params.usePerUserSharing && params.chatId) try {
788
+ if (params.usePerUserSharing && params.chatId) {
751
789
  const members = await getChatMembers({
752
790
  chatId: params.chatId,
753
791
  tokenProvider: params.tokenProvider,
754
792
  fetchFn: params.fetchFn
755
793
  });
756
- if (members.length > 0) {
757
- scope = "users";
758
- recipientObjectIds = members.map((m) => m.aadObjectId);
759
- }
760
- } catch {}
794
+ if (members.length === 0) throw new Error("MS Teams chat member lookup returned no recipients");
795
+ scope = "users";
796
+ recipientObjectIds = members.map((member) => member.aadObjectId);
797
+ }
761
798
  const shareLink = await createSharePointSharingLink({
762
799
  siteId: params.siteId,
763
800
  itemId: uploaded.id,
@@ -1,4 +1,4 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
2
2
  let openclaw_plugin_sdk_provider_auth = require("openclaw/plugin-sdk/provider-auth");
3
3
  let openclaw_plugin_sdk_provider_auth_runtime = require("openclaw/plugin-sdk/provider-auth-runtime");
4
4
  let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
@@ -44,6 +44,22 @@ function resolveMSTeamsSharePointUploadTimeoutMs(sizeInBytes) {
44
44
  const transferBudgetMs = Math.ceil((Number.isFinite(sizeInBytes) && sizeInBytes > 0 ? Math.ceil(sizeInBytes) : 0) / MSTEAMS_SHAREPOINT_UPLOAD_MIN_BYTES_PER_SECOND * 1e3);
45
45
  return (0, openclaw_plugin_sdk_number_runtime.resolveTimerTimeoutMs)(MSTEAMS_SHAREPOINT_UPLOAD_BASE_TIMEOUT_MS + transferBudgetMs, MSTEAMS_SHAREPOINT_UPLOAD_BASE_TIMEOUT_MS, 1);
46
46
  }
47
+ function createMSTeamsRequestTimeoutError(label, timeoutMs) {
48
+ const error = /* @__PURE__ */ new Error(`${label} timed out after ${timeoutMs}ms`);
49
+ error.name = "TimeoutError";
50
+ return error;
51
+ }
52
+ async function withMSTeamsAbortableRequestTimeout(params) {
53
+ const controller = new AbortController();
54
+ const timeoutMs = (0, openclaw_plugin_sdk_number_runtime.resolveTimerTimeoutMs)(params.timeoutMs, MSTEAMS_REQUEST_TIMEOUT_MS, 1);
55
+ const work = Promise.resolve().then(() => params.work(controller.signal));
56
+ try {
57
+ return await (0, openclaw_plugin_sdk_text_utility_runtime.withTimeout)(work, timeoutMs, { createError: () => createMSTeamsRequestTimeoutError(params.label, timeoutMs) });
58
+ } catch (error) {
59
+ controller.abort(error);
60
+ throw error;
61
+ }
62
+ }
47
63
  //#endregion
48
64
  //#region extensions/msteams/src/response-with-release.ts
49
65
  const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([
@@ -624,6 +640,16 @@ function resolveOpenClawVersion() {
624
640
  return "unknown";
625
641
  }
626
642
  }
643
+ /**
644
+ * Build a combined User-Agent string that preserves the Teams SDK identity
645
+ * and appends the OpenClaw version.
646
+ *
647
+ * Format: "teams.ts[apps]/<sdk-version> OpenClaw/<openclaw-version>"
648
+ * Example: "teams.ts[apps]/2.0.5 OpenClaw/2026.3.22"
649
+ *
650
+ * This lets the Teams backend track SDK usage while also identifying the
651
+ * host application.
652
+ */
627
653
  function buildUserAgent() {
628
654
  if (cachedUserAgent) return cachedUserAgent;
629
655
  cachedUserAgent = `teams.ts[apps]/${resolveTeamsSdkVersion()} OpenClaw/${resolveOpenClawVersion()}`;
@@ -2038,6 +2064,12 @@ Object.defineProperty(exports, "validateMSTeamsProactiveServiceUrlBoundary", {
2038
2064
  return validateMSTeamsProactiveServiceUrlBoundary;
2039
2065
  }
2040
2066
  });
2067
+ Object.defineProperty(exports, "withMSTeamsAbortableRequestTimeout", {
2068
+ enumerable: true,
2069
+ get: function() {
2070
+ return withMSTeamsAbortableRequestTimeout;
2071
+ }
2072
+ });
2041
2073
  Object.defineProperty(exports, "withMSTeamsRequestDeadline", {
2042
2074
  enumerable: true,
2043
2075
  get: function() {
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
3
3
  const require_config_schema = require("./config-schema-BSNLJUta.cjs");
4
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
4
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
5
5
  let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
6
6
  let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
7
7
  let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
@@ -1,8 +1,9 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
2
2
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
3
3
  let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
4
4
  let openclaw_plugin_sdk_setup = require("openclaw/plugin-sdk/setup");
5
5
  let openclaw_plugin_sdk_setup_tools = require("openclaw/plugin-sdk/setup-tools");
6
+ let openclaw_plugin_sdk_retry_runtime = require("openclaw/plugin-sdk/retry-runtime");
6
7
  let openclaw_plugin_sdk_secret_input = require("openclaw/plugin-sdk/secret-input");
7
8
  //#region extensions/msteams/src/setup-core.ts
8
9
  const t$1 = (0, openclaw_plugin_sdk_setup.createSetupTranslator)();
@@ -181,14 +182,14 @@ function extractRetryAfterMs(err) {
181
182
  if ((0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(headers)) {
182
183
  const raw = headers["retry-after"] ?? headers["Retry-After"];
183
184
  if (typeof raw === "string") {
184
- const parsed = parseNonNegativeRetryAfterSeconds(raw);
185
+ const parsed = (0, openclaw_plugin_sdk_retry_runtime.parseRetryAfterHeaderSeconds)(raw);
185
186
  if (parsed !== void 0) return parsed * 1e3;
186
187
  }
187
188
  }
188
189
  if (typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function") {
189
190
  const raw = headers.get("retry-after");
190
191
  if (raw) {
191
- const parsed = parseNonNegativeRetryAfterSeconds(raw);
192
+ const parsed = (0, openclaw_plugin_sdk_retry_runtime.parseRetryAfterHeaderSeconds)(raw);
192
193
  if (parsed !== void 0) return parsed * 1e3;
193
194
  }
194
195
  }
@@ -454,7 +455,7 @@ const msteamsSetupWizard = {
454
455
  };
455
456
  let oauthModule;
456
457
  try {
457
- oauthModule = await Promise.resolve().then(() => require("./oauth-C5E5powI.cjs"));
458
+ oauthModule = await Promise.resolve().then(() => require("./oauth-yNoKtU_3.cjs"));
458
459
  } catch (err) {
459
460
  await noteDelegatedAuthFailure(err);
460
461
  return {
@@ -505,16 +506,7 @@ const msteamsSetupWizard = {
505
506
  },
506
507
  dmPolicy: msteamsDmPolicy,
507
508
  groupAccess: msteamsGroupAccess,
508
- disable: (cfg) => ({
509
- ...cfg,
510
- channels: {
511
- ...cfg.channels,
512
- msteams: {
513
- ...cfg.channels?.msteams,
514
- enabled: false
515
- }
516
- }
517
- })
509
+ disable: (cfg) => (0, openclaw_plugin_sdk_setup.setSetupChannelEnabled)(cfg, channel, false)
518
510
  };
519
511
  //#endregion
520
512
  Object.defineProperty(exports, "classifyMSTeamsSendError", {
@@ -1,12 +1,12 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
2
2
  const require_runtime = require("./runtime-gZTAuFux.cjs");
3
3
  require("./runtime-api.cjs");
4
- const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
5
- const require_channel = require("./channel-BSyPdpGN.cjs");
6
- const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
4
+ const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
5
+ const require_channel = require("./channel-BKc8zroK.cjs");
6
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
7
7
  const require_polls = require("./polls-BhoI4VaN.cjs");
8
8
  const require_sso_token_store = require("./sso-token-store-CktCz88k.cjs");
9
- const require_messenger = require("./messenger-DtS9gqkV.cjs");
9
+ const require_messenger = require("./messenger-BVcKl6dv.cjs");
10
10
  let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
11
11
  let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
12
12
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
@@ -1461,6 +1461,8 @@ function createTeamsReplyStreamController(params) {
1461
1461
  let streamFailed = false;
1462
1462
  let lastInformativeText = "";
1463
1463
  let progressLines = [];
1464
+ let latestPlan;
1465
+ let latestPlanExplanation;
1464
1466
  let pendingFinalPayload;
1465
1467
  let emittedText = "";
1466
1468
  const wasCanceled = () => canceledLocally || Boolean(stream?.canceled);
@@ -1482,7 +1484,9 @@ function createTeamsReplyStreamController(params) {
1482
1484
  entry: params.msteamsConfig,
1483
1485
  lines: shouldStreamPreviewToolProgress ? progressLines : [],
1484
1486
  seed: params.progressSeed,
1485
- bullet: "-"
1487
+ bullet: "-",
1488
+ narration: latestPlanExplanation,
1489
+ plan: latestPlan
1486
1490
  });
1487
1491
  if (!informativeText || informativeText === lastInformativeText) return;
1488
1492
  lastInformativeText = informativeText;
@@ -1554,6 +1558,14 @@ function createTeamsReplyStreamController(params) {
1554
1558
  const progressActive = await progressDraftGate.noteWork();
1555
1559
  if ((hadStarted || progressActive) && progressDraftGate.hasStarted) renderInformativeUpdate();
1556
1560
  },
1561
+ async pushPlanProgress(steps, options) {
1562
+ if (!stream || streamMode !== "progress" || streamFinalizationPending) return;
1563
+ latestPlan = steps?.length ? steps.map((entry) => ({ ...entry })) : void 0;
1564
+ latestPlanExplanation = options?.explanation?.replace(/\s+/g, " ").trim() || void 0;
1565
+ const hadStarted = progressDraftGate.hasStarted;
1566
+ await progressDraftGate.startNow();
1567
+ if (hadStarted && progressDraftGate.hasStarted) renderInformativeUpdate();
1568
+ },
1557
1569
  preparePayload(payload) {
1558
1570
  if (!stream) return payload;
1559
1571
  if (wasCanceled()) return;
@@ -1901,13 +1913,7 @@ function createMSTeamsReplyDispatcher(params) {
1901
1913
  },
1902
1914
  onPlanUpdate: async (payload) => {
1903
1915
  if (payload?.phase !== "update") return;
1904
- await streamController.pushProgressLine((0, openclaw_plugin_sdk_channel_outbound.buildChannelProgressDraftLine)({
1905
- event: "plan",
1906
- phase: payload.phase,
1907
- ...typeof payload?.title === "string" ? { title: payload.title } : {},
1908
- ...typeof payload?.explanation === "string" ? { explanation: payload.explanation } : {},
1909
- ...Array.isArray(payload?.steps) && payload.steps.every((s) => typeof s === "string") ? { steps: payload.steps } : {}
1910
- }));
1916
+ await streamController.pushPlanProgress((0, openclaw_plugin_sdk_channel_outbound.normalizeAgentPlanSteps)(payload.planSteps), { explanation: typeof payload.explanation === "string" ? payload.explanation : void 0 });
1911
1917
  },
1912
1918
  onApprovalEvent: async (payload) => {
1913
1919
  if (payload?.phase !== "requested") return;
@@ -2698,7 +2704,7 @@ function createMSTeamsMessageHandler(deps) {
2698
2704
  canDetectMention: !isDirectMessage,
2699
2705
  wasMentioned: isDirectMessage || mentionDecision.effectiveWasMentioned
2700
2706
  },
2701
- commands: { authorized: commandAuthorized }
2707
+ commands: { authorized: commandAuthorized === true }
2702
2708
  },
2703
2709
  extra: {
2704
2710
  GroupSubject: !isDirectMessage ? conversationType : void 0,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/msteams",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/msteams",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.2",
10
10
  "dependencies": {
11
11
  "@azure/identity": "4.13.1",
12
12
  "@microsoft/teams.api": "2.0.13",
@@ -15,7 +15,7 @@
15
15
  "typebox": "1.3.3"
16
16
  },
17
17
  "peerDependencies": {
18
- "openclaw": ">=2026.7.2-beta.1"
18
+ "openclaw": ">=2026.7.2-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.7.2-beta.1",
3
+ "version": "2026.7.2-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.3.3"
16
16
  },
17
17
  "peerDependencies": {
18
- "openclaw": ">=2026.7.2-beta.1"
18
+ "openclaw": ">=2026.7.2-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.7.2-beta.1"
54
+ "pluginApi": ">=2026.7.2-beta.2"
55
55
  },
56
56
  "build": {
57
- "openclawVersion": "2026.7.2-beta.1",
57
+ "openclawVersion": "2026.7.2-beta.2",
58
58
  "runtimeFormat": "cjs"
59
59
  },
60
60
  "release": {