@openclaw/msteams 2026.7.2-beta.5 → 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,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_config_schema = require("./config-schema-BTnLgWAe.cjs");
2
+ const require_config_schema = require("./config-schema-C4CszdDi.cjs");
3
3
  exports.MSTeamsChannelConfigSchema = require_config_schema.MSTeamsChannelConfigSchema;
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./channel-DtZFlwhL.cjs");
2
+ const require_channel = require("./channel-DfCbi0d_.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-Dr_1sOJh.cjs");
4
- const require_channel = require("./channel-DtZFlwhL.cjs");
5
- const require_setup_surface = require("./setup-surface-xVejKCJV.cjs");
6
- const require_polls = require("./polls-CWExq2xZ.cjs");
7
- const require_messenger = require("./messenger-BJ0KM2sD.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, 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,14 +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
- serviceUrlBoundary: sdkCloudOptions
912
+ }
887
913
  });
888
914
  log.info("sent native file card", {
889
915
  conversationId,
@@ -955,16 +981,18 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
955
981
  })
956
982
  };
957
983
  }
958
- async function sendProactiveActivityRaw({ app, ref, activity, serviceUrlBoundary }) {
959
- return require_messenger.extractMessageId(await require_messenger.sendMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activity, { serviceUrlBoundary })) ?? "unknown";
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
989
+ })) ?? "unknown";
960
990
  }
961
- async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceUrlBoundary }) {
991
+ async function sendProactiveActivity({ ctx, activity, errorPrefix }) {
962
992
  try {
963
993
  return await sendProactiveActivityRaw({
964
- app,
965
- ref,
966
- activity,
967
- serviceUrlBoundary
994
+ ctx,
995
+ activity
968
996
  });
969
997
  } catch (err) {
970
998
  const classification = require_setup_surface.classifyMSTeamsSendError(err);
@@ -978,10 +1006,11 @@ async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceU
978
1006
  */
979
1007
  async function sendPollMSTeams(params) {
980
1008
  const { cfg, to, question, options, maxSelections } = params;
981
- const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
1009
+ const ctx = await resolveMSTeamsSendContext({
982
1010
  cfg,
983
1011
  to
984
1012
  });
1013
+ const { conversationId, log } = ctx;
985
1014
  const pollCard = require_polls.buildMSTeamsPollCard({
986
1015
  question,
987
1016
  options,
@@ -993,8 +1022,7 @@ async function sendPollMSTeams(params) {
993
1022
  optionCount: pollCard.options.length
994
1023
  });
995
1024
  const messageId = await sendProactiveActivity({
996
- app,
997
- ref,
1025
+ ctx,
998
1026
  activity: {
999
1027
  type: "message",
1000
1028
  attachments: [{
@@ -1002,8 +1030,7 @@ async function sendPollMSTeams(params) {
1002
1030
  content: pollCard.card
1003
1031
  }]
1004
1032
  },
1005
- errorPrefix: "msteams poll send",
1006
- serviceUrlBoundary: sdkCloudOptions
1033
+ errorPrefix: "msteams poll send"
1007
1034
  });
1008
1035
  log.info("sent poll", {
1009
1036
  conversationId,
@@ -1021,18 +1048,18 @@ async function sendPollMSTeams(params) {
1021
1048
  */
1022
1049
  async function sendAdaptiveCardMSTeams(params) {
1023
1050
  const { cfg, to, card } = params;
1024
- const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
1051
+ const ctx = await resolveMSTeamsSendContext({
1025
1052
  cfg,
1026
1053
  to
1027
1054
  });
1055
+ const { conversationId, log } = ctx;
1028
1056
  log.debug?.("sending adaptive card", {
1029
1057
  conversationId,
1030
1058
  cardType: card.type,
1031
1059
  cardVersion: card.version
1032
1060
  });
1033
1061
  const messageId = await sendProactiveActivity({
1034
- app,
1035
- ref,
1062
+ ctx,
1036
1063
  activity: {
1037
1064
  type: "message",
1038
1065
  attachments: [{
@@ -1040,8 +1067,7 @@ async function sendAdaptiveCardMSTeams(params) {
1040
1067
  content: card
1041
1068
  }]
1042
1069
  },
1043
- errorPrefix: "msteams card send",
1044
- serviceUrlBoundary: sdkCloudOptions
1070
+ errorPrefix: "msteams card send"
1045
1071
  });
1046
1072
  log.info("sent adaptive card", {
1047
1073
  conversationId,
@@ -1119,10 +1145,17 @@ async function deleteMessageMSTeams(params) {
1119
1145
  }
1120
1146
  //#endregion
1121
1147
  //#region extensions/msteams/src/outbound.ts
1122
- function asObjectRecord(value) {
1123
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1124
- }
1125
1148
  const MSTEAMS_TEXT_CHUNK_LIMIT = 4e3;
1149
+ function resolveMSTeamsEffectiveTextChunkLimit(configuredLimit) {
1150
+ return typeof configuredLimit === "number" && configuredLimit > 0 ? Math.min(configuredLimit, MSTEAMS_TEXT_CHUNK_LIMIT) : MSTEAMS_TEXT_CHUNK_LIMIT;
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
+ }
1126
1159
  function resolveMSTeamsTextSend(params) {
1127
1160
  return (0, openclaw_plugin_sdk_channel_outbound.resolveOutboundSendDep)(params.deps, "msteams") ?? ((to, text) => sendMessageMSTeams({
1128
1161
  cfg: params.cfg,
@@ -1135,9 +1168,7 @@ function resolveMSTeamsMediaSend(params) {
1135
1168
  cfg: params.cfg,
1136
1169
  to,
1137
1170
  text,
1138
- mediaUrl: opts?.mediaUrl,
1139
- mediaLocalRoots: opts?.mediaLocalRoots,
1140
- mediaReadFile: opts?.mediaReadFile
1171
+ ...opts
1141
1172
  }));
1142
1173
  }
1143
1174
  const msteamsOutbound = {
@@ -1145,6 +1176,7 @@ const msteamsOutbound = {
1145
1176
  chunker: openclaw_plugin_sdk_text_chunking.chunkTextForOutbound,
1146
1177
  chunkerMode: "markdown",
1147
1178
  textChunkLimit: MSTEAMS_TEXT_CHUNK_LIMIT,
1179
+ resolveEffectiveTextChunkLimit: ({ fallbackLimit }) => resolveMSTeamsEffectiveTextChunkLimit(fallbackLimit),
1148
1180
  pollMaxOptions: 12,
1149
1181
  deliveryCapabilities: { durableFinal: {
1150
1182
  text: true,
@@ -1159,7 +1191,7 @@ const msteamsOutbound = {
1159
1191
  presentation,
1160
1192
  text: payload.text
1161
1193
  });
1162
- const msteamsData = asObjectRecord(payload.channelData?.msteams) ?? {};
1194
+ const msteamsData = (0, openclaw_plugin_sdk_string_coerce_runtime.asOptionalRecord)(payload.channelData?.msteams) ?? {};
1163
1195
  return {
1164
1196
  ...payload,
1165
1197
  channelData: {
@@ -1171,11 +1203,12 @@ const msteamsOutbound = {
1171
1203
  }
1172
1204
  };
1173
1205
  },
1174
- sendPayload: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult }) => {
1175
- const presentationCard = asObjectRecord(payload.channelData?.msteams)?.presentationCard;
1206
+ sendPayload: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult, threadId }) => {
1207
+ const deliveryTarget = resolveMSTeamsThreadTarget(to, threadId);
1208
+ const presentationCard = (0, openclaw_plugin_sdk_string_coerce_runtime.asOptionalRecord)(payload.channelData?.msteams)?.presentationCard;
1176
1209
  if (presentationCard && typeof presentationCard === "object" && !Array.isArray(presentationCard)) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", await sendAdaptiveCardMSTeams({
1177
1210
  cfg,
1178
- to,
1211
+ to: deliveryTarget,
1179
1212
  card: presentationCard
1180
1213
  }));
1181
1214
  const mediaUrls = (0, openclaw_plugin_sdk_string_normalization_runtime.normalizeStringEntries)((0, openclaw_plugin_sdk_reply_payload.resolvePayloadMediaUrls)({
@@ -1193,8 +1226,9 @@ const msteamsOutbound = {
1193
1226
  onResult: async (deliveryResult) => {
1194
1227
  await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", deliveryResult));
1195
1228
  },
1196
- send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(to, textLocal, {
1229
+ send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(deliveryTarget, textLocal, {
1197
1230
  mediaUrl: mediaUrlLocal,
1231
+ mediaAccess,
1198
1232
  mediaLocalRoots,
1199
1233
  mediaReadFile
1200
1234
  })
@@ -1206,10 +1240,10 @@ const msteamsOutbound = {
1206
1240
  cfg,
1207
1241
  deps
1208
1242
  });
1209
- const chunks = (0, openclaw_plugin_sdk_reply_payload.resolveTextChunksWithFallback)(text, (0, openclaw_plugin_sdk_text_chunking.chunkTextForOutbound)(text, MSTEAMS_TEXT_CHUNK_LIMIT));
1243
+ const chunks = (0, openclaw_plugin_sdk_reply_payload.resolveTextChunksWithFallback)(text, (0, openclaw_plugin_sdk_text_chunking.chunkTextForOutbound)(text, resolveMSTeamsEffectiveTextChunkLimit(cfg.channels?.msteams?.textChunkLimit)));
1210
1244
  let result;
1211
1245
  for (const chunk of chunks) {
1212
- result = await send(to, chunk);
1246
+ result = await send(deliveryTarget, chunk);
1213
1247
  await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result));
1214
1248
  }
1215
1249
  return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result);
@@ -1218,27 +1252,28 @@ const msteamsOutbound = {
1218
1252
  },
1219
1253
  ...(0, openclaw_plugin_sdk_channel_send_result.createAttachedChannelResultAdapter)({
1220
1254
  channel: "msteams",
1221
- sendText: async ({ cfg, to, text, deps }) => {
1255
+ sendText: async ({ cfg, to, text, deps, threadId }) => {
1222
1256
  return await resolveMSTeamsTextSend({
1223
1257
  cfg,
1224
1258
  deps
1225
- })(to, text);
1259
+ })(resolveMSTeamsThreadTarget(to, threadId), text);
1226
1260
  },
1227
- sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, deps }) => {
1261
+ sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, deps, threadId }) => {
1228
1262
  return await resolveMSTeamsMediaSend({
1229
1263
  cfg,
1230
1264
  deps
1231
- })(to, text, {
1265
+ })(resolveMSTeamsThreadTarget(to, threadId), text, {
1232
1266
  mediaUrl,
1267
+ mediaAccess,
1233
1268
  mediaLocalRoots,
1234
1269
  mediaReadFile
1235
1270
  });
1236
1271
  },
1237
- sendPoll: async ({ cfg, to, poll }) => {
1272
+ sendPoll: async ({ cfg, to, poll, threadId }) => {
1238
1273
  const maxSelections = poll.maxSelections ?? 1;
1239
1274
  const result = await sendPollMSTeams({
1240
1275
  cfg,
1241
- to,
1276
+ to: resolveMSTeamsThreadTarget(to, threadId),
1242
1277
  question: poll.question,
1243
1278
  options: poll.options,
1244
1279
  maxSelections
@@ -1,3 +1,4 @@
1
+ let openclaw_plugin_sdk_channel_core = require("openclaw/plugin-sdk/channel-core");
1
2
  let openclaw_plugin_sdk_secret_input = require("openclaw/plugin-sdk/secret-input");
2
3
  let openclaw_plugin_sdk_channel_config_schema = require("openclaw/plugin-sdk/channel-config-schema");
3
4
  let zod = require("zod");
@@ -23,34 +24,17 @@ const msTeamsChannelConfigUiHints = {
23
24
  label: "MS Teams Graph Media Fallback",
24
25
  help: "Query Microsoft Graph for unresolved channel or group-chat HTML media. Adds one lookup per matching message when enabled (default: false)."
25
26
  },
26
- streaming: {
27
- label: "MS Teams Streaming",
28
- help: "Microsoft Teams preview/progress streaming mode: \"off\" | \"partial\" | \"block\" | \"progress\". Personal chats use Teams native streaminfo progress when available."
29
- },
30
- "streaming.progress.label": {
31
- label: "MS Teams Progress Label",
32
- help: "Initial progress title. Use \"auto\" for built-in single-word labels, a custom string, or false to hide the title."
33
- },
34
- "streaming.progress.labels": {
35
- label: "MS Teams Progress Label Pool",
36
- help: "Candidate labels for streaming.progress.label=\"auto\". Leave unset to use OpenClaw built-in progress labels."
37
- },
38
- "streaming.progress.maxLines": {
39
- label: "MS Teams Progress Max Lines",
40
- help: "Maximum number of compact progress lines to keep below the progress title (default: 8)."
41
- },
42
- "streaming.progress.maxLineChars": {
43
- label: "MS Teams Progress Max Line Chars",
44
- help: "Maximum characters per compact progress line before truncation (default: 120). Prose cuts at word boundaries; commands and paths keep useful suffixes."
45
- },
46
- "streaming.progress.toolProgress": {
47
- label: "MS Teams Progress Tool Lines",
48
- help: "Show compact tool/progress lines in progress mode (default: true). Set false to keep only the title until final delivery."
49
- },
50
- "streaming.progress.commandText": {
51
- label: "MS Teams Progress Command Text",
52
- help: "Command/exec detail in progress lines: \"raw\" preserves released behavior; \"status\" shows only the tool label."
53
- }
27
+ ...(0, openclaw_plugin_sdk_channel_core.createChannelConfigUiHints)({
28
+ channelLabel: "MS Teams",
29
+ streaming: { "": {
30
+ label: "MS Teams Streaming",
31
+ help: "Microsoft Teams preview/progress streaming mode: \"off\" | \"partial\" | \"block\" | \"progress\". Personal chats use Teams native streaminfo progress when available."
32
+ } },
33
+ progress: {
34
+ labels: "openclaw",
35
+ titleWording: true
36
+ }
37
+ })
54
38
  };
55
39
  //#endregion
56
40
  //#region extensions/msteams/src/config-schema.ts
@@ -1,25 +1,3 @@
1
- //#region \0rolldown/runtime.js
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
- //#endregion
23
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
24
2
  //#region extensions/msteams/src/delegated-state.ts
25
3
  const MSTEAMS_DELEGATED_TOKEN_LEGACY_FILENAME = "msteams-delegated.json";
@@ -72,12 +50,6 @@ Object.defineProperty(exports, "MSTEAMS_DELEGATED_TOKEN_NAMESPACE", {
72
50
  return MSTEAMS_DELEGATED_TOKEN_NAMESPACE;
73
51
  }
74
52
  });
75
- Object.defineProperty(exports, "__toESM", {
76
- enumerable: true,
77
- get: function() {
78
- return __toESM;
79
- }
80
- });
81
53
  Object.defineProperty(exports, "loadMSTeamsDelegatedTokens", {
82
54
  enumerable: true,
83
55
  get: function() {
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./resolve-allowlist-Dr_1sOJh.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_delegated_state = require("./delegated-state-DOSCHaAB.cjs");
3
- const require_polls = require("./polls-CWExq2xZ.cjs");
4
- const require_sso_token_store = require("./sso-token-store-OSg229re.cjs");
2
+ const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
3
+ const require_delegated_state = require("./delegated-state-DiEz9JIa.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_delegated_state.__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_delegated_state.__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_delegated_state.__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,