@openclaw/msteams 2026.9.6 → 2026.9.8

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-CQWZeqB5.cjs → adapter.runtime-BiWeMKXE.cjs} +21 -29
  3. package/dist/.setup/{approval-card-CPNH_q3P.cjs → approval-card-DWPDItvq.cjs} +6 -3
  4. package/dist/.setup/{approval-handler.runtime-CUnanUdR.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-BDp16XRR.cjs → channel-ByzS7QJ0.cjs} +286 -180
  7. package/dist/.setup/{channel.runtime-Cv5F8JCa.cjs → channel.runtime-Baz8XDFs.cjs} +43 -142
  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-8RA1FUJa.cjs → conversation-store-state-B7JuyZTm.cjs} +693 -287
  11. package/dist/.setup/{src-BfOCwlHp.cjs → monitor-BJ7IyH4y.cjs} +422 -592
  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-CYN_N7O1.cjs → send-VUM7Sryb.cjs} +43 -96
  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 +9 -9
  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");
@@ -43,13 +43,13 @@ function resolveActionUploadFilePath(params) {
43
43
  }
44
44
  //#endregion
45
45
  //#region extensions/msteams/src/action-results.ts
46
- function jsonActionResult(data) {
46
+ function jsonActionResult(data, details = data) {
47
47
  return {
48
48
  content: [{
49
49
  type: "text",
50
50
  text: JSON.stringify(data)
51
51
  }],
52
- details: data
52
+ details
53
53
  };
54
54
  }
55
55
  function jsonMSTeamsActionResult(action, data = {}) {
@@ -68,7 +68,7 @@ function jsonMSTeamsOkActionResult(action, data = {}) {
68
68
  });
69
69
  }
70
70
  function jsonMSTeamsConversationResult(conversationId) {
71
- return jsonActionResultWithDetails({
71
+ return jsonActionResult({
72
72
  ok: true,
73
73
  channel: "msteams",
74
74
  conversationId
@@ -77,15 +77,6 @@ function jsonMSTeamsConversationResult(conversationId) {
77
77
  channel: "msteams"
78
78
  });
79
79
  }
80
- function jsonActionResultWithDetails(contentData, details) {
81
- return {
82
- content: [{
83
- type: "text",
84
- text: JSON.stringify(contentData)
85
- }],
86
- details
87
- };
88
- }
89
80
  function actionError(message) {
90
81
  return {
91
82
  isError: true,
@@ -240,18 +231,18 @@ function resolveMSTeamsGroupToolPolicy(params) {
240
231
  ...senderScope
241
232
  });
242
233
  }
243
- function resolveMSTeamsAllowlistMatch(params) {
244
- return (0, openclaw_plugin_sdk_allow_from.resolveAllowlistMatchSimple)(params);
245
- }
246
234
  function resolveMSTeamsReplyPolicy(params) {
247
235
  if (params.isDirectMessage) return {
248
236
  requireMention: false,
249
237
  replyStyle: "thread"
250
238
  };
251
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;
252
242
  return {
253
243
  requireMention,
254
- 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 }
255
246
  };
256
247
  }
257
248
  //#endregion
@@ -402,7 +393,7 @@ const msTeamsLazyApprovalNativeRuntime = (0, openclaw_plugin_sdk_approval_handle
402
393
  request
403
394
  }),
404
395
  load: async () => {
405
- const { msTeamsApprovalNativeRuntime } = await Promise.resolve().then(() => require("./approval-handler.runtime-CUnanUdR.cjs"));
396
+ const { msTeamsApprovalNativeRuntime } = await Promise.resolve().then(() => require("./approval-handler.runtime-D1s7UR3U.cjs"));
406
397
  return msTeamsApprovalNativeRuntime;
407
398
  }
408
399
  });
@@ -418,7 +409,7 @@ const msTeamsApprovalCapability = {
418
409
  ...(0, openclaw_plugin_sdk_approval_delivery_runtime.createApproverRestrictedNativeApprovalCapability)({
419
410
  channel: "msteams",
420
411
  channelLabel: "Microsoft Teams",
421
- 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.",
422
413
  listAccountIds: require_channel_setup.msteamsConfigAdapter.listAccountIds,
423
414
  hasApprovers: ({ cfg, accountId }) => require_thread_session.getMSTeamsApprovalApprovers({
424
415
  cfg,
@@ -449,6 +440,160 @@ const msTeamsApprovalCapability = {
449
440
  authorizeActorAction: (params) => require_thread_session.msTeamsApprovalAuth.authorizeActorAction?.(params)
450
441
  };
451
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
452
597
  //#region extensions/msteams/src/doctor.ts
453
598
  const isMSTeamsMutableAllowEntry = (0, openclaw_plugin_sdk_channel_policy.buildMutableAllowEntryDetector)({
454
599
  prefixes: ["msteams:", "user:"],
@@ -459,6 +604,39 @@ const collectMSTeamsMutableAllowlistWarnings = (0, openclaw_plugin_sdk_channel_p
459
604
  detector: isMSTeamsMutableAllowEntry,
460
605
  collectLists: (scope) => (0, openclaw_plugin_sdk_channel_policy.collectStandardAllowlistLists)(scope)
461
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
+ };
462
640
  //#endregion
463
641
  //#region extensions/msteams/src/graph-action-context.ts
464
642
  const MSTEAMS_GROUP_MANAGEMENT_ACTIONS = /* @__PURE__ */ new Set([
@@ -861,7 +1039,7 @@ const collectMSTeamsSecurityFindings = openclaw_plugin_sdk_channel_policy.create
861
1039
  severity: "warn",
862
1040
  title: "MS Teams security warning"
863
1041
  });
864
- const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-Cv5F8JCa.cjs")), "msTeamsChannelRuntime");
1042
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-Baz8XDFs.cjs")), "msTeamsChannelRuntime");
865
1043
  const MSTEAMS_REACTION_TYPES = [
866
1044
  "like",
867
1045
  "heart",
@@ -891,18 +1069,6 @@ function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelI
891
1069
  function resolveCurrentGraphActionTarget(toolContext) {
892
1070
  return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentGraphChannelId) ?? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentMessagingTarget);
893
1071
  }
894
- function resolveActionMessageId(params) {
895
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.messageId) ?? "";
896
- }
897
- function resolveActionPinnedMessageId(params) {
898
- return typeof params.pinnedMessageId === "string" ? params.pinnedMessageId.trim() : typeof params.messageId === "string" ? params.messageId.trim() : "";
899
- }
900
- function resolveActionQuery(params) {
901
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.query) ?? "";
902
- }
903
- function readOptionalTrimmedString(params, key) {
904
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params[key]);
905
- }
906
1072
  function resolveMSTeamsActionTarget(params) {
907
1073
  return params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
908
1074
  }
@@ -919,7 +1085,7 @@ async function runWithRequiredActionMessageTarget(params) {
919
1085
  }) ? (0, openclaw_plugin_sdk_channel_actions.resolveReactionMessageId)({
920
1086
  args: params.toolParams,
921
1087
  toolContext: { currentMessageId: params.currentMessageId ?? void 0 }
922
- }) : resolveActionMessageId(params.toolParams);
1088
+ }) : (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.toolParams.messageId) ?? "";
923
1089
  const messageId = messageIdRaw == null ? "" : String(messageIdRaw).trim();
924
1090
  if (!to || !messageId) return actionError(`${params.actionLabel} requires a target (to) and messageId.`);
925
1091
  return await params.run({
@@ -929,7 +1095,7 @@ async function runWithRequiredActionMessageTarget(params) {
929
1095
  }
930
1096
  async function runWithRequiredActionPinnedMessageTarget(params) {
931
1097
  const to = resolveMSTeamsActionTarget(params);
932
- 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) ?? "";
933
1099
  if (!to || !pinnedMessageId) return actionError(`${params.actionLabel} requires a target (to) and pinnedMessageId.`);
934
1100
  return await params.run({
935
1101
  to,
@@ -1022,21 +1188,15 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1022
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."] },
1023
1189
  groups: { resolveToolPolicy: resolveMSTeamsGroupToolPolicy },
1024
1190
  approvalCapability: msTeamsApprovalCapability,
1025
- doctor: {
1026
- dmAllowFromMode: "topOnly",
1027
- groupModel: "hybrid",
1028
- groupAllowFromFallbackToAllowFrom: true,
1029
- warnOnEmptyGroupSenderAllowlist: true,
1030
- collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings
1031
- },
1191
+ doctor: msteamsDoctor,
1032
1192
  messaging: {
1033
1193
  targetPrefixes: ["msteams", "teams"],
1034
1194
  directTargetStyle: "user-prefixed",
1035
1195
  normalizeTarget: require_resolve_allowlist.normalizeMSTeamsMessagingTarget,
1036
1196
  inferTargetChatType: ({ to }) => inferMSTeamsTargetChatType(to),
1037
- resolveOutboundSessionRoute: (params) => resolveMSTeamsOutboundSessionRoute(params),
1197
+ resolveOutboundSessionRoute: resolveMSTeamsOutboundSessionRoute,
1038
1198
  targetResolver: {
1039
- looksLikeId: (raw) => require_resolve_allowlist.looksLikeMSTeamsTargetId(raw),
1199
+ looksLikeId: require_resolve_allowlist.looksLikeMSTeamsTargetId,
1040
1200
  hint: "<conversationId|user:ID|conversation:ID>"
1041
1201
  }
1042
1202
  },
@@ -1057,7 +1217,6 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1057
1217
  name: void 0,
1058
1218
  note: void 0
1059
1219
  }));
1060
- const stripPrefix = (value) => require_resolve_allowlist.normalizeMSTeamsUserInput(value);
1061
1220
  const markPendingLookupFailed = (pending) => {
1062
1221
  pending.forEach(({ index }) => {
1063
1222
  const entry = results[index];
@@ -1085,7 +1244,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1085
1244
  entry.note = "empty input";
1086
1245
  return;
1087
1246
  }
1088
- const cleaned = stripPrefix(trimmed);
1247
+ const cleaned = require_resolve_allowlist.normalizeMSTeamsUserInput(trimmed);
1089
1248
  if (/^[0-9a-fA-F-]{16,}$/.test(cleaned) || cleaned.includes("@")) {
1090
1249
  entry.resolved = true;
1091
1250
  entry.id = cleaned;
@@ -1198,15 +1357,11 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1198
1357
  assertDirectAdapterHandoff: ctx.assertDirectAdapterHandoff,
1199
1358
  onPlatformSendDispatch: ctx.onPlatformSendDispatch
1200
1359
  });
1201
- return jsonActionResultWithDetails({
1360
+ return jsonActionResult({
1202
1361
  ok: true,
1203
1362
  channel: "msteams",
1204
1363
  messageId: result.messageId,
1205
1364
  conversationId: result.conversationId
1206
- }, {
1207
- ok: true,
1208
- channel: "msteams",
1209
- messageId: result.messageId
1210
1365
  });
1211
1366
  }
1212
1367
  });
@@ -1225,62 +1380,47 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1225
1380
  to,
1226
1381
  text: resolveActionContent(ctx.params),
1227
1382
  mediaUrl,
1228
- 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),
1229
1384
  mediaAccess: ctx.mediaAccess,
1230
1385
  mediaLocalRoots: ctx.mediaLocalRoots,
1231
1386
  mediaReadFile: ctx.mediaReadFile,
1232
1387
  assertDirectAdapterHandoff: ctx.assertDirectAdapterHandoff,
1233
1388
  onPlatformSendDispatch: ctx.onPlatformSendDispatch
1234
1389
  });
1235
- return jsonActionResultWithDetails({
1390
+ return jsonActionResult({
1236
1391
  ok: true,
1237
1392
  channel: "msteams",
1238
1393
  action: "upload-file",
1239
1394
  messageId: result.messageId,
1240
1395
  conversationId: result.conversationId,
1241
1396
  ...result.pendingUploadId ? { pendingUploadId: result.pendingUploadId } : {}
1242
- }, {
1243
- ok: true,
1244
- channel: "msteams",
1245
- messageId: result.messageId,
1246
- ...result.pendingUploadId ? { pendingUploadId: result.pendingUploadId } : {}
1247
1397
  });
1248
1398
  }
1249
1399
  });
1250
1400
  }
1251
- if (ctx.action === "edit") {
1252
- const content = resolveActionContent(ctx.params);
1253
- 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.");
1254
1405
  return await runWithRequiredActionMessageTarget({
1255
- actionLabel: "Edit",
1406
+ actionLabel: action === "edit" ? "Edit" : "Delete",
1256
1407
  toolParams: ctx.params,
1257
1408
  currentChannelId: ctx.toolContext?.currentChannelId,
1258
1409
  run: async (target) => {
1259
1410
  const to = await authorizeActionTarget(target.to);
1260
- const { editMessageMSTeams } = await loadMSTeamsChannelRuntime();
1261
- return jsonMSTeamsConversationResult((await editMessageMSTeams({
1411
+ const runtime = await loadMSTeamsChannelRuntime();
1412
+ const params = {
1262
1413
  cfg: ctx.cfg,
1263
1414
  to,
1264
- activityId: target.messageId,
1415
+ activityId: target.messageId
1416
+ };
1417
+ return jsonMSTeamsConversationResult((action === "edit" ? await runtime.editMessageMSTeams({
1418
+ ...params,
1265
1419
  text: content
1266
- })).conversationId);
1420
+ }) : await runtime.deleteMessageMSTeams(params)).conversationId);
1267
1421
  }
1268
1422
  });
1269
1423
  }
1270
- if (ctx.action === "delete") return await runWithRequiredActionMessageTarget({
1271
- actionLabel: "Delete",
1272
- toolParams: ctx.params,
1273
- currentChannelId: ctx.toolContext?.currentChannelId,
1274
- run: async (target) => {
1275
- const to = await authorizeActionTarget(target.to);
1276
- const { deleteMessageMSTeams } = await loadMSTeamsChannelRuntime();
1277
- return jsonMSTeamsConversationResult((await deleteMessageMSTeams({
1278
- cfg: ctx.cfg,
1279
- to,
1280
- activityId: target.messageId
1281
- })).conversationId);
1282
- }
1283
- });
1284
1424
  const graphActionTarget = {
1285
1425
  toolParams: ctx.action === "search" || ctx.action === "member-info" ? {
1286
1426
  ...ctx.params,
@@ -1292,32 +1432,33 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1292
1432
  currentMessageId: ctx.toolContext?.currentMessageId,
1293
1433
  graphOnly: true
1294
1434
  };
1295
- if (ctx.action === "read") return await runWithRequiredActionMessageTarget({
1296
- actionLabel: "Read",
1297
- ...graphActionTarget,
1298
- run: async (target) => {
1299
- const to = await authorizeActionTarget(target.to);
1300
- const { getMessageMSTeams } = await loadMSTeamsChannelRuntime();
1301
- return jsonMSTeamsOkActionResult("read", { message: await getMessageMSTeams({
1302
- cfg: ctx.cfg,
1303
- to,
1304
- messageId: target.messageId
1305
- }) });
1306
- }
1307
- });
1308
- if (ctx.action === "pin") return await runWithRequiredActionMessageTarget({
1309
- actionLabel: "Pin",
1310
- ...graphActionTarget,
1311
- run: async (target) => {
1312
- const to = await authorizeActionTarget(target.to);
1313
- const { pinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1314
- return jsonMSTeamsActionResult("pin", await pinMessageMSTeams({
1315
- cfg: ctx.cfg,
1316
- to,
1317
- messageId: target.messageId
1318
- }));
1319
- }
1320
- });
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
+ }
1321
1462
  if (ctx.action === "unpin") return await runWithRequiredActionPinnedMessageTarget({
1322
1463
  actionLabel: "Unpin",
1323
1464
  ...graphActionTarget,
@@ -1362,51 +1503,26 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1362
1503
  }
1363
1504
  };
1364
1505
  const to = await authorizeActionTarget(target.to);
1365
- if (remove) {
1366
- const { unreactMessageMSTeams } = await loadMSTeamsChannelRuntime();
1367
- return jsonMSTeamsActionResult("react", {
1368
- removed: true,
1369
- reactionType: emoji,
1370
- ...await unreactMessageMSTeams({
1371
- cfg: ctx.cfg,
1372
- to,
1373
- messageId: target.messageId,
1374
- reactionType: emoji
1375
- })
1376
- });
1377
- }
1378
- 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
+ });
1379
1513
  return jsonMSTeamsActionResult("react", {
1514
+ ...remove ? { removed: true } : {},
1380
1515
  reactionType: emoji,
1381
- ...await reactMessageMSTeams({
1382
- cfg: ctx.cfg,
1383
- to,
1384
- messageId: target.messageId,
1385
- reactionType: emoji
1386
- })
1516
+ ...result
1387
1517
  });
1388
1518
  }
1389
1519
  });
1390
- if (ctx.action === "reactions") return await runWithRequiredActionMessageTarget({
1391
- actionLabel: "Reactions",
1392
- ...graphActionTarget,
1393
- allowCurrentMessageIdFallback: true,
1394
- run: async (target) => {
1395
- const to = await authorizeActionTarget(target.to);
1396
- const { listReactionsMSTeams } = await loadMSTeamsChannelRuntime();
1397
- return jsonMSTeamsOkActionResult("reactions", await listReactionsMSTeams({
1398
- cfg: ctx.cfg,
1399
- to,
1400
- messageId: target.messageId
1401
- }));
1402
- }
1403
- });
1404
1520
  if (ctx.action === "search") return await runWithRequiredActionTarget({
1405
1521
  actionLabel: "Search",
1406
1522
  ...graphActionTarget,
1407
1523
  run: async (to) => {
1408
1524
  const allowedTarget = await authorizeActionTarget(to);
1409
- const query = resolveActionQuery(ctx.params);
1525
+ const query = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.query);
1410
1526
  if (!query) return actionError("Search requires a target (to) and query.");
1411
1527
  const limit = (0, openclaw_plugin_sdk_channel_actions.readPositiveIntegerParam)(ctx.params, "limit");
1412
1528
  const from = typeof ctx.params.from === "string" ? ctx.params.from.trim() : void 0;
@@ -1469,39 +1585,27 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1469
1585
  channelId: graphChannelId
1470
1586
  })).channel });
1471
1587
  }
1472
- if (ctx.action === "addParticipant") {
1473
- const userId = typeof ctx.params.userId === "string" ? ctx.params.userId.trim() : "";
1474
- 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.`);
1475
1592
  return await runWithRequiredActionTarget({
1476
- actionLabel: "addParticipant",
1593
+ actionLabel: action,
1477
1594
  toolParams: ctx.params,
1478
1595
  currentChannelId: ctx.toolContext?.currentChannelId,
1479
1596
  run: async (to) => {
1480
- const role = readOptionalTrimmedString(ctx.params, "role");
1481
- const { addParticipantMSTeams } = await loadMSTeamsChannelRuntime();
1482
- return jsonMSTeamsOkActionResult("addParticipant", await addParticipantMSTeams({
1483
- cfg: ctx.cfg,
1484
- to,
1485
- userId,
1486
- role
1487
- }));
1488
- }
1489
- });
1490
- }
1491
- if (ctx.action === "removeParticipant") {
1492
- const userId = typeof ctx.params.userId === "string" ? ctx.params.userId.trim() : "";
1493
- if (!userId) return actionError("removeParticipant requires a userId.");
1494
- return await runWithRequiredActionTarget({
1495
- actionLabel: "removeParticipant",
1496
- toolParams: ctx.params,
1497
- currentChannelId: ctx.toolContext?.currentChannelId,
1498
- run: async (to) => {
1499
- const { removeParticipantMSTeams } = await loadMSTeamsChannelRuntime();
1500
- 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 = {
1501
1600
  cfg: ctx.cfg,
1502
1601
  to,
1503
1602
  userId
1504
- }));
1603
+ };
1604
+ const result = action === "addParticipant" ? await runtime.addParticipantMSTeams({
1605
+ ...params,
1606
+ role
1607
+ }) : await runtime.removeParticipantMSTeams(params);
1608
+ return jsonMSTeamsOkActionResult(action, result);
1505
1609
  }
1506
1610
  });
1507
1611
  }
@@ -1553,25 +1657,21 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1553
1657
  }
1554
1658
  return lines;
1555
1659
  },
1556
- resolveAccountSnapshot: ({ account, runtime }) => ({
1660
+ resolveAccountSnapshot: ({ account }) => ({
1557
1661
  accountId: account.accountId,
1558
1662
  enabled: account.enabled,
1559
1663
  configured: account.configured,
1560
- extra: {
1561
- port: runtime?.port ?? null,
1562
- tokenStatus: account.tokenStatus
1563
- }
1664
+ extra: { tokenStatus: account.tokenStatus }
1564
1665
  })
1565
1666
  }),
1566
1667
  gateway: { startAccount: async (ctx) => {
1567
- const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-BfOCwlHp.cjs"));
1568
- 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";
1569
1670
  const statusSink = (0, openclaw_plugin_sdk_channel_outbound.createAccountStatusSink)({
1570
1671
  accountId: ctx.accountId,
1571
1672
  setStatus: ctx.setStatus
1572
1673
  });
1573
- statusSink({ port });
1574
- ctx.log?.info(`starting provider (port ${port})`);
1674
+ ctx.log?.info(`starting provider (Gateway route ${webhookPath})`);
1575
1675
  if (isMSTeamsNativeApprovalClientEnabled({
1576
1676
  cfg: ctx.cfg,
1577
1677
  accountId: ctx.accountId
@@ -1661,10 +1761,10 @@ Object.defineProperty(exports, "msteamsPlugin", {
1661
1761
  return msteamsPlugin;
1662
1762
  }
1663
1763
  });
1664
- Object.defineProperty(exports, "resolveMSTeamsAllowlistMatch", {
1764
+ Object.defineProperty(exports, "resolveMSTeamsLegacyWebhook", {
1665
1765
  enumerable: true,
1666
1766
  get: function() {
1667
- return resolveMSTeamsAllowlistMatch;
1767
+ return resolveMSTeamsLegacyWebhook;
1668
1768
  }
1669
1769
  });
1670
1770
  Object.defineProperty(exports, "resolveMSTeamsReplyPolicy", {
@@ -1679,6 +1779,12 @@ Object.defineProperty(exports, "resolveMSTeamsRouteConfig", {
1679
1779
  return resolveMSTeamsRouteConfig;
1680
1780
  }
1681
1781
  });
1782
+ Object.defineProperty(exports, "resolveMSTeamsWebhookPathIssue", {
1783
+ enumerable: true,
1784
+ get: function() {
1785
+ return resolveMSTeamsWebhookPathIssue;
1786
+ }
1787
+ });
1682
1788
  Object.defineProperty(exports, "shouldHandleMSTeamsNativeApprovalRequest", {
1683
1789
  enumerable: true,
1684
1790
  get: function() {