@openclaw/msteams 2026.8.1-beta.2 → 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.
@@ -1,16 +1,17 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
2
2
  let openclaw_plugin_sdk_ssrf_runtime = require("openclaw/plugin-sdk/ssrf-runtime");
3
- let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
4
3
  let node_crypto = require("node:crypto");
5
4
  let node_fs_promises = require("node:fs/promises");
6
5
  node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises, 1);
7
6
  let node_path = require("node:path");
8
7
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
8
+ let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
9
9
  let node_timers_promises = require("node:timers/promises");
10
10
  let node_url = require("node:url");
11
11
  let node_events = require("node:events");
12
12
  let node_http = require("node:http");
13
13
  //#region extensions/msteams/src/qa/bot-framework-server.ts
14
+ const AMBIGUOUS_GATEWAY_TIMEOUT_MARKER = "QA-MSTEAMS-AMBIGUOUS-504";
14
15
  async function readJson(request) {
15
16
  const chunks = [];
16
17
  for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
@@ -53,7 +54,8 @@ async function startMSTeamsQaBotFrameworkServer(options) {
53
54
  conversationId: route.conversationId,
54
55
  ...route.threadId ? { threadId: route.threadId } : {}
55
56
  });
56
- sendJson(response, 200, { id: activityId });
57
+ const acceptedButTimedOut = typeof activity.text === "string" && activity.text.includes(AMBIGUOUS_GATEWAY_TIMEOUT_MARKER);
58
+ sendJson(response, acceptedButTimedOut ? 504 : 200, acceptedButTimedOut ? { error: "gateway timeout after acceptance" } : { id: activityId });
57
59
  })().catch((error) => {
58
60
  sendJson(response, 500, { error: (0, openclaw_plugin_sdk_error_runtime.coerceErrorMessage)(error) });
59
61
  });
package/dist/api.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./channel-DfCbi0d_.cjs");
3
- const require_setup_surface = require("./setup-surface-DAhGL2h8.cjs");
4
- exports.createMSTeamsSetupWizardBase = require_setup_surface.createMSTeamsSetupWizardBase;
2
+ const require_channel = require("./channel-KpWENcgK.cjs");
3
+ const require_channel_setup = require("./channel.setup-mOFtsfYz.cjs");
4
+ exports.createMSTeamsSetupWizardBase = require_channel_setup.createMSTeamsSetupWizardBase;
5
5
  exports.msteamsPlugin = require_channel.msteamsPlugin;
6
- exports.msteamsSetupAdapter = require_setup_surface.msteamsSetupAdapter;
7
- exports.msteamsSetupWizard = require_setup_surface.msteamsSetupWizard;
8
- exports.openDelegatedOAuthUrl = require_setup_surface.openDelegatedOAuthUrl;
6
+ exports.msteamsSetupAdapter = require_channel_setup.msteamsSetupAdapter;
7
+ exports.msteamsSetupWizard = require_channel_setup.msteamsSetupWizard;
8
+ exports.openDelegatedOAuthUrl = require_channel_setup.openDelegatedOAuthUrl;
@@ -1,8 +1,7 @@
1
1
  require("./runtime-api.cjs");
2
- const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
3
- const require_setup_surface = require("./setup-surface-DAhGL2h8.cjs");
4
- const require_config_schema = require("./config-schema-C4CszdDi.cjs");
5
- let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
3
+ const require_directory_contract_api = require("./directory-contract-api.cjs");
4
+ const require_channel_setup = require("./channel.setup-mOFtsfYz.cjs");
6
5
  let openclaw_plugin_sdk_channel_core = require("openclaw/plugin-sdk/channel-core");
7
6
  let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
8
7
  let openclaw_plugin_sdk_channel_pairing = require("openclaw/plugin-sdk/channel-pairing");
@@ -686,7 +685,13 @@ const collectMSTeamsSecurityWarnings = (0, openclaw_plugin_sdk_channel_policy.cr
686
685
  resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
687
686
  collect: ({ groupPolicy }) => groupPolicy === "open" ? ["- MS Teams groups: groupPolicy=\"open\" allows any member to trigger (mention-gated). Set channels.msteams.groupPolicy=\"allowlist\" + channels.msteams.groupAllowFrom to restrict senders."] : []
688
687
  });
689
- const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-BJmueA4q.cjs")), "msTeamsChannelRuntime");
688
+ const collectMSTeamsSecurityFindings = openclaw_plugin_sdk_channel_policy.createConditionalWarningCollector.findings({
689
+ collectWarnings: collectMSTeamsSecurityWarnings,
690
+ checkId: "channels.msteams.groups.open",
691
+ severity: "critical",
692
+ title: "MS Teams security warning"
693
+ });
694
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-Bkzj8jZ0.cjs")), "msTeamsChannelRuntime");
690
695
  function jsonActionResult(data) {
691
696
  return {
692
697
  content: [{
@@ -821,7 +826,8 @@ async function runWithRequiredActionPinnedMessageTarget(params) {
821
826
  });
822
827
  }
823
828
  function describeMSTeamsMessageTool({ cfg }) {
824
- const enabled = cfg.channels?.msteams?.enabled !== false && Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams));
829
+ const account = require_channel_setup.resolveMSTeamsAccount(cfg);
830
+ const enabled = account.enabled && account.configured && account.tokenStatus === "available";
825
831
  return {
826
832
  actions: enabled ? [
827
833
  "upload-file",
@@ -891,38 +897,13 @@ const msteamsMessageAdapter = (0, openclaw_plugin_sdk_channel_outbound.createCha
891
897
  });
892
898
  const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlugin)({
893
899
  base: {
894
- id: "msteams",
895
- meta: {
896
- ...require_setup_surface.msteamsMeta,
897
- aliases: [...require_setup_surface.msteamsMeta.aliases]
898
- },
899
- setupWizard: require_setup_surface.msteamsSetupWizard,
900
- capabilities: {
901
- chatTypes: [
902
- "direct",
903
- "channel",
904
- "thread"
905
- ],
906
- polls: true,
907
- threads: true,
908
- media: true
909
- },
900
+ ...require_channel_setup.msteamsSetupPlugin,
910
901
  streaming: { blockStreamingCoalesceDefaults: {
911
902
  minChars: 1500,
912
903
  idleMs: 1e3
913
904
  } },
914
905
  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."] },
915
906
  groups: { resolveToolPolicy: resolveMSTeamsGroupToolPolicy },
916
- reload: { configPrefixes: ["channels.msteams"] },
917
- configSchema: require_config_schema.MSTeamsChannelConfigSchema,
918
- config: {
919
- ...require_setup_surface.msteamsConfigAdapter,
920
- isConfigured: (_account, cfg) => Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams)),
921
- describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
922
- account,
923
- configured: account.configured
924
- })
925
- },
926
907
  approvalCapability: msTeamsApprovalAuth,
927
908
  doctor: {
928
909
  dmAllowFromMode: "topOnly",
@@ -931,7 +912,6 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
931
912
  warnOnEmptyGroupSenderAllowlist: true,
932
913
  collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings
933
914
  },
934
- setupContract: require_setup_surface.msteamsSetupContract,
935
915
  messaging: {
936
916
  targetPrefixes: ["msteams", "teams"],
937
917
  directTargetStyle: "user-prefixed",
@@ -945,34 +925,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
945
925
  },
946
926
  message: msteamsMessageAdapter,
947
927
  directory: (0, openclaw_plugin_sdk_directory_runtime.createChannelDirectoryAdapter)({
948
- self: async ({ cfg }) => {
949
- const creds = require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams);
950
- if (!creds) return null;
951
- return {
952
- kind: "user",
953
- id: creds.appId,
954
- name: creds.appId
955
- };
956
- },
957
- listPeers: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
958
- kind: "user",
959
- sources: [cfg.channels?.msteams?.allowFrom ?? [], Object.keys(cfg.channels?.msteams?.dms ?? {})],
960
- query,
961
- limit,
962
- normalizeId: (raw) => {
963
- const normalized = require_resolve_allowlist.normalizeMSTeamsMessagingTarget(raw) ?? raw;
964
- const lowered = normalized.toLowerCase();
965
- if (lowered.startsWith("user:") || lowered.startsWith("conversation:")) return normalized;
966
- return `user:${normalized}`;
967
- }
968
- }),
969
- listGroups: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
970
- kind: "group",
971
- sources: [Object.values(cfg.channels?.msteams?.teams ?? {}).flatMap((team) => Object.keys(team.channels ?? {}))],
972
- query,
973
- limit,
974
- normalizeId: (raw) => `conversation:${raw.replace(/^conversation:/i, "").trim()}`
975
- }),
928
+ ...require_directory_contract_api.msteamsDirectoryContractPlugin.directory,
976
929
  ...(0, openclaw_plugin_sdk_directory_runtime.createRuntimeDirectoryLiveAdapter)({
977
930
  getRuntime: loadMSTeamsChannelRuntime,
978
931
  listPeersLive: (runtime) => runtime.listMSTeamsDirectoryPeersLive,
@@ -1087,6 +1040,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1087
1040
  return results;
1088
1041
  } },
1089
1042
  actions: {
1043
+ providerOwnedReadGates: true,
1090
1044
  describeMessageTool: describeMSTeamsMessageTool,
1091
1045
  extractToolSendResult: ({ result, send }) => extractMSTeamsToolSendResult(result, send),
1092
1046
  requiresTrustedRequesterSender: ({ action, toolContext }) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentChannelProvider)?.toLowerCase() === "msteams" && MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(action),
@@ -1467,11 +1421,14 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1467
1421
  accountId: account.accountId,
1468
1422
  enabled: account.enabled,
1469
1423
  configured: account.configured,
1470
- extra: { port: runtime?.port ?? null }
1424
+ extra: {
1425
+ port: runtime?.port ?? null,
1426
+ tokenStatus: account.tokenStatus
1427
+ }
1471
1428
  })
1472
1429
  }),
1473
1430
  gateway: { startAccount: async (ctx) => {
1474
- const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-Bz9wY0Mr.cjs"));
1431
+ const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-C127-DcQ.cjs"));
1475
1432
  const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1476
1433
  const statusSink = (0, openclaw_plugin_sdk_channel_outbound.createAccountStatusSink)({
1477
1434
  accountId: ctx.accountId,
@@ -1487,7 +1444,7 @@ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlug
1487
1444
  });
1488
1445
  } }
1489
1446
  },
1490
- security: { collectWarnings: (0, openclaw_plugin_sdk_channel_policy.projectConfigWarningCollector)(collectMSTeamsSecurityWarnings) },
1447
+ security: { collectWarnings: ({ cfg }) => collectMSTeamsSecurityFindings({ cfg }) },
1491
1448
  pairing: { text: {
1492
1449
  idLabel: "msteamsUserId",
1493
1450
  message: openclaw_plugin_sdk_channel_status.PAIRING_APPROVED_MESSAGE,
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./channel-DfCbi0d_.cjs");
2
+ const require_channel = require("./channel-KpWENcgK.cjs");
3
3
  exports.msteamsPlugin = require_channel.msteamsPlugin;
@@ -1,10 +1,10 @@
1
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
2
2
  require("./runtime-api.cjs");
3
- const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
4
- const require_channel = require("./channel-DfCbi0d_.cjs");
5
- const require_setup_surface = require("./setup-surface-DAhGL2h8.cjs");
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
6
  const require_polls = require("./polls-DvuJvaDG.cjs");
7
- const require_messenger = require("./messenger-BqA8G3pY.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");
@@ -654,6 +654,9 @@ async function findConversationReference(recipient) {
654
654
  async function resolveMSTeamsSendContext(params) {
655
655
  const msteamsCfg = params.cfg.channels?.msteams;
656
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");
657
660
  const creds = require_resolve_allowlist.resolveMSTeamsCredentials(msteamsCfg);
658
661
  if (!creds) throw new Error("msteams credentials not configured");
659
662
  const store = require_polls.createMSTeamsConversationStoreState();
@@ -675,7 +678,7 @@ async function resolveMSTeamsSendContext(params) {
675
678
  } catch (err) {
676
679
  log.warn?.("failed to remove blocked msteams conversation reference", {
677
680
  conversationId,
678
- error: require_setup_surface.formatUnknownError(err)
681
+ error: require_channel_setup.formatUnknownError(err)
679
682
  });
680
683
  }
681
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.`);
@@ -922,10 +925,10 @@ async function sendMessageMSTeams(params) {
922
925
  kind: "media"
923
926
  });
924
927
  } catch (err) {
925
- const classification = require_setup_surface.classifyMSTeamsSendError(err);
926
- const hint = require_setup_surface.formatMSTeamsSendErrorHint(classification);
928
+ const classification = require_channel_setup.classifyMSTeamsSendError(err);
929
+ const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
927
930
  const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
928
- throw new Error(`msteams file send failed${status}: ${require_setup_surface.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
931
+ throw new Error(`msteams file send failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
929
932
  }
930
933
  }
931
934
  return sendTextWithMedia(ctx, messageText, void 0);
@@ -960,10 +963,10 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
960
963
  serviceUrlBoundary: ctx.sdkCloudOptions
961
964
  });
962
965
  } catch (err) {
963
- const classification = require_setup_surface.classifyMSTeamsSendError(err);
964
- const hint = require_setup_surface.formatMSTeamsSendErrorHint(classification);
966
+ const classification = require_channel_setup.classifyMSTeamsSendError(err);
967
+ const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
965
968
  const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
966
- throw new Error(`msteams send failed${status}: ${require_setup_surface.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
969
+ throw new Error(`msteams send failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
967
970
  }
968
971
  const messageId = platformMessageIds[0] ?? "unknown";
969
972
  log.info("sent proactive message", {
@@ -995,10 +998,10 @@ async function sendProactiveActivity({ ctx, activity, errorPrefix }) {
995
998
  activity
996
999
  });
997
1000
  } catch (err) {
998
- const classification = require_setup_surface.classifyMSTeamsSendError(err);
999
- const hint = require_setup_surface.formatMSTeamsSendErrorHint(classification);
1001
+ const classification = require_channel_setup.classifyMSTeamsSendError(err);
1002
+ const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
1000
1003
  const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
1001
- throw new Error(`${errorPrefix} failed${status}: ${require_setup_surface.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1004
+ throw new Error(`${errorPrefix} failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1002
1005
  }
1003
1006
  }
1004
1007
  /**
@@ -1102,10 +1105,10 @@ async function editMessageMSTeams(params) {
1102
1105
  text
1103
1106
  }, { serviceUrlBoundary: sdkCloudOptions });
1104
1107
  } catch (err) {
1105
- const classification = require_setup_surface.classifyMSTeamsSendError(err);
1106
- const hint = require_setup_surface.formatMSTeamsSendErrorHint(classification);
1108
+ const classification = require_channel_setup.classifyMSTeamsSendError(err);
1109
+ const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
1107
1110
  const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
1108
- throw new Error(`msteams edit failed${status}: ${require_setup_surface.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1111
+ throw new Error(`msteams edit failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1109
1112
  }
1110
1113
  log.info("edited proactive message", {
1111
1114
  conversationId,
@@ -1132,10 +1135,10 @@ async function deleteMessageMSTeams(params) {
1132
1135
  try {
1133
1136
  await require_messenger.deleteMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activityId, { serviceUrlBoundary: sdkCloudOptions });
1134
1137
  } catch (err) {
1135
- const classification = require_setup_surface.classifyMSTeamsSendError(err);
1136
- const hint = require_setup_surface.formatMSTeamsSendErrorHint(classification);
1138
+ const classification = require_channel_setup.classifyMSTeamsSendError(err);
1139
+ const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
1137
1140
  const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
1138
- throw new Error(`msteams delete failed${status}: ${require_setup_surface.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1141
+ throw new Error(`msteams delete failed${status}: ${require_channel_setup.formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
1139
1142
  }
1140
1143
  log.info("deleted proactive message", {
1141
1144
  conversationId,
@@ -1149,6 +1152,16 @@ const MSTEAMS_TEXT_CHUNK_LIMIT = 4e3;
1149
1152
  function resolveMSTeamsEffectiveTextChunkLimit(configuredLimit) {
1150
1153
  return typeof configuredLimit === "number" && configuredLimit > 0 ? Math.min(configuredLimit, MSTEAMS_TEXT_CHUNK_LIMIT) : MSTEAMS_TEXT_CHUNK_LIMIT;
1151
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
+ }
1152
1165
  function resolveMSTeamsThreadTarget(to, threadId) {
1153
1166
  const normalizedThreadId = threadId == null ? "" : String(threadId).trim();
1154
1167
  const graphChannelId = to.includes("/") ? to.slice(to.indexOf("/") + 1) : "";
@@ -1206,11 +1219,11 @@ const msteamsOutbound = {
1206
1219
  sendPayload: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, payload, deps, onDeliveryResult, threadId }) => {
1207
1220
  const deliveryTarget = resolveMSTeamsThreadTarget(to, threadId);
1208
1221
  const presentationCard = (0, openclaw_plugin_sdk_string_coerce_runtime.asOptionalRecord)(payload.channelData?.msteams)?.presentationCard;
1209
- 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({
1210
1223
  cfg,
1211
1224
  to: deliveryTarget,
1212
1225
  card: presentationCard
1213
- }));
1226
+ })));
1214
1227
  const mediaUrls = (0, openclaw_plugin_sdk_string_normalization_runtime.normalizeStringEntries)((0, openclaw_plugin_sdk_reply_payload.resolvePayloadMediaUrls)({
1215
1228
  ...payload,
1216
1229
  mediaUrl: payload.mediaUrl ?? mediaUrl
@@ -1224,7 +1237,7 @@ const msteamsOutbound = {
1224
1237
  text,
1225
1238
  mediaUrls,
1226
1239
  onResult: async (deliveryResult) => {
1227
- 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)));
1228
1241
  },
1229
1242
  send: async ({ text: textLocal, mediaUrl: mediaUrlLocal }) => await send(deliveryTarget, textLocal, {
1230
1243
  mediaUrl: mediaUrlLocal,
@@ -1233,7 +1246,7 @@ const msteamsOutbound = {
1233
1246
  mediaReadFile
1234
1247
  })
1235
1248
  });
1236
- 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));
1237
1250
  }
1238
1251
  if (text.trim()) {
1239
1252
  const send = resolveMSTeamsTextSend({
@@ -1244,22 +1257,22 @@ const msteamsOutbound = {
1244
1257
  let result;
1245
1258
  for (const chunk of chunks) {
1246
1259
  result = await send(deliveryTarget, chunk);
1247
- await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result));
1260
+ await onDeliveryResult?.((0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(result)));
1248
1261
  }
1249
- return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", result);
1262
+ return (0, openclaw_plugin_sdk_channel_send_result.attachChannelToResult)("msteams", toMSTeamsOutboundResult(result));
1250
1263
  }
1251
1264
  throw new Error("MS Teams payload send requires text, media, or a presentation card.");
1252
1265
  },
1253
1266
  ...(0, openclaw_plugin_sdk_channel_send_result.createAttachedChannelResultAdapter)({
1254
1267
  channel: "msteams",
1255
1268
  sendText: async ({ cfg, to, text, deps, threadId }) => {
1256
- return await resolveMSTeamsTextSend({
1269
+ return toMSTeamsOutboundResult(await resolveMSTeamsTextSend({
1257
1270
  cfg,
1258
1271
  deps
1259
- })(resolveMSTeamsThreadTarget(to, threadId), text);
1272
+ })(resolveMSTeamsThreadTarget(to, threadId), text));
1260
1273
  },
1261
1274
  sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, deps, threadId }) => {
1262
- return await resolveMSTeamsMediaSend({
1275
+ return toMSTeamsOutboundResult(await resolveMSTeamsMediaSend({
1263
1276
  cfg,
1264
1277
  deps
1265
1278
  })(resolveMSTeamsThreadTarget(to, threadId), text, {
@@ -1267,7 +1280,7 @@ const msteamsOutbound = {
1267
1280
  mediaAccess,
1268
1281
  mediaLocalRoots,
1269
1282
  mediaReadFile
1270
- });
1283
+ }));
1271
1284
  },
1272
1285
  sendPoll: async ({ cfg, to, poll, threadId }) => {
1273
1286
  const maxSelections = poll.maxSelections ?? 1;
@@ -1345,7 +1358,7 @@ async function probeMSTeams(cfg) {
1345
1358
  } catch (err) {
1346
1359
  graph = {
1347
1360
  ok: false,
1348
- error: require_setup_surface.formatUnknownError(err)
1361
+ error: require_channel_setup.formatUnknownError(err)
1349
1362
  };
1350
1363
  }
1351
1364
  let delegatedAuth;
@@ -1379,7 +1392,7 @@ async function probeMSTeams(cfg) {
1379
1392
  return {
1380
1393
  ok: false,
1381
1394
  appId: creds.appId,
1382
- error: require_setup_surface.formatUnknownError(err)
1395
+ error: require_channel_setup.formatUnknownError(err)
1383
1396
  };
1384
1397
  }
1385
1398
  }
@@ -1,9 +1,12 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
2
+ const require_config_schema = require("./config-schema-C4CszdDi.cjs");
2
3
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
3
- let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
4
4
  let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
5
+ let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
5
6
  let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
6
7
  let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
8
+ let openclaw_plugin_sdk_secret_file_runtime = require("openclaw/plugin-sdk/secret-file-runtime");
9
+ let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
7
10
  let openclaw_plugin_sdk_channel_setup = require("openclaw/plugin-sdk/channel-setup");
8
11
  let openclaw_plugin_sdk_setup = require("openclaw/plugin-sdk/setup");
9
12
  let openclaw_plugin_sdk_setup_tools = require("openclaw/plugin-sdk/setup-tools");
@@ -20,13 +23,23 @@ const msteamsMeta = {
20
23
  aliases: ["teams"],
21
24
  order: 60
22
25
  };
26
+ function resolveMSTeamsAccount(cfg) {
27
+ const config = cfg.channels?.msteams;
28
+ const credentials = require_resolve_allowlist.resolveMSTeamsCredentials(config);
29
+ const certificatePath = credentials?.type === "federated" && !credentials.useManagedIdentity ? credentials.certificatePath : void 0;
30
+ const certificate = certificatePath ? (0, openclaw_plugin_sdk_secret_file_runtime.tryReadSecretFileSync)(certificatePath, "Microsoft Teams certificate", void 0, { configPath: config?.certificatePath?.trim() ? "channels.msteams.certificatePath" : "env.MSTEAMS_CERTIFICATE_PATH" }) : void 0;
31
+ const unavailable = certificate?.status === "configured_unavailable";
32
+ return {
33
+ accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
34
+ enabled: config?.enabled !== false,
35
+ configured: Boolean(credentials),
36
+ tokenStatus: !credentials ? "missing" : unavailable ? "configured_unavailable" : "available",
37
+ ...unavailable ? { credentialDiagnostics: [certificate.diagnostic] } : {}
38
+ };
39
+ }
23
40
  const msteamsConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createTopLevelChannelConfigAdapter)({
24
41
  sectionKey: "msteams",
25
- resolveAccount: (cfg) => ({
26
- accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
27
- enabled: cfg.channels?.msteams?.enabled !== false,
28
- configured: Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams))
29
- }),
42
+ resolveAccount: resolveMSTeamsAccount,
30
43
  resolveAccessorAccount: ({ cfg }) => ({
31
44
  allowFrom: cfg.channels?.msteams?.allowFrom,
32
45
  defaultTo: cfg.channels?.msteams?.defaultTo
@@ -220,12 +233,8 @@ function parseNonNegativeRetryAfterSeconds(raw) {
220
233
  });
221
234
  }
222
235
  /**
223
- * Classify outbound send errors for safe retries and actionable logs.
224
- *
225
- * Important: We only mark errors as retryable when we have an explicit HTTP
226
- * status code that indicates the message was not accepted (e.g. 429, 5xx).
227
- * For transport-level errors where delivery is ambiguous, we prefer to avoid
228
- * retries to reduce the chance of duplicate posts.
236
+ * Owns retry safety and delivery ambiguity for Teams send failures.
237
+ * Only Teams rate-limit rejection proves this unkeyed POST safe to replay.
229
238
  */
230
239
  function classifyMSTeamsSendError(err) {
231
240
  const statusCode = extractStatusCode(err);
@@ -249,15 +258,15 @@ function classifyMSTeamsSendError(err) {
249
258
  };
250
259
  }
251
260
  if (statusCode === 429) return {
252
- kind: "throttled",
261
+ kind: "replay-safe",
253
262
  statusCode,
254
263
  retryAfterMs: retryAfterMs ?? void 0,
255
264
  errorCode
256
265
  };
257
266
  if (statusCode === 408 || statusCode != null && statusCode >= 500) return {
258
- kind: "transient",
267
+ kind: "ambiguous",
268
+ source: "http",
259
269
  statusCode,
260
- retryAfterMs: retryAfterMs ?? void 0,
261
270
  errorCode
262
271
  };
263
272
  if (statusCode != null && statusCode >= 400) return {
@@ -265,17 +274,14 @@ function classifyMSTeamsSendError(err) {
265
274
  statusCode,
266
275
  errorCode
267
276
  };
268
- if (statusCode == null) {
269
- const networkCode = (0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(err) && typeof err.code === "string" ? err.code : null;
270
- if (networkCode === "ECONNREFUSED" || networkCode === "ENOTFOUND" || networkCode === "EHOSTUNREACH" || networkCode === "ETIMEDOUT" || networkCode === "ECONNRESET") return {
271
- kind: "network",
272
- errorCode: networkCode
273
- };
274
- }
277
+ if (statusCode == null && (0, openclaw_plugin_sdk_retry_runtime.isTransientNetworkError)(err)) return {
278
+ kind: "ambiguous",
279
+ source: "transport",
280
+ errorCode
281
+ };
275
282
  return {
276
283
  kind: "unknown",
277
284
  statusCode: statusCode ?? void 0,
278
- retryAfterMs: retryAfterMs ?? void 0,
279
285
  errorCode
280
286
  };
281
287
  }
@@ -294,9 +300,15 @@ function isRevokedProxyError(err) {
294
300
  function formatMSTeamsSendErrorHint(classification) {
295
301
  if (classification.kind === "auth") return "check msteams appId/appPassword/tenantId (or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID)";
296
302
  if (classification.errorCode === "ContentStreamNotAllowed") return "Teams expired the content stream; stop streaming earlier and fall back to normal message delivery";
297
- if (classification.kind === "throttled") return "Teams throttled the bot; backing off may help";
298
- if (classification.kind === "transient") return "transient Teams/Bot Framework error; retry may succeed";
299
- if (classification.kind === "network") return "transport-level failure sending reply to Teams Bot Connector (smba.trafficmanager.net) — check egress firewall rules allow outbound HTTPS to smba.trafficmanager.net";
303
+ if (classification.kind === "replay-safe") return "Teams throttled the bot; backing off may help";
304
+ if (classification.kind === "ambiguous") {
305
+ if (classification.source === "transport") return "transport-level failure sending to Teams Bot Connector (smba.trafficmanager.net); the outcome is unknown, so check egress and conversation history before taking further action";
306
+ return "Teams/Bot Framework delivery outcome is unknown; inspect the conversation history before taking further action";
307
+ }
308
+ }
309
+ function formatMSTeamsDeliveryFailureGuidance(classification) {
310
+ if (classification.kind === "replay-safe") return "The request was rate-limited before delivery; retrying later may succeed.";
311
+ if (classification.kind === "ambiguous") return "Delivery may already have succeeded; do not send the same content again without checking the conversation.";
300
312
  }
301
313
  //#endregion
302
314
  //#region extensions/msteams/src/setup-surface.ts
@@ -466,7 +478,7 @@ const msteamsSetupWizard = {
466
478
  };
467
479
  let oauthModule;
468
480
  try {
469
- oauthModule = await Promise.resolve().then(() => require("./oauth-DktsbN22.cjs"));
481
+ oauthModule = await Promise.resolve().then(() => require("./oauth-C9So7uld.cjs"));
470
482
  } catch (err) {
471
483
  await noteDelegatedAuthFailure(err);
472
484
  return {
@@ -520,6 +532,40 @@ const msteamsSetupWizard = {
520
532
  disable: (cfg) => (0, openclaw_plugin_sdk_setup.setSetupChannelEnabled)(cfg, channel, false)
521
533
  };
522
534
  //#endregion
535
+ //#region extensions/msteams/src/channel.setup.ts
536
+ const msteamsSetupPlugin = {
537
+ id: "msteams",
538
+ meta: {
539
+ ...msteamsMeta,
540
+ aliases: [...msteamsMeta.aliases]
541
+ },
542
+ capabilities: {
543
+ chatTypes: [
544
+ "direct",
545
+ "channel",
546
+ "group",
547
+ "thread"
548
+ ],
549
+ polls: true,
550
+ threads: true,
551
+ media: true,
552
+ reactions: true
553
+ },
554
+ reload: { configPrefixes: ["channels.msteams"] },
555
+ configSchema: require_config_schema.MSTeamsChannelConfigSchema,
556
+ config: {
557
+ ...msteamsConfigAdapter,
558
+ isConfigured: (account) => account.configured,
559
+ describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
560
+ account,
561
+ configured: account.configured,
562
+ extra: { tokenStatus: account.tokenStatus }
563
+ })
564
+ },
565
+ setupWizard: msteamsSetupWizard,
566
+ setupContract: msteamsSetupContract
567
+ };
568
+ //#endregion
523
569
  Object.defineProperty(exports, "classifyMSTeamsSendError", {
524
570
  enumerable: true,
525
571
  get: function() {
@@ -532,6 +578,12 @@ Object.defineProperty(exports, "createMSTeamsSetupWizardBase", {
532
578
  return createMSTeamsSetupWizardBase;
533
579
  }
534
580
  });
581
+ Object.defineProperty(exports, "formatMSTeamsDeliveryFailureGuidance", {
582
+ enumerable: true,
583
+ get: function() {
584
+ return formatMSTeamsDeliveryFailureGuidance;
585
+ }
586
+ });
535
587
  Object.defineProperty(exports, "formatMSTeamsSendErrorHint", {
536
588
  enumerable: true,
537
589
  get: function() {
@@ -550,28 +602,16 @@ Object.defineProperty(exports, "isRevokedProxyError", {
550
602
  return isRevokedProxyError;
551
603
  }
552
604
  });
553
- Object.defineProperty(exports, "msteamsConfigAdapter", {
554
- enumerable: true,
555
- get: function() {
556
- return msteamsConfigAdapter;
557
- }
558
- });
559
- Object.defineProperty(exports, "msteamsMeta", {
560
- enumerable: true,
561
- get: function() {
562
- return msteamsMeta;
563
- }
564
- });
565
605
  Object.defineProperty(exports, "msteamsSetupAdapter", {
566
606
  enumerable: true,
567
607
  get: function() {
568
608
  return msteamsSetupAdapter;
569
609
  }
570
610
  });
571
- Object.defineProperty(exports, "msteamsSetupContract", {
611
+ Object.defineProperty(exports, "msteamsSetupPlugin", {
572
612
  enumerable: true,
573
613
  get: function() {
574
- return msteamsSetupContract;
614
+ return msteamsSetupPlugin;
575
615
  }
576
616
  });
577
617
  Object.defineProperty(exports, "msteamsSetupWizard", {
@@ -586,3 +626,9 @@ Object.defineProperty(exports, "openDelegatedOAuthUrl", {
586
626
  return openDelegatedOAuthUrl;
587
627
  }
588
628
  });
629
+ Object.defineProperty(exports, "resolveMSTeamsAccount", {
630
+ enumerable: true,
631
+ get: function() {
632
+ return resolveMSTeamsAccount;
633
+ }
634
+ });
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./resolve-allowlist-C6YcNC9a.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
3
3
  let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
4
4
  const msteamsDirectoryContractPlugin = {
5
5
  id: "msteams",