@openclaw/msteams 2026.7.2-beta.7 → 2026.8.1-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.
@@ -1,10 +1,10 @@
1
- const require_polls = require("./polls-BWKNpBSg.cjs");
2
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
3
2
  require("./runtime-api.cjs");
4
- const require_resolve_allowlist = require("./resolve-allowlist-CEj9sABO.cjs");
5
- const require_channel = require("./channel-C7QxRjBW.cjs");
6
- const require_setup_surface = require("./setup-surface-ByWjaXEn.cjs");
7
- const require_messenger = require("./messenger-DTiaLTDO.cjs");
3
+ const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
4
+ const require_channel = require("./channel-DfCbi0d_.cjs");
5
+ const require_setup_surface = require("./setup-surface-DAhGL2h8.cjs");
6
+ const require_polls = require("./polls-DvuJvaDG.cjs");
7
+ const require_messenger = require("./messenger-BqA8G3pY.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");
@@ -165,9 +165,10 @@ async function pinMessageMSTeams(params) {
165
165
  const body = { "message@odata.bind": `https://graph.microsoft.com/v1.0/chats/${encodeURIComponent(conversationId)}/messages/${encodeURIComponent(params.messageId)}` };
166
166
  return {
167
167
  ok: true,
168
- pinnedMessageId: (await require_resolve_allowlist.postGraphJson({
168
+ pinnedMessageId: (await require_resolve_allowlist.mutateGraphJson({
169
169
  token,
170
170
  path: `${conv.basePath}/pinnedMessages`,
171
+ method: "POST",
171
172
  body
172
173
  })).id
173
174
  };
@@ -239,10 +240,12 @@ async function reactMessageMSTeams(params) {
239
240
  const reactionType = require_messenger.resolveMSTeamsReactionEmoji(params.reactionType);
240
241
  const token = await require_resolve_allowlist.resolveGraphToken(params.cfg, { preferDelegated: true });
241
242
  const { basePath } = resolveConversationPath(await resolveGraphConversationId(params.to));
242
- await require_resolve_allowlist.postGraphBetaJson({
243
+ await require_resolve_allowlist.mutateGraphJson({
243
244
  token,
244
245
  path: `${basePath}/messages/${encodeURIComponent(params.messageId)}/setReaction`,
245
- body: { reactionType }
246
+ method: "POST",
247
+ body: { reactionType },
248
+ beta: true
246
249
  });
247
250
  return { ok: true };
248
251
  }
@@ -256,10 +259,12 @@ async function unreactMessageMSTeams(params) {
256
259
  const reactionType = require_messenger.resolveMSTeamsReactionEmoji(params.reactionType);
257
260
  const token = await require_resolve_allowlist.resolveGraphToken(params.cfg, { preferDelegated: true });
258
261
  const { basePath } = resolveConversationPath(await resolveGraphConversationId(params.to));
259
- await require_resolve_allowlist.postGraphBetaJson({
262
+ await require_resolve_allowlist.mutateGraphJson({
260
263
  token,
261
264
  path: `${basePath}/messages/${encodeURIComponent(params.messageId)}/unsetReaction`,
262
- body: { reactionType }
265
+ method: "POST",
266
+ body: { reactionType },
267
+ beta: true
263
268
  });
264
269
  return { ok: true };
265
270
  }
@@ -411,9 +416,10 @@ async function addParticipantMSTeams(params) {
411
416
  roles: resolveConversationMemberRoles(params.role, conv.kind),
412
417
  "user@odata.bind": `https://graph.microsoft.com/v1.0/users('${require_resolve_allowlist.escapeOData(params.userId)}')`
413
418
  };
414
- await require_resolve_allowlist.postGraphJson({
419
+ await require_resolve_allowlist.mutateGraphJson({
415
420
  token,
416
421
  path: `${conv.basePath}/members`,
422
+ method: "POST",
417
423
  body
418
424
  });
419
425
  return { added: {
@@ -450,9 +456,10 @@ async function renameGroupMSTeams(params) {
450
456
  const conversationId = await resolveGraphConversationId(params.to);
451
457
  const conv = resolveConversationPath(conversationId);
452
458
  const body = conv.kind === "chat" ? { topic: params.name } : { displayName: params.name };
453
- await require_resolve_allowlist.patchGraphJson({
459
+ await require_resolve_allowlist.mutateGraphJson({
454
460
  token,
455
461
  path: conv.basePath,
462
+ method: "PATCH",
456
463
  body
457
464
  });
458
465
  return { renamed: {
@@ -571,9 +578,9 @@ async function getChannelInfoMSTeams(params) {
571
578
  }
572
579
  //#endregion
573
580
  //#region extensions/msteams/src/send-context.ts
574
- function resolveMSTeamsProactiveReplyStyle(params) {
581
+ function resolveMSTeamsProactiveReplyTarget(params) {
575
582
  const threadRootId = params.ref.threadId ?? params.ref.activityId;
576
- if (params.conversationType !== "channel" || !threadRootId) return "top-level";
583
+ if (params.conversationType !== "channel" || !threadRootId) return { replyStyle: "top-level" };
577
584
  const routeConfig = require_channel.resolveMSTeamsRouteConfig({
578
585
  cfg: params.cfg,
579
586
  teamId: params.ref.teamId,
@@ -586,12 +593,16 @@ function resolveMSTeamsProactiveReplyStyle(params) {
586
593
  teamConfig: routeConfig.teamConfig,
587
594
  channelConfig: routeConfig.channelConfig
588
595
  });
589
- return replyStyle;
596
+ return replyStyle === "thread" ? {
597
+ replyStyle,
598
+ threadActivityId: threadRootId
599
+ } : { replyStyle };
590
600
  }
591
601
  /**
592
602
  * Parse the target value into a conversation reference lookup key.
593
603
  * Supported formats:
594
604
  * - conversation:19:abc@thread.tacv2 → lookup by conversation ID
605
+ * - conversation:19:abc@thread.tacv2;messageid=root → lookup base ID, use root
595
606
  * - user:aad-object-id → lookup by user AAD object ID
596
607
  * - 19:abc@thread.tacv2 → direct conversation ID
597
608
  */
@@ -600,6 +611,17 @@ function parseRecipient(to) {
600
611
  const finalize = (type, id) => {
601
612
  const normalized = id.trim();
602
613
  if (!normalized) throw new Error(`Invalid target value: missing ${type} id`);
614
+ if (type === "conversation") {
615
+ const threadId = require_resolve_allowlist.extractMSTeamsConversationMessageId(normalized);
616
+ const normalizedConversationId = require_resolve_allowlist.normalizeMSTeamsConversationId(normalized);
617
+ const slashIndex = normalizedConversationId.indexOf("/");
618
+ const graphChannelId = slashIndex > 0 ? normalizedConversationId.slice(slashIndex + 1) : void 0;
619
+ return {
620
+ type,
621
+ id: graphChannelId && (graphChannelId.startsWith("19:") || graphChannelId.includes("@thread")) ? graphChannelId : normalizedConversationId,
622
+ ...threadId ? { threadId } : {}
623
+ };
624
+ }
603
625
  return {
604
626
  type,
605
627
  id: normalized
@@ -641,7 +663,11 @@ async function resolveMSTeamsSendContext(params) {
641
663
  store
642
664
  });
643
665
  if (!found) throw new Error(`No conversation reference found for ${recipient.type}:${recipient.id}. The bot must receive a message from this conversation before it can send proactively.`);
644
- const { conversationId, ref } = found;
666
+ const conversationId = found.conversationId;
667
+ const ref = recipient.threadId ? {
668
+ ...found.ref,
669
+ threadId: recipient.threadId
670
+ } : found.ref;
645
671
  const log = require_runtime.getMSTeamsRuntime().logging.getChildLogger({ name: "msteams:send" });
646
672
  if (ref.serviceUrl && !require_resolve_allowlist.isAllowedBotFrameworkServiceUrl(ref.serviceUrl)) {
647
673
  try {
@@ -676,7 +702,10 @@ async function resolveMSTeamsSendContext(params) {
676
702
  if (storedConversationType === "personal") conversationType = "personal";
677
703
  else if (storedConversationType === "channel") conversationType = "channel";
678
704
  else conversationType = "groupChat";
679
- const replyStyle = resolveMSTeamsProactiveReplyStyle({
705
+ const replyTarget = recipient.threadId && conversationType === "channel" ? {
706
+ replyStyle: "thread",
707
+ threadActivityId: recipient.threadId
708
+ } : resolveMSTeamsProactiveReplyTarget({
680
709
  cfg: msteamsCfg,
681
710
  conversationId,
682
711
  ref: safeRef,
@@ -694,7 +723,7 @@ async function resolveMSTeamsSendContext(params) {
694
723
  app,
695
724
  log,
696
725
  conversationType,
697
- replyStyle,
726
+ ...replyTarget,
698
727
  sdkCloudOptions,
699
728
  tokenProvider,
700
729
  sharePointSiteId,
@@ -761,7 +790,7 @@ function createMSTeamsSendResult(params) {
761
790
  * - Group chats / channels: files require configured SharePoint storage
762
791
  */
763
792
  async function sendMessageMSTeams(params) {
764
- const { cfg, to, text, mediaUrl, filename, mediaLocalRoots, mediaReadFile } = params;
793
+ const { cfg, to, text, mediaUrl, filename, mediaAccess, mediaLocalRoots, mediaReadFile } = params;
765
794
  const tableMode = (0, openclaw_plugin_sdk_markdown_table_runtime.resolveMarkdownTableMode)({
766
795
  cfg,
767
796
  channel: "msteams"
@@ -771,7 +800,7 @@ async function sendMessageMSTeams(params) {
771
800
  cfg,
772
801
  to
773
802
  });
774
- const { app, conversationId, ref, log, conversationType, replyStyle, tokenProvider, sharePointSiteId, sdkCloudOptions } = ctx;
803
+ const { conversationId, log, conversationType, tokenProvider, sharePointSiteId } = ctx;
775
804
  log.debug?.("sending proactive message", {
776
805
  conversationId,
777
806
  conversationType,
@@ -781,6 +810,7 @@ async function sendMessageMSTeams(params) {
781
810
  if (mediaUrl) {
782
811
  const media = await (0, openclaw_plugin_sdk_outbound_media.loadOutboundMediaFromUrl)(mediaUrl, {
783
812
  maxBytes: ctx.mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES,
813
+ mediaAccess,
784
814
  mediaLocalRoots,
785
815
  mediaReadFile
786
816
  });
@@ -817,11 +847,9 @@ async function sendMessageMSTeams(params) {
817
847
  size: media.buffer.length
818
848
  });
819
849
  const messageId = await sendProactiveActivity({
820
- app,
821
- ref,
850
+ ctx,
822
851
  activity,
823
- errorPrefix: "msteams consent card send",
824
- serviceUrlBoundary: sdkCloudOptions
852
+ errorPrefix: "msteams consent card send"
825
853
  });
826
854
  require_messenger.setPendingUploadActivityId(uploadId, messageId);
827
855
  await require_messenger.setPendingUploadActivityIdFs(uploadId, messageId);
@@ -876,15 +904,12 @@ async function sendMessageMSTeams(params) {
876
904
  });
877
905
  const fileCardAttachment = require_messenger.buildTeamsFileInfoCard(driveItem);
878
906
  const messageId = await sendProactiveActivityRaw({
879
- app,
880
- ref,
907
+ ctx,
881
908
  activity: {
882
909
  type: "message",
883
910
  text: messageText || void 0,
884
911
  attachments: [fileCardAttachment]
885
- },
886
- threadActivityId: replyStyle === "thread" && conversationType === "channel" ? ref.threadId ?? ref.activityId : void 0,
887
- serviceUrlBoundary: sdkCloudOptions
912
+ }
888
913
  });
889
914
  log.info("sent native file card", {
890
915
  conversationId,
@@ -956,19 +981,18 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
956
981
  })
957
982
  };
958
983
  }
959
- async function sendProactiveActivityRaw({ app, ref, activity, threadActivityId, serviceUrlBoundary }) {
960
- return require_messenger.extractMessageId(await require_messenger.sendMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activity, {
961
- ...threadActivityId ? { threadActivityId } : {},
962
- serviceUrlBoundary
984
+ async function sendProactiveActivityRaw({ ctx, activity }) {
985
+ const baseRef = require_messenger.buildConversationReference(ctx.ref);
986
+ return require_messenger.extractMessageId(await require_messenger.sendMSTeamsActivityWithReference(ctx.app, baseRef, activity, {
987
+ ...ctx.threadActivityId ? { threadActivityId: ctx.threadActivityId } : {},
988
+ serviceUrlBoundary: ctx.sdkCloudOptions
963
989
  })) ?? "unknown";
964
990
  }
965
- async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceUrlBoundary }) {
991
+ async function sendProactiveActivity({ ctx, activity, errorPrefix }) {
966
992
  try {
967
993
  return await sendProactiveActivityRaw({
968
- app,
969
- ref,
970
- activity,
971
- serviceUrlBoundary
994
+ ctx,
995
+ activity
972
996
  });
973
997
  } catch (err) {
974
998
  const classification = require_setup_surface.classifyMSTeamsSendError(err);
@@ -982,10 +1006,11 @@ async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceU
982
1006
  */
983
1007
  async function sendPollMSTeams(params) {
984
1008
  const { cfg, to, question, options, maxSelections } = params;
985
- const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
1009
+ const ctx = await resolveMSTeamsSendContext({
986
1010
  cfg,
987
1011
  to
988
1012
  });
1013
+ const { conversationId, log } = ctx;
989
1014
  const pollCard = require_polls.buildMSTeamsPollCard({
990
1015
  question,
991
1016
  options,
@@ -997,8 +1022,7 @@ async function sendPollMSTeams(params) {
997
1022
  optionCount: pollCard.options.length
998
1023
  });
999
1024
  const messageId = await sendProactiveActivity({
1000
- app,
1001
- ref,
1025
+ ctx,
1002
1026
  activity: {
1003
1027
  type: "message",
1004
1028
  attachments: [{
@@ -1006,8 +1030,7 @@ async function sendPollMSTeams(params) {
1006
1030
  content: pollCard.card
1007
1031
  }]
1008
1032
  },
1009
- errorPrefix: "msteams poll send",
1010
- serviceUrlBoundary: sdkCloudOptions
1033
+ errorPrefix: "msteams poll send"
1011
1034
  });
1012
1035
  log.info("sent poll", {
1013
1036
  conversationId,
@@ -1025,18 +1048,18 @@ async function sendPollMSTeams(params) {
1025
1048
  */
1026
1049
  async function sendAdaptiveCardMSTeams(params) {
1027
1050
  const { cfg, to, card } = params;
1028
- const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
1051
+ const ctx = await resolveMSTeamsSendContext({
1029
1052
  cfg,
1030
1053
  to
1031
1054
  });
1055
+ const { conversationId, log } = ctx;
1032
1056
  log.debug?.("sending adaptive card", {
1033
1057
  conversationId,
1034
1058
  cardType: card.type,
1035
1059
  cardVersion: card.version
1036
1060
  });
1037
1061
  const messageId = await sendProactiveActivity({
1038
- app,
1039
- ref,
1062
+ ctx,
1040
1063
  activity: {
1041
1064
  type: "message",
1042
1065
  attachments: [{
@@ -1044,8 +1067,7 @@ async function sendAdaptiveCardMSTeams(params) {
1044
1067
  content: card
1045
1068
  }]
1046
1069
  },
1047
- errorPrefix: "msteams card send",
1048
- serviceUrlBoundary: sdkCloudOptions
1070
+ errorPrefix: "msteams card send"
1049
1071
  });
1050
1072
  log.info("sent adaptive card", {
1051
1073
  conversationId,
@@ -1127,6 +1149,13 @@ const MSTEAMS_TEXT_CHUNK_LIMIT = 4e3;
1127
1149
  function resolveMSTeamsEffectiveTextChunkLimit(configuredLimit) {
1128
1150
  return typeof configuredLimit === "number" && configuredLimit > 0 ? Math.min(configuredLimit, MSTEAMS_TEXT_CHUNK_LIMIT) : MSTEAMS_TEXT_CHUNK_LIMIT;
1129
1151
  }
1152
+ function resolveMSTeamsThreadTarget(to, threadId) {
1153
+ const normalizedThreadId = threadId == null ? "" : String(threadId).trim();
1154
+ const graphChannelId = to.includes("/") ? to.slice(to.indexOf("/") + 1) : "";
1155
+ const isConversationTarget = to.startsWith("conversation:") || to.startsWith("19:") || graphChannelId.startsWith("19:") || graphChannelId.includes("@thread");
1156
+ if (!normalizedThreadId || /(?:^|;)messageid=/iu.test(to) || !isConversationTarget) return to;
1157
+ return `${to};messageid=${normalizedThreadId}`;
1158
+ }
1130
1159
  function resolveMSTeamsTextSend(params) {
1131
1160
  return (0, openclaw_plugin_sdk_channel_outbound.resolveOutboundSendDep)(params.deps, "msteams") ?? ((to, text) => sendMessageMSTeams({
1132
1161
  cfg: params.cfg,
@@ -1139,9 +1168,7 @@ function resolveMSTeamsMediaSend(params) {
1139
1168
  cfg: params.cfg,
1140
1169
  to,
1141
1170
  text,
1142
- mediaUrl: opts?.mediaUrl,
1143
- mediaLocalRoots: opts?.mediaLocalRoots,
1144
- mediaReadFile: opts?.mediaReadFile
1171
+ ...opts
1145
1172
  }));
1146
1173
  }
1147
1174
  const msteamsOutbound = {
@@ -1176,11 +1203,12 @@ const msteamsOutbound = {
1176
1203
  }
1177
1204
  };
1178
1205
  },
1179
- sendPayload: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult }) => {
1206
+ sendPayload: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult, threadId }) => {
1207
+ const deliveryTarget = resolveMSTeamsThreadTarget(to, threadId);
1180
1208
  const presentationCard = (0, openclaw_plugin_sdk_string_coerce_runtime.asOptionalRecord)(payload.channelData?.msteams)?.presentationCard;
1181
1209
  if (presentationCard && typeof presentationCard === "object" && !Array.isArray(presentationCard)) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", await sendAdaptiveCardMSTeams({
1182
1210
  cfg,
1183
- to,
1211
+ to: deliveryTarget,
1184
1212
  card: presentationCard
1185
1213
  }));
1186
1214
  const mediaUrls = (0, openclaw_plugin_sdk_string_normalization_runtime.normalizeStringEntries)((0, openclaw_plugin_sdk_reply_payload.resolvePayloadMediaUrls)({
@@ -1198,8 +1226,9 @@ const msteamsOutbound = {
1198
1226
  onResult: async (deliveryResult) => {
1199
1227
  await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", deliveryResult));
1200
1228
  },
1201
- send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(to, textLocal, {
1229
+ send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(deliveryTarget, textLocal, {
1202
1230
  mediaUrl: mediaUrlLocal,
1231
+ mediaAccess,
1203
1232
  mediaLocalRoots,
1204
1233
  mediaReadFile
1205
1234
  })
@@ -1214,7 +1243,7 @@ const msteamsOutbound = {
1214
1243
  const chunks = (0, openclaw_plugin_sdk_reply_payload.resolveTextChunksWithFallback)(text, (0, openclaw_plugin_sdk_text_chunking.chunkTextForOutbound)(text, resolveMSTeamsEffectiveTextChunkLimit(cfg.channels?.msteams?.textChunkLimit)));
1215
1244
  let result;
1216
1245
  for (const chunk of chunks) {
1217
- result = await send(to, chunk);
1246
+ result = await send(deliveryTarget, chunk);
1218
1247
  await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result));
1219
1248
  }
1220
1249
  return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result);
@@ -1223,27 +1252,28 @@ const msteamsOutbound = {
1223
1252
  },
1224
1253
  ...(0, openclaw_plugin_sdk_channel_send_result.createAttachedChannelResultAdapter)({
1225
1254
  channel: "msteams",
1226
- sendText: async ({ cfg, to, text, deps }) => {
1255
+ sendText: async ({ cfg, to, text, deps, threadId }) => {
1227
1256
  return await resolveMSTeamsTextSend({
1228
1257
  cfg,
1229
1258
  deps
1230
- })(to, text);
1259
+ })(resolveMSTeamsThreadTarget(to, threadId), text);
1231
1260
  },
1232
- sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, deps }) => {
1261
+ sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, deps, threadId }) => {
1233
1262
  return await resolveMSTeamsMediaSend({
1234
1263
  cfg,
1235
1264
  deps
1236
- })(to, text, {
1265
+ })(resolveMSTeamsThreadTarget(to, threadId), text, {
1237
1266
  mediaUrl,
1267
+ mediaAccess,
1238
1268
  mediaLocalRoots,
1239
1269
  mediaReadFile
1240
1270
  });
1241
1271
  },
1242
- sendPoll: async ({ cfg, to, poll }) => {
1272
+ sendPoll: async ({ cfg, to, poll, threadId }) => {
1243
1273
  const maxSelections = poll.maxSelections ?? 1;
1244
1274
  const result = await sendPollMSTeams({
1245
1275
  cfg,
1246
- to,
1276
+ to: resolveMSTeamsThreadTarget(to, threadId),
1247
1277
  question: poll.question,
1248
1278
  options: poll.options,
1249
1279
  maxSelections
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./resolve-allowlist-CEj9sABO.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
3
3
  let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
4
4
  const msteamsDirectoryContractPlugin = {
5
5
  id: "msteams",
@@ -1,18 +1,18 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_polls = require("./polls-BWKNpBSg.cjs");
2
+ const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
3
3
  const require_delegated_state = require("./delegated-state-DiEz9JIa.cjs");
4
- const require_sso_token_store = require("./sso-token-store-TKYk_Ms7.cjs");
4
+ const require_polls = require("./polls-DvuJvaDG.cjs");
5
+ const require_sso_token_store = require("./sso-token-store-ChhO1f4i.cjs");
5
6
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
6
7
  let node_crypto = require("node:crypto");
7
- node_crypto = require_polls.__toESM(node_crypto, 1);
8
+ node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
8
9
  let node_fs_promises = require("node:fs/promises");
9
- node_fs_promises = require_polls.__toESM(node_fs_promises, 1);
10
+ node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises, 1);
10
11
  let node_path = require("node:path");
11
- node_path = require_polls.__toESM(node_path, 1);
12
- let openclaw_plugin_sdk_runtime_doctor = require("openclaw/plugin-sdk/runtime-doctor");
13
- let openclaw_plugin_sdk_session_store_runtime = require("openclaw/plugin-sdk/session-store-runtime");
12
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
13
+ let openclaw_plugin_sdk_runtime_doctor_migrations = require("openclaw/plugin-sdk/runtime-doctor-migrations");
14
14
  //#region extensions/msteams/doctor-contract-api.ts
15
- const streamingAliasMigration = (0, openclaw_plugin_sdk_runtime_doctor.defineChannelAliasMigration)({
15
+ const streamingAliasMigration = (0, openclaw_plugin_sdk_runtime_doctor_migrations.defineChannelAliasMigration)({
16
16
  channelId: "msteams",
17
17
  streaming: { defaultMode: "partial" }
18
18
  });
@@ -66,9 +66,10 @@ function listAgentIds(config) {
66
66
  for (const agent of config.agents?.list ?? []) if (typeof agent.id === "string" && agent.id.trim()) ids.add(agent.id.trim());
67
67
  return [...ids];
68
68
  }
69
- function listCandidateStorePaths(params) {
69
+ async function listCandidateStorePaths(params) {
70
+ const { resolveStorePath } = await import("openclaw/plugin-sdk/session-store-runtime");
70
71
  const paths = /* @__PURE__ */ new Set();
71
- for (const agentId of listAgentIds(params.config)) paths.add((0, openclaw_plugin_sdk_session_store_runtime.resolveStorePath)(params.config.session?.store, {
72
+ for (const agentId of listAgentIds(params.config)) paths.add(resolveStorePath(params.config.session?.store, {
72
73
  agentId,
73
74
  env: params.env
74
75
  }));
@@ -193,7 +194,7 @@ const stateMigrations = [
193
194
  if (await store.registerIfAbsent(require_polls.buildMSTeamsConversationStateKey(conversationId), require_polls.prepareMSTeamsConversationReferenceForStorage(conversationId, reference))) imported++;
194
195
  }
195
196
  changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} conversation ${imported === 1 ? "entry" : "entries"} -> plugin state`);
196
- await (0, openclaw_plugin_sdk_runtime_doctor.archiveLegacyStateSource)({
197
+ await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
197
198
  filePath,
198
199
  label: `${MSTEAMS_PLUGIN_ID} conversation`,
199
200
  changes,
@@ -259,7 +260,7 @@ const stateMigrations = [
259
260
  if (didImportPoll || importedVoteBucket) imported++;
260
261
  }
261
262
  changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} poll ${imported === 1 ? "entry" : "entries"} -> plugin state`);
262
- await (0, openclaw_plugin_sdk_runtime_doctor.archiveLegacyStateSource)({
263
+ await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
263
264
  filePath,
264
265
  label: `${MSTEAMS_PLUGIN_ID} poll`,
265
266
  changes,
@@ -304,7 +305,7 @@ const stateMigrations = [
304
305
  }
305
306
  changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} SSO token ${imported === 1 ? "entry" : "entries"} -> plugin state`);
306
307
  if (skipped > 0) warnings.push(`Skipped ${skipped} malformed ${MSTEAMS_PLUGIN_ID} SSO token ${skipped === 1 ? "entry" : "entries"} during migration`);
307
- await (0, openclaw_plugin_sdk_runtime_doctor.archiveLegacyStateSource)({
308
+ await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
308
309
  filePath,
309
310
  label: `${MSTEAMS_PLUGIN_ID} SSO-token`,
310
311
  changes,
@@ -383,7 +384,7 @@ const stateMigrations = [
383
384
  };
384
385
  }
385
386
  changes.push(`Migrated ${MSTEAMS_PLUGIN_ID} delegated OAuth token -> plugin state`);
386
- await (0, openclaw_plugin_sdk_runtime_doctor.archiveLegacyStateSource)({
387
+ await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
387
388
  filePath,
388
389
  label: `${MSTEAMS_PLUGIN_ID} delegated OAuth token`,
389
390
  changes,
@@ -399,14 +400,14 @@ const stateMigrations = [
399
400
  id: "msteams-feedback-learnings-json-to-plugin-state",
400
401
  label: "Microsoft Teams feedback learnings",
401
402
  async detectLegacyState(params) {
402
- const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
403
+ const files = (await Promise.all((await listCandidateStorePaths(params)).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
403
404
  if (files.length === 0) return null;
404
405
  return { preview: [`- Microsoft Teams feedback learnings: ${files.length} ${files.length === 1 ? "file" : "files"} -> plugin state (${LEARNINGS_NAMESPACE})`] };
405
406
  },
406
407
  async migrateLegacyState(params) {
407
408
  const changes = [];
408
409
  const warnings = [];
409
- const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
410
+ const files = (await Promise.all((await listCandidateStorePaths(params)).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
410
411
  const store = params.context.openPluginStateKeyedStore({
411
412
  namespace: LEARNINGS_NAMESPACE,
412
413
  maxEntries: MAX_LEARNING_ENTRIES
@@ -436,7 +437,7 @@ const stateMigrations = [
436
437
  updatedAt: Date.now()
437
438
  });
438
439
  imported++;
439
- await (0, openclaw_plugin_sdk_runtime_doctor.archiveLegacyStateSource)({
440
+ await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
440
441
  filePath: file.filePath,
441
442
  label: "Microsoft Teams feedback-learning",
442
443
  changes,
@@ -1,22 +1,24 @@
1
- const require_polls = require("./polls-BWKNpBSg.cjs");
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-CEj9sABO.cjs");
5
- const require_setup_surface = require("./setup-surface-ByWjaXEn.cjs");
4
+ const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
5
+ const require_setup_surface = require("./setup-surface-DAhGL2h8.cjs");
6
+ const require_polls = require("./polls-DvuJvaDG.cjs");
6
7
  let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
7
8
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
8
9
  let openclaw_plugin_sdk_reply_payload = require("openclaw/plugin-sdk/reply-payload");
9
10
  let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunking");
11
+ let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
10
12
  let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
11
13
  let node_dns_promises = require("node:dns/promises");
12
14
  let openclaw_plugin_sdk_ssrf_policy = require("openclaw/plugin-sdk/ssrf-policy");
13
15
  let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text-utility-runtime");
14
- let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
16
+ let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
15
17
  let node_crypto = require("node:crypto");
16
- node_crypto = require_polls.__toESM(node_crypto, 1);
18
+ node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
17
19
  let node_path = require("node:path");
18
- node_path = require_polls.__toESM(node_path, 1);
19
- let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
20
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
21
+ let openclaw_plugin_sdk_global_singleton = require("openclaw/plugin-sdk/global-singleton");
20
22
  let openclaw_plugin_sdk_reply_chunking = require("openclaw/plugin-sdk/reply-chunking");
21
23
  let openclaw_plugin_sdk_web_media = require("openclaw/plugin-sdk/web-media");
22
24
  let openclaw_plugin_sdk_media_runtime = require("openclaw/plugin-sdk/media-runtime");
@@ -449,9 +451,15 @@ async function setPendingUploadActivityIdFs(id, activityId, options) {
449
451
  * before upload. This module stores the file data temporarily until the user
450
452
  * accepts or declines, or until the TTL expires.
451
453
  */
452
- const pendingUploads = /* @__PURE__ */ new Map();
453
- /** Timer handles keyed by upload ID, cleared on explicit removal to prevent ghost cleanup */
454
- const pendingUploadTimers = /* @__PURE__ */ new Map();
454
+ const { pendingUploads, pendingUploadTimers } = (0, openclaw_plugin_sdk_global_singleton.resolveGlobalSingleton)(Symbol.for("openclaw.msteams.pendingUploadState"), () => ({
455
+ pendingUploads: /* @__PURE__ */ new Map(),
456
+ /** Timer handles keyed by upload ID, cleared on explicit removal to prevent ghost cleanup. */
457
+ pendingUploadTimers: /* @__PURE__ */ new Map()
458
+ }), (state) => {
459
+ for (const timer of state.pendingUploadTimers.values()) clearTimeout(timer);
460
+ state.pendingUploadTimers.clear();
461
+ state.pendingUploads.clear();
462
+ });
455
463
  /** TTL for pending uploads: 5 minutes */
456
464
  const PENDING_UPLOAD_TTL_MS = 300 * 1e3;
457
465
  /**
@@ -1088,13 +1096,14 @@ async function getGraphAccessToken(tokenProvider) {
1088
1096
  async function uploadToSharePoint(params) {
1089
1097
  const fetchFn = params.fetchFn ?? fetch;
1090
1098
  const uploadPath = `/OpenClawShared/${encodeURIComponent(params.filename)}`;
1099
+ const uploadUrl = `${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content?@microsoft.graph.conflictBehavior=rename`;
1091
1100
  const timeoutMs = require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length);
1092
1101
  const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
1093
1102
  label: SHAREPOINT_UPLOAD_TIMEOUT_LABEL,
1094
1103
  timeoutMs,
1095
1104
  work: async (signal) => {
1096
1105
  const token = await getGraphAccessToken(params.tokenProvider);
1097
- const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content`, {
1106
+ const res = await fetchFn(uploadUrl, {
1098
1107
  method: "PUT",
1099
1108
  headers: {
1100
1109
  "User-Agent": require_resolve_allowlist.buildUserAgent(),
@@ -1297,7 +1306,7 @@ async function extractFilename(url) {
1297
1306
  * Check if a URL refers to a local file path.
1298
1307
  */
1299
1308
  function isLocalPath(url) {
1300
- if (url.startsWith("file://") || url.startsWith("/") || url.startsWith("~")) return true;
1309
+ if (/^file:\/\//iu.test(url) || url.startsWith("/") || url.startsWith("~")) return true;
1301
1310
  if (url.startsWith("\\") && !url.startsWith("\\\\")) return true;
1302
1311
  if (/^[a-zA-Z]:[\\/]/.test(url)) return true;
1303
1312
  if (url.startsWith("\\\\")) return true;
@@ -1,4 +1,4 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-CEj9sABO.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.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");
@@ -6,9 +6,6 @@ let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env")
6
6
  function shouldUseManualOAuthFlow(isRemote) {
7
7
  return isRemote || (0, openclaw_plugin_sdk_runtime_env.isWSL2Sync)();
8
8
  }
9
- function generatePkce() {
10
- return (0, openclaw_plugin_sdk_provider_auth.generateHexPkceVerifierChallenge)();
11
- }
12
9
  function buildMSTeamsAuthUrl(params) {
13
10
  const scopes = params.scopes ?? require_resolve_allowlist.MSTEAMS_DEFAULT_DELEGATED_SCOPES;
14
11
  return `${require_resolve_allowlist.buildMSTeamsAuthEndpoint(params.tenantId)}?${new URLSearchParams({
@@ -22,24 +19,6 @@ function buildMSTeamsAuthUrl(params) {
22
19
  prompt: "consent"
23
20
  }).toString()}`;
24
21
  }
25
- function parseCallbackInput(input, _expectedState) {
26
- return (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(input, {
27
- missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
28
- invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
29
- });
30
- }
31
- async function waitForLocalCallback(params) {
32
- return await (0, openclaw_plugin_sdk_provider_auth_runtime.waitForLocalOAuthCallback)({
33
- expectedState: params.expectedState,
34
- timeoutMs: params.timeoutMs,
35
- port: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT,
36
- callbackPath: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PATH,
37
- redirectUri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
38
- successTitle: "MSTeams Delegated OAuth complete",
39
- progressMessage: `Waiting for OAuth callback on ${require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI}...`,
40
- onProgress: params.onProgress
41
- });
42
- }
43
22
  //#endregion
44
23
  //#region extensions/msteams/src/oauth.ts
45
24
  async function loginMSTeamsDelegated(ctx, params) {
@@ -54,7 +33,7 @@ async function loginMSTeamsDelegated(ctx, params) {
54
33
  `Sign in to grant delegated permissions for MSTeams.`,
55
34
  `The callback will be captured automatically on localhost:${require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT}.`
56
35
  ].join("\n"), "MSTeams Delegated OAuth");
57
- const { verifier, challenge } = generatePkce();
36
+ const { verifier, challenge } = (0, openclaw_plugin_sdk_provider_auth.generateHexPkceVerifierChallenge)();
58
37
  const state = (0, openclaw_plugin_sdk_provider_auth_runtime.generateOAuthState)();
59
38
  const authUrl = buildMSTeamsAuthUrl({
60
39
  tenantId: params.tenantId,
@@ -71,9 +50,14 @@ async function loginMSTeamsDelegated(ctx, params) {
71
50
  ctx.log(`\nOpen this URL in your browser:\n\n${authUrl}\n`);
72
51
  }
73
52
  try {
74
- const { code } = await waitForLocalCallback({
53
+ const { code } = await (0, openclaw_plugin_sdk_provider_auth_runtime.waitForLocalOAuthCallback)({
75
54
  expectedState: state,
76
55
  timeoutMs: 300 * 1e3,
56
+ port: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT,
57
+ callbackPath: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PATH,
58
+ redirectUri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
59
+ successTitle: "MSTeams Delegated OAuth complete",
60
+ progressMessage: `Waiting for OAuth callback on ${require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI}...`,
77
61
  onProgress: (msg) => ctx.progress.update(msg)
78
62
  });
79
63
  ctx.progress.update("Exchanging authorization code for tokens...");
@@ -97,7 +81,10 @@ async function manualFlow(ctx, authUrl, state, verifier, params, cause) {
97
81
  ctx.progress.update("OAuth URL ready");
98
82
  ctx.log(`\nOpen this URL in your LOCAL browser:\n\n${authUrl}\n`);
99
83
  ctx.progress.update("Waiting for you to paste the callback URL...");
100
- const parsed = parseCallbackInput(await ctx.prompt("Paste the redirect URL here: "), state);
84
+ const parsed = (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(await ctx.prompt("Paste the redirect URL here: "), {
85
+ missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
86
+ invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
87
+ });
101
88
  if ("error" in parsed) throw new Error(parsed.error, cause ? { cause } : void 0);
102
89
  if (parsed.state !== state) throw new Error("OAuth state mismatch - please try again", cause ? { cause } : void 0);
103
90
  ctx.progress.update("Exchanging authorization code for tokens...");