@openclaw/msteams 2026.9.5 → 2026.9.7

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.
Files changed (33) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{adapter.runtime-ChuVK6k_.cjs → adapter.runtime-BiWeMKXE.cjs} +24 -30
  3. package/dist/.setup/{approval-card-CPNH_q3P.cjs → approval-card-DWPDItvq.cjs} +6 -3
  4. package/dist/.setup/{approval-handler.runtime-DDxGPJDz.cjs → approval-handler.runtime-D1s7UR3U.cjs} +4 -4
  5. package/dist/.setup/bot-framework-service-url-BUhTe8F3.cjs +55 -0
  6. package/dist/.setup/{channel-Dzpbbht8.cjs → channel-ByzS7QJ0.cjs} +338 -220
  7. package/dist/.setup/{channel.runtime-TE49QvFv.cjs → channel.runtime-Baz8XDFs.cjs} +47 -144
  8. package/dist/.setup/{channel.setup-BVDfgdCc.cjs → channel.setup-DL8lcWT_.cjs} +6 -6
  9. package/dist/.setup/{config-schema-D22Lr1Qk.cjs → config-schema-0KoBzb0t.cjs} +24 -38
  10. package/dist/.setup/{messenger-BR1l4zw-.cjs → conversation-store-state-B7JuyZTm.cjs} +697 -297
  11. package/dist/.setup/{src-CpKfpP1m.cjs → monitor-BJ7IyH4y.cjs} +440 -663
  12. package/dist/.setup/{oauth-C6m7dvHj.cjs → oauth-DQjOnJ4l.cjs} +1 -1
  13. package/dist/.setup/{reaction-types-C7RA7Wxt.cjs → reaction-types-CQ4oSUe7.cjs} +2 -6
  14. package/dist/.setup/{resolve-allowlist-CHzaaWiC.cjs → resolve-allowlist-Pl_NQFYH.cjs} +55 -312
  15. package/dist/.setup/{rolldown-runtime-VH7oDXx4.cjs → rolldown-runtime-BloeesfJ.cjs} +22 -0
  16. package/dist/.setup/{send-D8ATH4QI.cjs → send-VUM7Sryb.cjs} +47 -97
  17. package/dist/.setup/{setup-plugin-api-DpiaA8z1.cjs → setup-plugin-api-Dyf8kF-l.cjs} +1 -1
  18. package/dist/.setup/{thread-session-CXgHK-yi.cjs → thread-session--rw3BTal.cjs} +2 -5
  19. package/dist/api.cjs +2 -2
  20. package/dist/channel-config-api.cjs +1 -1
  21. package/dist/channel-plugin-api.cjs +1 -1
  22. package/dist/configured-state.cjs +0 -1
  23. package/dist/directory-contract-api.cjs +1 -1
  24. package/dist/doctor-contract-api.cjs +201 -371
  25. package/dist/qa-runner-api.cjs +1 -1
  26. package/dist/runtime-api.cjs +0 -6
  27. package/dist/setup-entry.cjs +1 -1
  28. package/dist/setup-plugin-api.cjs +1 -1
  29. package/openclaw.plugin.json +46 -5
  30. package/package.json +10 -10
  31. package/dist/.setup/polls-BJ4-4uZm.cjs +0 -668
  32. package/dist/.setup/secret-input-C65t6kjM.cjs +0 -1
  33. package/dist/.setup/sso-token-store-YYLHXgFH.cjs +0 -111
@@ -1,8 +1,9 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-BloeesfJ.cjs");
1
2
  require("../runtime-api.cjs");
2
- const require_resolve_allowlist = require("./resolve-allowlist-CHzaaWiC.cjs");
3
+ const require_resolve_allowlist = require("./resolve-allowlist-Pl_NQFYH.cjs");
3
4
  const require_directory_contract_api = require("../directory-contract-api.cjs");
4
- const require_thread_session = require("./thread-session-CXgHK-yi.cjs");
5
- const require_channel_setup = require("./channel.setup-BVDfgdCc.cjs");
5
+ const require_thread_session = require("./thread-session--rw3BTal.cjs");
6
+ const require_channel_setup = require("./channel.setup-DL8lcWT_.cjs");
6
7
  let openclaw_plugin_sdk_approval_handler_adapter_runtime = require("openclaw/plugin-sdk/approval-handler-adapter-runtime");
7
8
  let openclaw_plugin_sdk_channel_actions = require("openclaw/plugin-sdk/channel-actions");
8
9
  let openclaw_plugin_sdk_channel_core = require("openclaw/plugin-sdk/channel-core");
@@ -21,7 +22,6 @@ let openclaw_plugin_sdk_reply_reference = require("openclaw/plugin-sdk/reply-ref
21
22
  let openclaw_plugin_sdk_approval_delivery_runtime = require("openclaw/plugin-sdk/approval-delivery-runtime");
22
23
  let openclaw_plugin_sdk_approval_native_runtime = require("openclaw/plugin-sdk/approval-native-runtime");
23
24
  let openclaw_plugin_sdk_channel_targets = require("openclaw/plugin-sdk/channel-targets");
24
- let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
25
25
  let openclaw_plugin_sdk_dangerous_name_runtime = require("openclaw/plugin-sdk/dangerous-name-runtime");
26
26
  let openclaw_plugin_sdk_runtime_group_policy = require("openclaw/plugin-sdk/runtime-group-policy");
27
27
  let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunking");
@@ -42,6 +42,52 @@ function resolveActionUploadFilePath(params) {
42
42
  }
43
43
  }
44
44
  //#endregion
45
+ //#region extensions/msteams/src/action-results.ts
46
+ function jsonActionResult(data, details = data) {
47
+ return {
48
+ content: [{
49
+ type: "text",
50
+ text: JSON.stringify(data)
51
+ }],
52
+ details
53
+ };
54
+ }
55
+ function jsonMSTeamsActionResult(action, data = {}) {
56
+ return jsonActionResult({
57
+ channel: "msteams",
58
+ action,
59
+ ...data
60
+ });
61
+ }
62
+ function jsonMSTeamsOkActionResult(action, data = {}) {
63
+ return jsonActionResult({
64
+ ok: true,
65
+ channel: "msteams",
66
+ action,
67
+ ...data
68
+ });
69
+ }
70
+ function jsonMSTeamsConversationResult(conversationId) {
71
+ return jsonActionResult({
72
+ ok: true,
73
+ channel: "msteams",
74
+ conversationId
75
+ }, {
76
+ ok: true,
77
+ channel: "msteams"
78
+ });
79
+ }
80
+ function actionError(message) {
81
+ return {
82
+ isError: true,
83
+ content: [{
84
+ type: "text",
85
+ text: message
86
+ }],
87
+ details: { error: message }
88
+ };
89
+ }
90
+ //#endregion
45
91
  //#region extensions/msteams/src/policy.ts
46
92
  const teamScopeKey = (teamKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey]);
47
93
  const channelScopeKey = (teamKey, channelKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey], ["channel", channelKey]);
@@ -185,18 +231,18 @@ function resolveMSTeamsGroupToolPolicy(params) {
185
231
  ...senderScope
186
232
  });
187
233
  }
188
- function resolveMSTeamsAllowlistMatch(params) {
189
- return (0, openclaw_plugin_sdk_allow_from.resolveAllowlistMatchSimple)(params);
190
- }
191
234
  function resolveMSTeamsReplyPolicy(params) {
192
235
  if (params.isDirectMessage) return {
193
236
  requireMention: false,
194
237
  replyStyle: "thread"
195
238
  };
196
239
  const requireMention = params.channelConfig?.requireMention ?? params.teamConfig?.requireMention ?? params.globalConfig?.requireMention ?? true;
240
+ const explicitReplyStyle = params.channelConfig?.replyStyle ?? params.teamConfig?.replyStyle ?? params.globalConfig?.replyStyle;
241
+ const requireMentionInBotThreads = params.channelConfig?.requireMentionInBotThreads ?? params.teamConfig?.requireMentionInBotThreads ?? params.globalConfig?.requireMentionInBotThreads;
197
242
  return {
198
243
  requireMention,
199
- replyStyle: params.channelConfig?.replyStyle ?? params.teamConfig?.replyStyle ?? params.globalConfig?.replyStyle ?? (requireMention ? "thread" : "top-level")
244
+ replyStyle: explicitReplyStyle ?? (requireMention ? "thread" : "top-level"),
245
+ ...requireMentionInBotThreads === void 0 ? {} : { requireMentionInBotThreads }
200
246
  };
201
247
  }
202
248
  //#endregion
@@ -347,7 +393,7 @@ const msTeamsLazyApprovalNativeRuntime = (0, openclaw_plugin_sdk_approval_handle
347
393
  request
348
394
  }),
349
395
  load: async () => {
350
- const { msTeamsApprovalNativeRuntime } = await Promise.resolve().then(() => require("./approval-handler.runtime-DDxGPJDz.cjs"));
396
+ const { msTeamsApprovalNativeRuntime } = await Promise.resolve().then(() => require("./approval-handler.runtime-D1s7UR3U.cjs"));
351
397
  return msTeamsApprovalNativeRuntime;
352
398
  }
353
399
  });
@@ -363,7 +409,7 @@ const msTeamsApprovalCapability = {
363
409
  ...(0, openclaw_plugin_sdk_approval_delivery_runtime.createApproverRestrictedNativeApprovalCapability)({
364
410
  channel: "msteams",
365
411
  channelLabel: "Microsoft Teams",
366
- describeExecApprovalSetup: () => "Approve it from the Web UI or terminal UI for now. Microsoft Teams supports native approvals when the bot is configured. Configure `channels.msteams.allowFrom` or `channels.msteams.defaultTo` with Microsoft Entra object ID approvers.",
412
+ describeExecApprovalSetup: () => "Approve it from the Web UI for now. Microsoft Teams supports native approvals when the bot is configured. Configure `channels.msteams.allowFrom` or `channels.msteams.defaultTo` with Microsoft Entra object ID approvers.",
367
413
  listAccountIds: require_channel_setup.msteamsConfigAdapter.listAccountIds,
368
414
  hasApprovers: ({ cfg, accountId }) => require_thread_session.getMSTeamsApprovalApprovers({
369
415
  cfg,
@@ -394,6 +440,160 @@ const msTeamsApprovalCapability = {
394
440
  authorizeActorAction: (params) => require_thread_session.msTeamsApprovalAuth.authorizeActorAction?.(params)
395
441
  };
396
442
  //#endregion
443
+ //#region src/gateway/gateway-http-route-contracts.ts
444
+ const GATEWAY_PROBE_ROUTES = /* @__PURE__ */ new Map([
445
+ ["/health", "live"],
446
+ ["/healthz", "live"],
447
+ ["/ready", "ready"],
448
+ ["/readyz", "ready"],
449
+ ["/startup", "startup"],
450
+ ["/startupz", "startup"]
451
+ ]);
452
+ function classifyGatewayProbePath(pathname) {
453
+ for (const [root, status] of GATEWAY_PROBE_ROUTES) {
454
+ if (pathname === root) return status;
455
+ if (pathname.startsWith(`${root}/`)) return "namespace";
456
+ }
457
+ return "outside";
458
+ }
459
+ //#endregion
460
+ //#region packages/normalization-core/src/string-coerce.ts
461
+ /** Trims string input and returns null for non-strings or empty strings. */
462
+ function normalizeNullableString(value) {
463
+ if (typeof value !== "string") return null;
464
+ const trimmed = value.trim();
465
+ return trimmed ? trimmed : null;
466
+ }
467
+ /** Trims string input and returns undefined for non-strings or empty strings. */
468
+ function normalizeOptionalString$3(value) {
469
+ return normalizeNullableString(value) ?? void 0;
470
+ }
471
+ /** Lowercases a normalized optional string. */
472
+ function normalizeOptionalLowercaseString(value) {
473
+ return normalizeOptionalString$3(value)?.toLowerCase();
474
+ }
475
+ /** Lowercases a normalized string or returns an empty string when absent. */
476
+ function normalizeLowercaseStringOrEmpty$1(value) {
477
+ return normalizeOptionalLowercaseString(value) ?? "";
478
+ }
479
+ //#endregion
480
+ //#region src/plugins/http-path-prefix.ts
481
+ function prefixMatchPath(pathname, prefix) {
482
+ return pathname === prefix || pathname.startsWith(`${prefix}/`) || pathname.startsWith(`${prefix}%`);
483
+ }
484
+ //#endregion
485
+ //#region src/gateway/security-path.ts
486
+ const MAX_PATH_DECODE_PASSES = 32;
487
+ function normalizePathSeparators(pathname) {
488
+ const collapsed = pathname.replace(/\/{2,}/g, "/");
489
+ if (collapsed.length <= 1) return collapsed;
490
+ return collapsed.replace(/\/+$/, "");
491
+ }
492
+ function resolveDotSegments(pathname) {
493
+ try {
494
+ return new URL(pathname, "http://localhost").pathname;
495
+ } catch {
496
+ return pathname;
497
+ }
498
+ }
499
+ function normalizePathForSecurity(pathname) {
500
+ return normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(resolveDotSegments(pathname))) || "/";
501
+ }
502
+ function buildCanonicalPathCandidates(pathname, maxDecodePasses = MAX_PATH_DECODE_PASSES) {
503
+ const candidates = /* @__PURE__ */ new Set([normalizePathForSecurity(pathname)]);
504
+ let decoded = pathname;
505
+ let malformedEncoding = false;
506
+ let decodePasses = 0;
507
+ for (let pass = 0; pass < maxDecodePasses; pass++) {
508
+ let nextDecoded;
509
+ try {
510
+ nextDecoded = decodeURIComponent(decoded);
511
+ } catch {
512
+ malformedEncoding = true;
513
+ break;
514
+ }
515
+ if (nextDecoded === decoded) break;
516
+ decodePasses += 1;
517
+ decoded = nextDecoded;
518
+ candidates.add(normalizePathForSecurity(decoded));
519
+ }
520
+ let decodePassLimitReached = false;
521
+ if (!malformedEncoding) try {
522
+ decodePassLimitReached = decodeURIComponent(decoded) !== decoded;
523
+ } catch {
524
+ malformedEncoding = true;
525
+ }
526
+ return {
527
+ candidates: [...candidates],
528
+ decodePasses,
529
+ decodePassLimitReached,
530
+ malformedEncoding
531
+ };
532
+ }
533
+ function canonicalizePathForSecurity(pathname) {
534
+ const { candidates, decodePasses, decodePassLimitReached, malformedEncoding } = buildCanonicalPathCandidates(pathname);
535
+ return {
536
+ canonicalPath: candidates[candidates.length - 1] ?? "/",
537
+ candidates,
538
+ decodePasses,
539
+ decodePassLimitReached,
540
+ malformedEncoding,
541
+ rawNormalizedPath: normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(pathname)) || "/"
542
+ };
543
+ }
544
+ const PROTECTED_PLUGIN_ROUTE_PREFIXES = ["/api/channels"];
545
+ //#endregion
546
+ //#region src/gateway/server/plugins-http/path-context.ts
547
+ function normalizeProtectedPrefix(prefix) {
548
+ const collapsed = normalizeLowercaseStringOrEmpty$1(prefix).replace(/\/{2,}/g, "/");
549
+ if (collapsed.length <= 1) return collapsed || "/";
550
+ return collapsed.replace(/\/+$/, "");
551
+ }
552
+ const NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES = PROTECTED_PLUGIN_ROUTE_PREFIXES.map(normalizeProtectedPrefix);
553
+ /** Returns true when any decoded path candidate targets a protected route. */
554
+ function isProtectedPluginRoutePathFromContext(context) {
555
+ if (context.candidates.some((candidate) => NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES.some((prefix) => prefixMatchPath(candidate, prefix)))) return true;
556
+ if (context.decodePassLimitReached) return true;
557
+ if (!context.malformedEncoding) return false;
558
+ return NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES.some((prefix) => prefixMatchPath(context.rawNormalizedPath, prefix));
559
+ }
560
+ /** Builds all security-relevant decoded path candidates for a request path. */
561
+ function resolvePluginRoutePathContext(pathname) {
562
+ const canonical = canonicalizePathForSecurity(pathname);
563
+ return {
564
+ pathname,
565
+ canonicalPath: canonical.canonicalPath,
566
+ candidates: canonical.candidates,
567
+ malformedEncoding: canonical.malformedEncoding,
568
+ decodePassLimitReached: canonical.decodePassLimitReached,
569
+ rawNormalizedPath: canonical.rawNormalizedPath
570
+ };
571
+ }
572
+ //#endregion
573
+ //#region \0openclaw:bundled-sdk:openclaw/plugin-sdk/gateway-config-runtime
574
+ var gateway_config_runtime_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
575
+ classifyGatewayProbePath: () => classifyGatewayProbePath,
576
+ isProtectedPluginRoutePathFromContext: () => isProtectedPluginRoutePathFromContext,
577
+ resolvePluginRoutePathContext: () => resolvePluginRoutePathContext
578
+ });
579
+ require_rolldown_runtime.__reExport(gateway_config_runtime_exports, require("openclaw/plugin-sdk/gateway-config-runtime"));
580
+ //#endregion
581
+ //#region extensions/msteams/src/webhook-route.ts
582
+ function resolveMSTeamsLegacyWebhook(config) {
583
+ const listener = config?.legacyWebhook;
584
+ return listener === false ? void 0 : listener ?? { port: 3978 };
585
+ }
586
+ function resolveMSTeamsWebhookPathIssue({ cfg, env }) {
587
+ const channel = cfg.channels?.msteams;
588
+ const path = channel?.webhook?.path || "/api/messages";
589
+ const legacy = resolveMSTeamsLegacyWebhook(channel);
590
+ const pathname = URL.parse(path, "http://localhost")?.pathname ?? path;
591
+ const probe = classifyGatewayProbePath(pathname);
592
+ const reason = isProtectedPluginRoutePathFromContext(resolvePluginRoutePathContext(pathname)) ? "requires Gateway authentication on the main HTTP listener" : probe !== "namespace" && probe !== "outside" ? "is reserved for Gateway probes" : /[:*{}\\]/.test(path) ? "uses Express pattern syntax that requires the compatibility listener" : void 0;
593
+ if (!reason) return;
594
+ return `Microsoft Teams webhook path ${path} ${reason}. Set channels.msteams.webhook.path to /api/messages and update the Azure Bot messaging endpoint or reverse-proxy upstream to Gateway port ${(0, gateway_config_runtime_exports.resolveGatewayPort)(cfg, env)}/api/messages; verify delivery before setting channels.msteams.legacyWebhook=false.` + (legacy ? ` Compatibility port ${legacy.port} continues serving the current path.` : " The compatibility listener is disabled, so this path cannot receive Teams callbacks.");
595
+ }
596
+ //#endregion
397
597
  //#region extensions/msteams/src/doctor.ts
398
598
  const isMSTeamsMutableAllowEntry = (0, openclaw_plugin_sdk_channel_policy.buildMutableAllowEntryDetector)({
399
599
  prefixes: ["msteams:", "user:"],
@@ -404,6 +604,39 @@ const collectMSTeamsMutableAllowlistWarnings = (0, openclaw_plugin_sdk_channel_p
404
604
  detector: isMSTeamsMutableAllowEntry,
405
605
  collectLists: (scope) => (0, openclaw_plugin_sdk_channel_policy.collectStandardAllowlistLists)(scope)
406
606
  });
607
+ function runMSTeamsWebhookDoctorSequence({ cfg, env }) {
608
+ const channel = cfg.channels?.msteams;
609
+ if (!channel || channel.enabled === false) return {
610
+ changeNotes: [],
611
+ warningNotes: [],
612
+ infoNotes: []
613
+ };
614
+ const pathIssue = resolveMSTeamsWebhookPathIssue({
615
+ cfg,
616
+ env
617
+ });
618
+ if (pathIssue) return {
619
+ changeNotes: [],
620
+ warningNotes: [pathIssue],
621
+ infoNotes: []
622
+ };
623
+ const path = channel.webhook?.path || "/api/messages";
624
+ const port = (0, gateway_config_runtime_exports.resolveGatewayPort)(cfg, env);
625
+ const legacy = resolveMSTeamsLegacyWebhook(channel);
626
+ return {
627
+ changeNotes: [],
628
+ warningNotes: [],
629
+ infoNotes: [legacy ? `Microsoft Teams: compatibility port ${legacy.port} continues forwarding to Gateway route ${path}. To use only the Gateway listener, update the Azure Bot messaging endpoint or reverse-proxy upstream to Gateway port ${port}${path}, verify delivery, then set channels.msteams.legacyWebhook=false to close the old port.` : `Microsoft Teams webhooks use Gateway port ${port}${path}; the compatibility listener is disabled by channels.msteams.legacyWebhook=false. Point the Azure Bot messaging endpoint or reverse-proxy upstream to this route.`]
630
+ };
631
+ }
632
+ const msteamsDoctor = {
633
+ dmAllowFromMode: "topOnly",
634
+ groupModel: "hybrid",
635
+ groupAllowFromFallbackToAllowFrom: true,
636
+ warnOnEmptyGroupSenderAllowlist: true,
637
+ collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings,
638
+ runConfigSequence: runMSTeamsWebhookDoctorSequence
639
+ };
407
640
  //#endregion
408
641
  //#region extensions/msteams/src/graph-action-context.ts
409
642
  const MSTEAMS_GROUP_MANAGEMENT_ACTIONS = /* @__PURE__ */ new Set([
@@ -806,50 +1039,7 @@ const collectMSTeamsSecurityFindings = openclaw_plugin_sdk_channel_policy.create
806
1039
  severity: "warn",
807
1040
  title: "MS Teams security warning"
808
1041
  });
809
- const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-TE49QvFv.cjs")), "msTeamsChannelRuntime");
810
- function jsonActionResult(data) {
811
- return {
812
- content: [{
813
- type: "text",
814
- text: JSON.stringify(data)
815
- }],
816
- details: data
817
- };
818
- }
819
- function jsonMSTeamsActionResult(action, data = {}) {
820
- return jsonActionResult({
821
- channel: "msteams",
822
- action,
823
- ...data
824
- });
825
- }
826
- function jsonMSTeamsOkActionResult(action, data = {}) {
827
- return jsonActionResult({
828
- ok: true,
829
- channel: "msteams",
830
- action,
831
- ...data
832
- });
833
- }
834
- function jsonMSTeamsConversationResult(conversationId) {
835
- return jsonActionResultWithDetails({
836
- ok: true,
837
- channel: "msteams",
838
- conversationId
839
- }, {
840
- ok: true,
841
- channel: "msteams"
842
- });
843
- }
844
- function jsonActionResultWithDetails(contentData, details) {
845
- return {
846
- content: [{
847
- type: "text",
848
- text: JSON.stringify(contentData)
849
- }],
850
- details
851
- };
852
- }
1042
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-Baz8XDFs.cjs")), "msTeamsChannelRuntime");
853
1043
  const MSTEAMS_REACTION_TYPES = [
854
1044
  "like",
855
1045
  "heart",
@@ -858,16 +1048,6 @@ const MSTEAMS_REACTION_TYPES = [
858
1048
  "sad",
859
1049
  "angry"
860
1050
  ];
861
- function actionError(message) {
862
- return {
863
- isError: true,
864
- content: [{
865
- type: "text",
866
- text: message
867
- }],
868
- details: { error: message }
869
- };
870
- }
871
1051
  function requireMSTeamsGroupManagementAuthorization(ctx) {
872
1052
  if (ctx.senderIsOwner === true || ctx.gatewayClientScopes?.includes("operator.admin")) return null;
873
1053
  return actionError("Microsoft Teams group management requires an owner or operator.admin requester.");
@@ -889,18 +1069,6 @@ function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelI
889
1069
  function resolveCurrentGraphActionTarget(toolContext) {
890
1070
  return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentGraphChannelId) ?? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentMessagingTarget);
891
1071
  }
892
- function resolveActionMessageId(params) {
893
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.messageId) ?? "";
894
- }
895
- function resolveActionPinnedMessageId(params) {
896
- return typeof params.pinnedMessageId === "string" ? params.pinnedMessageId.trim() : typeof params.messageId === "string" ? params.messageId.trim() : "";
897
- }
898
- function resolveActionQuery(params) {
899
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.query) ?? "";
900
- }
901
- function readOptionalTrimmedString(params, key) {
902
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params[key]);
903
- }
904
1072
  function resolveMSTeamsActionTarget(params) {
905
1073
  return params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
906
1074
  }
@@ -911,7 +1079,14 @@ async function runWithRequiredActionTarget(params) {
911
1079
  }
912
1080
  async function runWithRequiredActionMessageTarget(params) {
913
1081
  const to = resolveMSTeamsActionTarget(params);
914
- const messageId = resolveActionMessageId(params.toolParams);
1082
+ const messageIdRaw = params.allowCurrentMessageIdFallback === true && msteamsContextTargetsMatch(to, {
1083
+ currentChannelId: params.currentChannelId ?? void 0,
1084
+ currentMessagingTarget: params.currentGraphChannelId ?? void 0
1085
+ }) ? (0, openclaw_plugin_sdk_channel_actions.resolveReactionMessageId)({
1086
+ args: params.toolParams,
1087
+ toolContext: { currentMessageId: params.currentMessageId ?? void 0 }
1088
+ }) : (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.toolParams.messageId) ?? "";
1089
+ const messageId = messageIdRaw == null ? "" : String(messageIdRaw).trim();
915
1090
  if (!to || !messageId) return actionError(`${params.actionLabel} requires a target (to) and messageId.`);
916
1091
  return await params.run({
917
1092
  to,
@@ -920,7 +1095,7 @@ async function runWithRequiredActionMessageTarget(params) {
920
1095
  }
921
1096
  async function runWithRequiredActionPinnedMessageTarget(params) {
922
1097
  const to = resolveMSTeamsActionTarget(params);
923
- const pinnedMessageId = resolveActionPinnedMessageId(params.toolParams);
1098
+ const pinnedMessageId = typeof params.toolParams.pinnedMessageId === "string" ? params.toolParams.pinnedMessageId.trim() : (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.toolParams.messageId) ?? "";
924
1099
  if (!to || !pinnedMessageId) return actionError(`${params.actionLabel} requires a target (to) and pinnedMessageId.`);
925
1100
  return await params.run({
926
1101
  to,
@@ -1013,21 +1188,15 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1013
1188
  agentPrompt: { messageToolHints: () => ["- Adaptive Cards supported. Use `action=send` with `card={type,version,body}` to send rich cards.", "- MSTeams targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:ID` or `user:Display Name` (requires Graph API) for DMs, `conversation:19:...@thread.tacv2` for groups/channels. Prefer IDs over display names for speed."] },
1014
1189
  groups: { resolveToolPolicy: resolveMSTeamsGroupToolPolicy },
1015
1190
  approvalCapability: msTeamsApprovalCapability,
1016
- doctor: {
1017
- dmAllowFromMode: "topOnly",
1018
- groupModel: "hybrid",
1019
- groupAllowFromFallbackToAllowFrom: true,
1020
- warnOnEmptyGroupSenderAllowlist: true,
1021
- collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings
1022
- },
1191
+ doctor: msteamsDoctor,
1023
1192
  messaging: {
1024
1193
  targetPrefixes: ["msteams", "teams"],
1025
1194
  directTargetStyle: "user-prefixed",
1026
1195
  normalizeTarget: require_resolve_allowlist.normalizeMSTeamsMessagingTarget,
1027
1196
  inferTargetChatType: ({ to }) => inferMSTeamsTargetChatType(to),
1028
- resolveOutboundSessionRoute: (params) => resolveMSTeamsOutboundSessionRoute(params),
1197
+ resolveOutboundSessionRoute: resolveMSTeamsOutboundSessionRoute,
1029
1198
  targetResolver: {
1030
- looksLikeId: (raw) => require_resolve_allowlist.looksLikeMSTeamsTargetId(raw),
1199
+ looksLikeId: require_resolve_allowlist.looksLikeMSTeamsTargetId,
1031
1200
  hint: "<conversationId|user:ID|conversation:ID>"
1032
1201
  }
1033
1202
  },
@@ -1048,7 +1217,6 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1048
1217
  name: void 0,
1049
1218
  note: void 0
1050
1219
  }));
1051
- const stripPrefix = (value) => require_resolve_allowlist.normalizeMSTeamsUserInput(value);
1052
1220
  const markPendingLookupFailed = (pending) => {
1053
1221
  pending.forEach(({ index }) => {
1054
1222
  const entry = results[index];
@@ -1076,7 +1244,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1076
1244
  entry.note = "empty input";
1077
1245
  return;
1078
1246
  }
1079
- const cleaned = stripPrefix(trimmed);
1247
+ const cleaned = require_resolve_allowlist.normalizeMSTeamsUserInput(trimmed);
1080
1248
  if (/^[0-9a-fA-F-]{16,}$/.test(cleaned) || cleaned.includes("@")) {
1081
1249
  entry.resolved = true;
1082
1250
  entry.id = cleaned;
@@ -1189,15 +1357,11 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1189
1357
  assertDirectAdapterHandoff: ctx.assertDirectAdapterHandoff,
1190
1358
  onPlatformSendDispatch: ctx.onPlatformSendDispatch
1191
1359
  });
1192
- return jsonActionResultWithDetails({
1360
+ return jsonActionResult({
1193
1361
  ok: true,
1194
1362
  channel: "msteams",
1195
1363
  messageId: result.messageId,
1196
1364
  conversationId: result.conversationId
1197
- }, {
1198
- ok: true,
1199
- channel: "msteams",
1200
- messageId: result.messageId
1201
1365
  });
1202
1366
  }
1203
1367
  });
@@ -1216,62 +1380,47 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1216
1380
  to,
1217
1381
  text: resolveActionContent(ctx.params),
1218
1382
  mediaUrl,
1219
- filename: readOptionalTrimmedString(ctx.params, "filename") ?? readOptionalTrimmedString(ctx.params, "title"),
1383
+ filename: (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.filename) ?? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.title),
1220
1384
  mediaAccess: ctx.mediaAccess,
1221
1385
  mediaLocalRoots: ctx.mediaLocalRoots,
1222
1386
  mediaReadFile: ctx.mediaReadFile,
1223
1387
  assertDirectAdapterHandoff: ctx.assertDirectAdapterHandoff,
1224
1388
  onPlatformSendDispatch: ctx.onPlatformSendDispatch
1225
1389
  });
1226
- return jsonActionResultWithDetails({
1390
+ return jsonActionResult({
1227
1391
  ok: true,
1228
1392
  channel: "msteams",
1229
1393
  action: "upload-file",
1230
1394
  messageId: result.messageId,
1231
1395
  conversationId: result.conversationId,
1232
1396
  ...result.pendingUploadId ? { pendingUploadId: result.pendingUploadId } : {}
1233
- }, {
1234
- ok: true,
1235
- channel: "msteams",
1236
- messageId: result.messageId,
1237
- ...result.pendingUploadId ? { pendingUploadId: result.pendingUploadId } : {}
1238
1397
  });
1239
1398
  }
1240
1399
  });
1241
1400
  }
1242
- if (ctx.action === "edit") {
1243
- const content = resolveActionContent(ctx.params);
1244
- if (!content) return actionError("Edit requires content.");
1401
+ if (ctx.action === "edit" || ctx.action === "delete") {
1402
+ const action = ctx.action;
1403
+ const content = action === "edit" ? resolveActionContent(ctx.params) : "";
1404
+ if (action === "edit" && !content) return actionError("Edit requires content.");
1245
1405
  return await runWithRequiredActionMessageTarget({
1246
- actionLabel: "Edit",
1406
+ actionLabel: action === "edit" ? "Edit" : "Delete",
1247
1407
  toolParams: ctx.params,
1248
1408
  currentChannelId: ctx.toolContext?.currentChannelId,
1249
1409
  run: async (target) => {
1250
1410
  const to = await authorizeActionTarget(target.to);
1251
- const { editMessageMSTeams } = await loadMSTeamsChannelRuntime();
1252
- return jsonMSTeamsConversationResult((await editMessageMSTeams({
1411
+ const runtime = await loadMSTeamsChannelRuntime();
1412
+ const params = {
1253
1413
  cfg: ctx.cfg,
1254
1414
  to,
1255
- activityId: target.messageId,
1415
+ activityId: target.messageId
1416
+ };
1417
+ return jsonMSTeamsConversationResult((action === "edit" ? await runtime.editMessageMSTeams({
1418
+ ...params,
1256
1419
  text: content
1257
- })).conversationId);
1420
+ }) : await runtime.deleteMessageMSTeams(params)).conversationId);
1258
1421
  }
1259
1422
  });
1260
1423
  }
1261
- if (ctx.action === "delete") return await runWithRequiredActionMessageTarget({
1262
- actionLabel: "Delete",
1263
- toolParams: ctx.params,
1264
- currentChannelId: ctx.toolContext?.currentChannelId,
1265
- run: async (target) => {
1266
- const to = await authorizeActionTarget(target.to);
1267
- const { deleteMessageMSTeams } = await loadMSTeamsChannelRuntime();
1268
- return jsonMSTeamsConversationResult((await deleteMessageMSTeams({
1269
- cfg: ctx.cfg,
1270
- to,
1271
- activityId: target.messageId
1272
- })).conversationId);
1273
- }
1274
- });
1275
1424
  const graphActionTarget = {
1276
1425
  toolParams: ctx.action === "search" || ctx.action === "member-info" ? {
1277
1426
  ...ctx.params,
@@ -1280,34 +1429,36 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1280
1429
  currentChannelId: ctx.toolContext?.currentChannelId,
1281
1430
  currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1282
1431
  currentChatType: ctx.toolContext?.currentChatType,
1432
+ currentMessageId: ctx.toolContext?.currentMessageId,
1283
1433
  graphOnly: true
1284
1434
  };
1285
- if (ctx.action === "read") return await runWithRequiredActionMessageTarget({
1286
- actionLabel: "Read",
1287
- ...graphActionTarget,
1288
- run: async (target) => {
1289
- const to = await authorizeActionTarget(target.to);
1290
- const { getMessageMSTeams } = await loadMSTeamsChannelRuntime();
1291
- return jsonMSTeamsOkActionResult("read", { message: await getMessageMSTeams({
1292
- cfg: ctx.cfg,
1293
- to,
1294
- messageId: target.messageId
1295
- }) });
1296
- }
1297
- });
1298
- if (ctx.action === "pin") return await runWithRequiredActionMessageTarget({
1299
- actionLabel: "Pin",
1300
- ...graphActionTarget,
1301
- run: async (target) => {
1302
- const to = await authorizeActionTarget(target.to);
1303
- const { pinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1304
- return jsonMSTeamsActionResult("pin", await pinMessageMSTeams({
1305
- cfg: ctx.cfg,
1306
- to,
1307
- messageId: target.messageId
1308
- }));
1309
- }
1310
- });
1435
+ if (ctx.action === "read" || ctx.action === "pin" || ctx.action === "reactions") {
1436
+ const action = ctx.action;
1437
+ return await runWithRequiredActionMessageTarget({
1438
+ actionLabel: {
1439
+ read: "Read",
1440
+ pin: "Pin",
1441
+ reactions: "Reactions"
1442
+ }[action],
1443
+ ...graphActionTarget,
1444
+ allowCurrentMessageIdFallback: action === "reactions",
1445
+ run: async (target) => {
1446
+ const to = await authorizeActionTarget(target.to);
1447
+ const runtime = await loadMSTeamsChannelRuntime();
1448
+ const params = {
1449
+ cfg: ctx.cfg,
1450
+ to,
1451
+ messageId: target.messageId
1452
+ };
1453
+ if (action === "read") {
1454
+ const message = await runtime.getMessageMSTeams(params);
1455
+ return jsonMSTeamsOkActionResult(action, { message });
1456
+ }
1457
+ if (action === "pin") return jsonMSTeamsActionResult(action, await runtime.pinMessageMSTeams(params));
1458
+ return jsonMSTeamsOkActionResult(action, await runtime.listReactionsMSTeams(params));
1459
+ }
1460
+ });
1461
+ }
1311
1462
  if (ctx.action === "unpin") return await runWithRequiredActionPinnedMessageTarget({
1312
1463
  actionLabel: "Unpin",
1313
1464
  ...graphActionTarget,
@@ -1336,6 +1487,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1336
1487
  if (ctx.action === "react") return await runWithRequiredActionMessageTarget({
1337
1488
  actionLabel: "React",
1338
1489
  ...graphActionTarget,
1490
+ allowCurrentMessageIdFallback: true,
1339
1491
  run: async (target) => {
1340
1492
  const emoji = typeof ctx.params.emoji === "string" ? ctx.params.emoji.trim() : "";
1341
1493
  const remove = typeof ctx.params.remove === "boolean" ? ctx.params.remove : false;
@@ -1351,50 +1503,26 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1351
1503
  }
1352
1504
  };
1353
1505
  const to = await authorizeActionTarget(target.to);
1354
- if (remove) {
1355
- const { unreactMessageMSTeams } = await loadMSTeamsChannelRuntime();
1356
- return jsonMSTeamsActionResult("react", {
1357
- removed: true,
1358
- reactionType: emoji,
1359
- ...await unreactMessageMSTeams({
1360
- cfg: ctx.cfg,
1361
- to,
1362
- messageId: target.messageId,
1363
- reactionType: emoji
1364
- })
1365
- });
1366
- }
1367
- const { reactMessageMSTeams } = await loadMSTeamsChannelRuntime();
1506
+ const runtime = await loadMSTeamsChannelRuntime();
1507
+ const result = await (remove ? runtime.unreactMessageMSTeams : runtime.reactMessageMSTeams)({
1508
+ cfg: ctx.cfg,
1509
+ to,
1510
+ messageId: target.messageId,
1511
+ reactionType: emoji
1512
+ });
1368
1513
  return jsonMSTeamsActionResult("react", {
1514
+ ...remove ? { removed: true } : {},
1369
1515
  reactionType: emoji,
1370
- ...await reactMessageMSTeams({
1371
- cfg: ctx.cfg,
1372
- to,
1373
- messageId: target.messageId,
1374
- reactionType: emoji
1375
- })
1516
+ ...result
1376
1517
  });
1377
1518
  }
1378
1519
  });
1379
- if (ctx.action === "reactions") return await runWithRequiredActionMessageTarget({
1380
- actionLabel: "Reactions",
1381
- ...graphActionTarget,
1382
- run: async (target) => {
1383
- const to = await authorizeActionTarget(target.to);
1384
- const { listReactionsMSTeams } = await loadMSTeamsChannelRuntime();
1385
- return jsonMSTeamsOkActionResult("reactions", await listReactionsMSTeams({
1386
- cfg: ctx.cfg,
1387
- to,
1388
- messageId: target.messageId
1389
- }));
1390
- }
1391
- });
1392
1520
  if (ctx.action === "search") return await runWithRequiredActionTarget({
1393
1521
  actionLabel: "Search",
1394
1522
  ...graphActionTarget,
1395
1523
  run: async (to) => {
1396
1524
  const allowedTarget = await authorizeActionTarget(to);
1397
- const query = resolveActionQuery(ctx.params);
1525
+ const query = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.query);
1398
1526
  if (!query) return actionError("Search requires a target (to) and query.");
1399
1527
  const limit = (0, openclaw_plugin_sdk_channel_actions.readPositiveIntegerParam)(ctx.params, "limit");
1400
1528
  const from = typeof ctx.params.from === "string" ? ctx.params.from.trim() : void 0;
@@ -1457,39 +1585,27 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1457
1585
  channelId: graphChannelId
1458
1586
  })).channel });
1459
1587
  }
1460
- if (ctx.action === "addParticipant") {
1461
- const userId = typeof ctx.params.userId === "string" ? ctx.params.userId.trim() : "";
1462
- if (!userId) return actionError("addParticipant requires a userId.");
1588
+ if (ctx.action === "addParticipant" || ctx.action === "removeParticipant") {
1589
+ const action = ctx.action;
1590
+ const userId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.userId);
1591
+ if (!userId) return actionError(`${action} requires a userId.`);
1463
1592
  return await runWithRequiredActionTarget({
1464
- actionLabel: "addParticipant",
1593
+ actionLabel: action,
1465
1594
  toolParams: ctx.params,
1466
1595
  currentChannelId: ctx.toolContext?.currentChannelId,
1467
1596
  run: async (to) => {
1468
- const role = readOptionalTrimmedString(ctx.params, "role");
1469
- const { addParticipantMSTeams } = await loadMSTeamsChannelRuntime();
1470
- return jsonMSTeamsOkActionResult("addParticipant", await addParticipantMSTeams({
1471
- cfg: ctx.cfg,
1472
- to,
1473
- userId,
1474
- role
1475
- }));
1476
- }
1477
- });
1478
- }
1479
- if (ctx.action === "removeParticipant") {
1480
- const userId = typeof ctx.params.userId === "string" ? ctx.params.userId.trim() : "";
1481
- if (!userId) return actionError("removeParticipant requires a userId.");
1482
- return await runWithRequiredActionTarget({
1483
- actionLabel: "removeParticipant",
1484
- toolParams: ctx.params,
1485
- currentChannelId: ctx.toolContext?.currentChannelId,
1486
- run: async (to) => {
1487
- const { removeParticipantMSTeams } = await loadMSTeamsChannelRuntime();
1488
- return jsonMSTeamsOkActionResult("removeParticipant", await removeParticipantMSTeams({
1597
+ const role = action === "addParticipant" ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.role) : void 0;
1598
+ const runtime = await loadMSTeamsChannelRuntime();
1599
+ const params = {
1489
1600
  cfg: ctx.cfg,
1490
1601
  to,
1491
1602
  userId
1492
- }));
1603
+ };
1604
+ const result = action === "addParticipant" ? await runtime.addParticipantMSTeams({
1605
+ ...params,
1606
+ role
1607
+ }) : await runtime.removeParticipantMSTeams(params);
1608
+ return jsonMSTeamsOkActionResult(action, result);
1493
1609
  }
1494
1610
  });
1495
1611
  }
@@ -1541,25 +1657,21 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1541
1657
  }
1542
1658
  return lines;
1543
1659
  },
1544
- resolveAccountSnapshot: ({ account, runtime }) => ({
1660
+ resolveAccountSnapshot: ({ account }) => ({
1545
1661
  accountId: account.accountId,
1546
1662
  enabled: account.enabled,
1547
1663
  configured: account.configured,
1548
- extra: {
1549
- port: runtime?.port ?? null,
1550
- tokenStatus: account.tokenStatus
1551
- }
1664
+ extra: { tokenStatus: account.tokenStatus }
1552
1665
  })
1553
1666
  }),
1554
1667
  gateway: { startAccount: async (ctx) => {
1555
- const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-CpKfpP1m.cjs"));
1556
- const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1668
+ const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./monitor-BJ7IyH4y.cjs"));
1669
+ const webhookPath = ctx.cfg.channels?.msteams?.webhook?.path || "/api/messages";
1557
1670
  const statusSink = (0, openclaw_plugin_sdk_channel_outbound.createAccountStatusSink)({
1558
1671
  accountId: ctx.accountId,
1559
1672
  setStatus: ctx.setStatus
1560
1673
  });
1561
- statusSink({ port });
1562
- ctx.log?.info(`starting provider (port ${port})`);
1674
+ ctx.log?.info(`starting provider (Gateway route ${webhookPath})`);
1563
1675
  if (isMSTeamsNativeApprovalClientEnabled({
1564
1676
  cfg: ctx.cfg,
1565
1677
  accountId: ctx.accountId
@@ -1649,10 +1761,10 @@ Object.defineProperty(exports, "msteamsPlugin", {
1649
1761
  return msteamsPlugin;
1650
1762
  }
1651
1763
  });
1652
- Object.defineProperty(exports, "resolveMSTeamsAllowlistMatch", {
1764
+ Object.defineProperty(exports, "resolveMSTeamsLegacyWebhook", {
1653
1765
  enumerable: true,
1654
1766
  get: function() {
1655
- return resolveMSTeamsAllowlistMatch;
1767
+ return resolveMSTeamsLegacyWebhook;
1656
1768
  }
1657
1769
  });
1658
1770
  Object.defineProperty(exports, "resolveMSTeamsReplyPolicy", {
@@ -1667,6 +1779,12 @@ Object.defineProperty(exports, "resolveMSTeamsRouteConfig", {
1667
1779
  return resolveMSTeamsRouteConfig;
1668
1780
  }
1669
1781
  });
1782
+ Object.defineProperty(exports, "resolveMSTeamsWebhookPathIssue", {
1783
+ enumerable: true,
1784
+ get: function() {
1785
+ return resolveMSTeamsWebhookPathIssue;
1786
+ }
1787
+ });
1670
1788
  Object.defineProperty(exports, "shouldHandleMSTeamsNativeApprovalRequest", {
1671
1789
  enumerable: true,
1672
1790
  get: function() {