@openclaw/msteams 2026.7.2-beta.7 → 2026.8.1-beta.3
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/adapter.runtime-8g-MOPfb.cjs +311 -0
- package/dist/api.cjs +6 -6
- package/dist/{channel-C7QxRjBW.cjs → channel-KpWENcgK.cjs} +222 -265
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/{channel.runtime-DjY6d_hd.cjs → channel.runtime-Bkzj8jZ0.cjs} +131 -88
- package/dist/{setup-surface-ByWjaXEn.cjs → channel.setup-mOFtsfYz.cjs} +91 -50
- package/dist/directory-contract-api.cjs +1 -1
- package/dist/doctor-contract-api.cjs +18 -17
- package/dist/{messenger-DTiaLTDO.cjs → messenger-IISPSOvj.cjs} +61 -46
- package/dist/{oauth-CW6jVGp8.cjs → oauth-C9So7uld.cjs} +13 -26
- package/dist/{polls-BWKNpBSg.cjs → polls-DvuJvaDG.cjs} +6 -39
- package/dist/qa-runner-api.cjs +36 -0
- package/dist/{resolve-allowlist-CEj9sABO.cjs → resolve-allowlist-CIfWUwuc.cjs} +182 -118
- package/dist/rolldown-runtime-D6vf50IK.cjs +28 -0
- package/dist/runtime-api.cjs +1 -1
- package/dist/secret-contract-api.cjs +6 -30
- package/dist/setup-plugin-api.cjs +2 -37
- package/dist/{src-B_BdEvcr.cjs → src-C127-DcQ.cjs} +439 -269
- package/dist/{sso-token-store-TKYk_Ms7.cjs → sso-token-store-ChhO1f4i.cjs} +1 -1
- package/openclaw.plugin.json +34 -8
- package/package.json +4 -5
|
@@ -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-
|
|
5
|
-
const require_channel = require("./channel-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
3
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
|
|
4
|
+
const require_channel = require("./channel-KpWENcgK.cjs");
|
|
5
|
+
const require_channel_setup = require("./channel.setup-mOFtsfYz.cjs");
|
|
6
|
+
const require_polls = require("./polls-DvuJvaDG.cjs");
|
|
7
|
+
const require_messenger = require("./messenger-IISPSOvj.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.
|
|
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.
|
|
243
|
+
await require_resolve_allowlist.mutateGraphJson({
|
|
243
244
|
token,
|
|
244
245
|
path: `${basePath}/messages/${encodeURIComponent(params.messageId)}/setReaction`,
|
|
245
|
-
|
|
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.
|
|
262
|
+
await require_resolve_allowlist.mutateGraphJson({
|
|
260
263
|
token,
|
|
261
264
|
path: `${basePath}/messages/${encodeURIComponent(params.messageId)}/unsetReaction`,
|
|
262
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
@@ -632,6 +654,9 @@ async function findConversationReference(recipient) {
|
|
|
632
654
|
async function resolveMSTeamsSendContext(params) {
|
|
633
655
|
const msteamsCfg = params.cfg.channels?.msteams;
|
|
634
656
|
if (!msteamsCfg?.enabled) throw new Error("msteams provider is not enabled");
|
|
657
|
+
const account = require_channel_setup.resolveMSTeamsAccount(params.cfg);
|
|
658
|
+
if (account.tokenStatus === "configured_unavailable") throw new Error("msteams credential file is configured but unavailable");
|
|
659
|
+
if (!account.configured) throw new Error("msteams credentials not configured");
|
|
635
660
|
const creds = require_resolve_allowlist.resolveMSTeamsCredentials(msteamsCfg);
|
|
636
661
|
if (!creds) throw new Error("msteams credentials not configured");
|
|
637
662
|
const store = require_polls.createMSTeamsConversationStoreState();
|
|
@@ -641,7 +666,11 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
641
666
|
store
|
|
642
667
|
});
|
|
643
668
|
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
|
|
669
|
+
const conversationId = found.conversationId;
|
|
670
|
+
const ref = recipient.threadId ? {
|
|
671
|
+
...found.ref,
|
|
672
|
+
threadId: recipient.threadId
|
|
673
|
+
} : found.ref;
|
|
645
674
|
const log = require_runtime.getMSTeamsRuntime().logging.getChildLogger({ name: "msteams:send" });
|
|
646
675
|
if (ref.serviceUrl && !require_resolve_allowlist.isAllowedBotFrameworkServiceUrl(ref.serviceUrl)) {
|
|
647
676
|
try {
|
|
@@ -649,7 +678,7 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
649
678
|
} catch (err) {
|
|
650
679
|
log.warn?.("failed to remove blocked msteams conversation reference", {
|
|
651
680
|
conversationId,
|
|
652
|
-
error:
|
|
681
|
+
error: require_channel_setup.formatUnknownError(err)
|
|
653
682
|
});
|
|
654
683
|
}
|
|
655
684
|
throw new Error(`Stored Microsoft Teams conversation reference has blocked serviceUrl host: ${require_resolve_allowlist.describeBotFrameworkServiceUrlHost(ref.serviceUrl)}. The bot must receive a new message from this conversation before it can send proactively.`);
|
|
@@ -676,7 +705,10 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
676
705
|
if (storedConversationType === "personal") conversationType = "personal";
|
|
677
706
|
else if (storedConversationType === "channel") conversationType = "channel";
|
|
678
707
|
else conversationType = "groupChat";
|
|
679
|
-
const
|
|
708
|
+
const replyTarget = recipient.threadId && conversationType === "channel" ? {
|
|
709
|
+
replyStyle: "thread",
|
|
710
|
+
threadActivityId: recipient.threadId
|
|
711
|
+
} : resolveMSTeamsProactiveReplyTarget({
|
|
680
712
|
cfg: msteamsCfg,
|
|
681
713
|
conversationId,
|
|
682
714
|
ref: safeRef,
|
|
@@ -694,7 +726,7 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
694
726
|
app,
|
|
695
727
|
log,
|
|
696
728
|
conversationType,
|
|
697
|
-
|
|
729
|
+
...replyTarget,
|
|
698
730
|
sdkCloudOptions,
|
|
699
731
|
tokenProvider,
|
|
700
732
|
sharePointSiteId,
|
|
@@ -761,7 +793,7 @@ function createMSTeamsSendResult(params) {
|
|
|
761
793
|
* - Group chats / channels: files require configured SharePoint storage
|
|
762
794
|
*/
|
|
763
795
|
async function sendMessageMSTeams(params) {
|
|
764
|
-
const { cfg, to, text, mediaUrl, filename, mediaLocalRoots, mediaReadFile } = params;
|
|
796
|
+
const { cfg, to, text, mediaUrl, filename, mediaAccess, mediaLocalRoots, mediaReadFile } = params;
|
|
765
797
|
const tableMode = (0, openclaw_plugin_sdk_markdown_table_runtime.resolveMarkdownTableMode)({
|
|
766
798
|
cfg,
|
|
767
799
|
channel: "msteams"
|
|
@@ -771,7 +803,7 @@ async function sendMessageMSTeams(params) {
|
|
|
771
803
|
cfg,
|
|
772
804
|
to
|
|
773
805
|
});
|
|
774
|
-
const {
|
|
806
|
+
const { conversationId, log, conversationType, tokenProvider, sharePointSiteId } = ctx;
|
|
775
807
|
log.debug?.("sending proactive message", {
|
|
776
808
|
conversationId,
|
|
777
809
|
conversationType,
|
|
@@ -781,6 +813,7 @@ async function sendMessageMSTeams(params) {
|
|
|
781
813
|
if (mediaUrl) {
|
|
782
814
|
const media = await (0, openclaw_plugin_sdk_outbound_media.loadOutboundMediaFromUrl)(mediaUrl, {
|
|
783
815
|
maxBytes: ctx.mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES,
|
|
816
|
+
mediaAccess,
|
|
784
817
|
mediaLocalRoots,
|
|
785
818
|
mediaReadFile
|
|
786
819
|
});
|
|
@@ -817,11 +850,9 @@ async function sendMessageMSTeams(params) {
|
|
|
817
850
|
size: media.buffer.length
|
|
818
851
|
});
|
|
819
852
|
const messageId = await sendProactiveActivity({
|
|
820
|
-
|
|
821
|
-
ref,
|
|
853
|
+
ctx,
|
|
822
854
|
activity,
|
|
823
|
-
errorPrefix: "msteams consent card send"
|
|
824
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
855
|
+
errorPrefix: "msteams consent card send"
|
|
825
856
|
});
|
|
826
857
|
require_messenger.setPendingUploadActivityId(uploadId, messageId);
|
|
827
858
|
await require_messenger.setPendingUploadActivityIdFs(uploadId, messageId);
|
|
@@ -876,15 +907,12 @@ async function sendMessageMSTeams(params) {
|
|
|
876
907
|
});
|
|
877
908
|
const fileCardAttachment = require_messenger.buildTeamsFileInfoCard(driveItem);
|
|
878
909
|
const messageId = await sendProactiveActivityRaw({
|
|
879
|
-
|
|
880
|
-
ref,
|
|
910
|
+
ctx,
|
|
881
911
|
activity: {
|
|
882
912
|
type: "message",
|
|
883
913
|
text: messageText || void 0,
|
|
884
914
|
attachments: [fileCardAttachment]
|
|
885
|
-
}
|
|
886
|
-
threadActivityId: replyStyle === "thread" && conversationType === "channel" ? ref.threadId ?? ref.activityId : void 0,
|
|
887
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
915
|
+
}
|
|
888
916
|
});
|
|
889
917
|
log.info("sent native file card", {
|
|
890
918
|
conversationId,
|
|
@@ -897,10 +925,10 @@ async function sendMessageMSTeams(params) {
|
|
|
897
925
|
kind: "media"
|
|
898
926
|
});
|
|
899
927
|
} catch (err) {
|
|
900
|
-
const classification =
|
|
901
|
-
const hint =
|
|
928
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(err);
|
|
929
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
902
930
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
903
|
-
throw new Error(`msteams file send failed${status}: ${
|
|
931
|
+
throw new Error(`msteams file send failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
904
932
|
}
|
|
905
933
|
}
|
|
906
934
|
return sendTextWithMedia(ctx, messageText, void 0);
|
|
@@ -935,10 +963,10 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
|
935
963
|
serviceUrlBoundary: ctx.sdkCloudOptions
|
|
936
964
|
});
|
|
937
965
|
} catch (err) {
|
|
938
|
-
const classification =
|
|
939
|
-
const hint =
|
|
966
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(err);
|
|
967
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
940
968
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
941
|
-
throw new Error(`msteams send failed${status}: ${
|
|
969
|
+
throw new Error(`msteams send failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
942
970
|
}
|
|
943
971
|
const messageId = platformMessageIds[0] ?? "unknown";
|
|
944
972
|
log.info("sent proactive message", {
|
|
@@ -956,25 +984,24 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
|
956
984
|
})
|
|
957
985
|
};
|
|
958
986
|
}
|
|
959
|
-
async function sendProactiveActivityRaw({
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
987
|
+
async function sendProactiveActivityRaw({ ctx, activity }) {
|
|
988
|
+
const baseRef = require_messenger.buildConversationReference(ctx.ref);
|
|
989
|
+
return require_messenger.extractMessageId(await require_messenger.sendMSTeamsActivityWithReference(ctx.app, baseRef, activity, {
|
|
990
|
+
...ctx.threadActivityId ? { threadActivityId: ctx.threadActivityId } : {},
|
|
991
|
+
serviceUrlBoundary: ctx.sdkCloudOptions
|
|
963
992
|
})) ?? "unknown";
|
|
964
993
|
}
|
|
965
|
-
async function sendProactiveActivity({
|
|
994
|
+
async function sendProactiveActivity({ ctx, activity, errorPrefix }) {
|
|
966
995
|
try {
|
|
967
996
|
return await sendProactiveActivityRaw({
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
activity,
|
|
971
|
-
serviceUrlBoundary
|
|
997
|
+
ctx,
|
|
998
|
+
activity
|
|
972
999
|
});
|
|
973
1000
|
} catch (err) {
|
|
974
|
-
const classification =
|
|
975
|
-
const hint =
|
|
1001
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(err);
|
|
1002
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
976
1003
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
977
|
-
throw new Error(`${errorPrefix} failed${status}: ${
|
|
1004
|
+
throw new Error(`${errorPrefix} failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
978
1005
|
}
|
|
979
1006
|
}
|
|
980
1007
|
/**
|
|
@@ -982,10 +1009,11 @@ async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceU
|
|
|
982
1009
|
*/
|
|
983
1010
|
async function sendPollMSTeams(params) {
|
|
984
1011
|
const { cfg, to, question, options, maxSelections } = params;
|
|
985
|
-
const
|
|
1012
|
+
const ctx = await resolveMSTeamsSendContext({
|
|
986
1013
|
cfg,
|
|
987
1014
|
to
|
|
988
1015
|
});
|
|
1016
|
+
const { conversationId, log } = ctx;
|
|
989
1017
|
const pollCard = require_polls.buildMSTeamsPollCard({
|
|
990
1018
|
question,
|
|
991
1019
|
options,
|
|
@@ -997,8 +1025,7 @@ async function sendPollMSTeams(params) {
|
|
|
997
1025
|
optionCount: pollCard.options.length
|
|
998
1026
|
});
|
|
999
1027
|
const messageId = await sendProactiveActivity({
|
|
1000
|
-
|
|
1001
|
-
ref,
|
|
1028
|
+
ctx,
|
|
1002
1029
|
activity: {
|
|
1003
1030
|
type: "message",
|
|
1004
1031
|
attachments: [{
|
|
@@ -1006,8 +1033,7 @@ async function sendPollMSTeams(params) {
|
|
|
1006
1033
|
content: pollCard.card
|
|
1007
1034
|
}]
|
|
1008
1035
|
},
|
|
1009
|
-
errorPrefix: "msteams poll send"
|
|
1010
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1036
|
+
errorPrefix: "msteams poll send"
|
|
1011
1037
|
});
|
|
1012
1038
|
log.info("sent poll", {
|
|
1013
1039
|
conversationId,
|
|
@@ -1025,18 +1051,18 @@ async function sendPollMSTeams(params) {
|
|
|
1025
1051
|
*/
|
|
1026
1052
|
async function sendAdaptiveCardMSTeams(params) {
|
|
1027
1053
|
const { cfg, to, card } = params;
|
|
1028
|
-
const
|
|
1054
|
+
const ctx = await resolveMSTeamsSendContext({
|
|
1029
1055
|
cfg,
|
|
1030
1056
|
to
|
|
1031
1057
|
});
|
|
1058
|
+
const { conversationId, log } = ctx;
|
|
1032
1059
|
log.debug?.("sending adaptive card", {
|
|
1033
1060
|
conversationId,
|
|
1034
1061
|
cardType: card.type,
|
|
1035
1062
|
cardVersion: card.version
|
|
1036
1063
|
});
|
|
1037
1064
|
const messageId = await sendProactiveActivity({
|
|
1038
|
-
|
|
1039
|
-
ref,
|
|
1065
|
+
ctx,
|
|
1040
1066
|
activity: {
|
|
1041
1067
|
type: "message",
|
|
1042
1068
|
attachments: [{
|
|
@@ -1044,8 +1070,7 @@ async function sendAdaptiveCardMSTeams(params) {
|
|
|
1044
1070
|
content: card
|
|
1045
1071
|
}]
|
|
1046
1072
|
},
|
|
1047
|
-
errorPrefix: "msteams card send"
|
|
1048
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1073
|
+
errorPrefix: "msteams card send"
|
|
1049
1074
|
});
|
|
1050
1075
|
log.info("sent adaptive card", {
|
|
1051
1076
|
conversationId,
|
|
@@ -1080,10 +1105,10 @@ async function editMessageMSTeams(params) {
|
|
|
1080
1105
|
text
|
|
1081
1106
|
}, { serviceUrlBoundary: sdkCloudOptions });
|
|
1082
1107
|
} catch (err) {
|
|
1083
|
-
const classification =
|
|
1084
|
-
const hint =
|
|
1108
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(err);
|
|
1109
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
1085
1110
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1086
|
-
throw new Error(`msteams edit failed${status}: ${
|
|
1111
|
+
throw new Error(`msteams edit failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1087
1112
|
}
|
|
1088
1113
|
log.info("edited proactive message", {
|
|
1089
1114
|
conversationId,
|
|
@@ -1110,10 +1135,10 @@ async function deleteMessageMSTeams(params) {
|
|
|
1110
1135
|
try {
|
|
1111
1136
|
await require_messenger.deleteMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activityId, { serviceUrlBoundary: sdkCloudOptions });
|
|
1112
1137
|
} catch (err) {
|
|
1113
|
-
const classification =
|
|
1114
|
-
const hint =
|
|
1138
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(err);
|
|
1139
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
1115
1140
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1116
|
-
throw new Error(`msteams delete failed${status}: ${
|
|
1141
|
+
throw new Error(`msteams delete failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1117
1142
|
}
|
|
1118
1143
|
log.info("deleted proactive message", {
|
|
1119
1144
|
conversationId,
|
|
@@ -1127,6 +1152,23 @@ const MSTEAMS_TEXT_CHUNK_LIMIT = 4e3;
|
|
|
1127
1152
|
function resolveMSTeamsEffectiveTextChunkLimit(configuredLimit) {
|
|
1128
1153
|
return typeof configuredLimit === "number" && configuredLimit > 0 ? Math.min(configuredLimit, MSTEAMS_TEXT_CHUNK_LIMIT) : MSTEAMS_TEXT_CHUNK_LIMIT;
|
|
1129
1154
|
}
|
|
1155
|
+
function toMSTeamsOutboundResult(result) {
|
|
1156
|
+
const { conversationId, ...delivery } = result;
|
|
1157
|
+
return {
|
|
1158
|
+
...delivery,
|
|
1159
|
+
target: {
|
|
1160
|
+
kind: "conversation",
|
|
1161
|
+
id: conversationId
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
function resolveMSTeamsThreadTarget(to, threadId) {
|
|
1166
|
+
const normalizedThreadId = threadId == null ? "" : String(threadId).trim();
|
|
1167
|
+
const graphChannelId = to.includes("/") ? to.slice(to.indexOf("/") + 1) : "";
|
|
1168
|
+
const isConversationTarget = to.startsWith("conversation:") || to.startsWith("19:") || graphChannelId.startsWith("19:") || graphChannelId.includes("@thread");
|
|
1169
|
+
if (!normalizedThreadId || /(?:^|;)messageid=/iu.test(to) || !isConversationTarget) return to;
|
|
1170
|
+
return `${to};messageid=${normalizedThreadId}`;
|
|
1171
|
+
}
|
|
1130
1172
|
function resolveMSTeamsTextSend(params) {
|
|
1131
1173
|
return (0, openclaw_plugin_sdk_channel_outbound.resolveOutboundSendDep)(params.deps, "msteams") ?? ((to, text) => sendMessageMSTeams({
|
|
1132
1174
|
cfg: params.cfg,
|
|
@@ -1139,9 +1181,7 @@ function resolveMSTeamsMediaSend(params) {
|
|
|
1139
1181
|
cfg: params.cfg,
|
|
1140
1182
|
to,
|
|
1141
1183
|
text,
|
|
1142
|
-
|
|
1143
|
-
mediaLocalRoots: opts?.mediaLocalRoots,
|
|
1144
|
-
mediaReadFile: opts?.mediaReadFile
|
|
1184
|
+
...opts
|
|
1145
1185
|
}));
|
|
1146
1186
|
}
|
|
1147
1187
|
const msteamsOutbound = {
|
|
@@ -1176,13 +1216,14 @@ const msteamsOutbound = {
|
|
|
1176
1216
|
}
|
|
1177
1217
|
};
|
|
1178
1218
|
},
|
|
1179
|
-
sendPayload: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult }) => {
|
|
1219
|
+
sendPayload: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult, threadId }) => {
|
|
1220
|
+
const deliveryTarget = resolveMSTeamsThreadTarget(to, threadId);
|
|
1180
1221
|
const presentationCard = (0, openclaw_plugin_sdk_string_coerce_runtime.asOptionalRecord)(payload.channelData?.msteams)?.presentationCard;
|
|
1181
|
-
if (presentationCard && typeof presentationCard === "object" && !Array.isArray(presentationCard)) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", await sendAdaptiveCardMSTeams({
|
|
1222
|
+
if (presentationCard && typeof presentationCard === "object" && !Array.isArray(presentationCard)) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(await sendAdaptiveCardMSTeams({
|
|
1182
1223
|
cfg,
|
|
1183
|
-
to,
|
|
1224
|
+
to: deliveryTarget,
|
|
1184
1225
|
card: presentationCard
|
|
1185
|
-
}));
|
|
1226
|
+
})));
|
|
1186
1227
|
const mediaUrls = (0, openclaw_plugin_sdk_string_normalization_runtime.normalizeStringEntries)((0, openclaw_plugin_sdk_reply_payload.resolvePayloadMediaUrls)({
|
|
1187
1228
|
...payload,
|
|
1188
1229
|
mediaUrl: payload.mediaUrl ?? mediaUrl
|
|
@@ -1196,15 +1237,16 @@ const msteamsOutbound = {
|
|
|
1196
1237
|
text,
|
|
1197
1238
|
mediaUrls,
|
|
1198
1239
|
onResult: async (deliveryResult) => {
|
|
1199
|
-
await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", deliveryResult));
|
|
1240
|
+
await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(deliveryResult)));
|
|
1200
1241
|
},
|
|
1201
|
-
send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(
|
|
1242
|
+
send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(deliveryTarget, textLocal, {
|
|
1202
1243
|
mediaUrl: mediaUrlLocal,
|
|
1244
|
+
mediaAccess,
|
|
1203
1245
|
mediaLocalRoots,
|
|
1204
1246
|
mediaReadFile
|
|
1205
1247
|
})
|
|
1206
1248
|
});
|
|
1207
|
-
if (result) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result);
|
|
1249
|
+
if (result) return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(result));
|
|
1208
1250
|
}
|
|
1209
1251
|
if (text.trim()) {
|
|
1210
1252
|
const send = resolveMSTeamsTextSend({
|
|
@@ -1214,36 +1256,37 @@ const msteamsOutbound = {
|
|
|
1214
1256
|
const chunks = (0, openclaw_plugin_sdk_reply_payload.resolveTextChunksWithFallback)(text, (0, openclaw_plugin_sdk_text_chunking.chunkTextForOutbound)(text, resolveMSTeamsEffectiveTextChunkLimit(cfg.channels?.msteams?.textChunkLimit)));
|
|
1215
1257
|
let result;
|
|
1216
1258
|
for (const chunk of chunks) {
|
|
1217
|
-
result = await send(
|
|
1218
|
-
await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result));
|
|
1259
|
+
result = await send(deliveryTarget, chunk);
|
|
1260
|
+
await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(result)));
|
|
1219
1261
|
}
|
|
1220
|
-
return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result);
|
|
1262
|
+
return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(result));
|
|
1221
1263
|
}
|
|
1222
1264
|
throw new Error("MS Teams payload send requires text, media, or a presentation card.");
|
|
1223
1265
|
},
|
|
1224
1266
|
...(0, openclaw_plugin_sdk_channel_send_result.createAttachedChannelResultAdapter)({
|
|
1225
1267
|
channel: "msteams",
|
|
1226
|
-
sendText: async ({ cfg, to, text, deps }) => {
|
|
1227
|
-
return await resolveMSTeamsTextSend({
|
|
1268
|
+
sendText: async ({ cfg, to, text, deps, threadId }) => {
|
|
1269
|
+
return toMSTeamsOutboundResult(await resolveMSTeamsTextSend({
|
|
1228
1270
|
cfg,
|
|
1229
1271
|
deps
|
|
1230
|
-
})(to, text);
|
|
1272
|
+
})(resolveMSTeamsThreadTarget(to, threadId), text));
|
|
1231
1273
|
},
|
|
1232
|
-
sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, deps }) => {
|
|
1233
|
-
return await resolveMSTeamsMediaSend({
|
|
1274
|
+
sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, deps, threadId }) => {
|
|
1275
|
+
return toMSTeamsOutboundResult(await resolveMSTeamsMediaSend({
|
|
1234
1276
|
cfg,
|
|
1235
1277
|
deps
|
|
1236
|
-
})(to, text, {
|
|
1278
|
+
})(resolveMSTeamsThreadTarget(to, threadId), text, {
|
|
1237
1279
|
mediaUrl,
|
|
1280
|
+
mediaAccess,
|
|
1238
1281
|
mediaLocalRoots,
|
|
1239
1282
|
mediaReadFile
|
|
1240
|
-
});
|
|
1283
|
+
}));
|
|
1241
1284
|
},
|
|
1242
|
-
sendPoll: async ({ cfg, to, poll }) => {
|
|
1285
|
+
sendPoll: async ({ cfg, to, poll, threadId }) => {
|
|
1243
1286
|
const maxSelections = poll.maxSelections ?? 1;
|
|
1244
1287
|
const result = await sendPollMSTeams({
|
|
1245
1288
|
cfg,
|
|
1246
|
-
to,
|
|
1289
|
+
to: resolveMSTeamsThreadTarget(to, threadId),
|
|
1247
1290
|
question: poll.question,
|
|
1248
1291
|
options: poll.options,
|
|
1249
1292
|
maxSelections
|
|
@@ -1315,7 +1358,7 @@ async function probeMSTeams(cfg) {
|
|
|
1315
1358
|
} catch (err) {
|
|
1316
1359
|
graph = {
|
|
1317
1360
|
ok: false,
|
|
1318
|
-
error:
|
|
1361
|
+
error: require_channel_setup.formatUnknownError(err)
|
|
1319
1362
|
};
|
|
1320
1363
|
}
|
|
1321
1364
|
let delegatedAuth;
|
|
@@ -1349,7 +1392,7 @@ async function probeMSTeams(cfg) {
|
|
|
1349
1392
|
return {
|
|
1350
1393
|
ok: false,
|
|
1351
1394
|
appId: creds.appId,
|
|
1352
|
-
error:
|
|
1395
|
+
error: require_channel_setup.formatUnknownError(err)
|
|
1353
1396
|
};
|
|
1354
1397
|
}
|
|
1355
1398
|
}
|