@openclaw/msteams 2026.7.1 → 2026.7.2-beta.1

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 (35) hide show
  1. package/dist/api.cjs +8 -0
  2. package/dist/{channel-Cf5LJ4aO.js → channel-BSyPdpGN.cjs} +641 -227
  3. package/dist/channel-config-api.cjs +3 -0
  4. package/dist/channel-plugin-api.cjs +3 -0
  5. package/dist/channel.runtime-DQTOzzet.cjs +1372 -0
  6. package/dist/{config-schema-BL4qQZiA.js → config-schema-BSNLJUta.cjs} +13 -3
  7. package/dist/{directory-contract-api.js → directory-contract-api.cjs} +8 -7
  8. package/dist/{doctor-contract-api.js → doctor-contract-api.cjs} +73 -57
  9. package/dist/index.cjs +21 -0
  10. package/dist/{probe-BnyZRZsD.js → messenger-DtS9gqkV.cjs} +369 -861
  11. package/dist/{oauth-BifWxWzq.js → oauth-C5E5powI.cjs} +21 -21
  12. package/dist/{polls-B_hs4aKm.js → polls-BhoI4VaN.cjs} +188 -38
  13. package/dist/{resolve-allowlist-Dnw4aNOu.js → resolve-allowlist-CyQ57MfH.cjs} +817 -140
  14. package/dist/rolldown-runtime-D6vf50IK.cjs +28 -0
  15. package/dist/runtime-api.cjs +207 -0
  16. package/dist/runtime-gZTAuFux.cjs +24 -0
  17. package/dist/secret-contract-api.cjs +31 -0
  18. package/dist/setup-entry.cjs +14 -0
  19. package/dist/setup-plugin-api.cjs +65 -0
  20. package/dist/{setup-surface-qW-ECHL-.js → setup-surface-BDTPN3dX.cjs} +123 -49
  21. package/dist/{src-DZFs5XtZ.js → src-CUMz2B6f.cjs} +672 -740
  22. package/dist/{sso-token-store-DrVbnCUF.js → sso-token-store-CktCz88k.cjs} +51 -10
  23. package/npm-shrinkwrap.json +3 -3
  24. package/openclaw.plugin.json +10 -31
  25. package/package.json +8 -7
  26. package/dist/api.js +0 -3
  27. package/dist/channel-config-api.js +0 -2
  28. package/dist/channel-plugin-api.js +0 -2
  29. package/dist/channel.runtime-Bwu6Tjhf.js +0 -664
  30. package/dist/index.js +0 -22
  31. package/dist/runtime-BS5AZrKK.js +0 -8
  32. package/dist/runtime-api.js +0 -20
  33. package/dist/secret-contract-api.js +0 -35
  34. package/dist/setup-entry.js +0 -15
  35. package/dist/setup-plugin-api.js +0 -64
@@ -1,50 +1,58 @@
1
- import { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelKeyCandidates, buildProbeChannelStatusSummary, chunkTextForOutbound, createDefaultChannelRuntimeState, isDangerousNameMatchingEnabled, normalizeChannelSlug, resolveAllowlistMatchSimple, resolveChannelEntryMatchWithFallback, resolveNestedAllowlistDecision, resolveToolsBySender } from "./runtime-api.js";
2
- import { C as resolveMSTeamsCredentials, a as parseMSTeamsTeamChannelInput, c as resolveMSTeamsUserAllowlist, i as parseMSTeamsConversationId, n as normalizeMSTeamsMessagingTarget, r as normalizeMSTeamsUserInput, s as resolveMSTeamsChannelAllowlist, t as looksLikeMSTeamsTargetId } from "./resolve-allowlist-Dnw4aNOu.js";
3
- import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
4
- import { c as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-qW-ECHL-.js";
5
- import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
6
- import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
7
- import { createTopLevelChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
8
- import { buildChannelOutboundSessionRoute, createChatChannelPlugin, stripChannelTargetPrefix, stripTargetKindPrefix } from "openclaw/plugin-sdk/channel-core";
9
- import { createChannelMessageAdapterFromOutbound, createRuntimeOutboundDelegates } from "openclaw/plugin-sdk/channel-outbound";
10
- import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
11
- import { createAllowlistProviderGroupPolicyWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, projectConfigWarningCollector } from "openclaw/plugin-sdk/channel-policy";
12
- import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, listDirectoryEntriesFromSources } from "openclaw/plugin-sdk/directory-runtime";
13
- import { adaptMessagePresentationForChannel, normalizeMessagePresentation, resolveMessagePresentationControlValue } from "openclaw/plugin-sdk/interactive-runtime";
14
- import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
15
- import { createComputedAccountStatusAdapter } from "openclaw/plugin-sdk/status-helpers";
16
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
17
- import { Type } from "typebox";
18
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
19
- import { resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
1
+ require("./runtime-api.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-CyQ57MfH.cjs");
3
+ const require_config_schema = require("./config-schema-BSNLJUta.cjs");
4
+ const require_setup_surface = require("./setup-surface-BDTPN3dX.cjs");
5
+ let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
6
+ let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
7
+ let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
8
+ let openclaw_plugin_sdk_channel_core = require("openclaw/plugin-sdk/channel-core");
9
+ let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
10
+ let openclaw_plugin_sdk_channel_pairing = require("openclaw/plugin-sdk/channel-pairing");
11
+ let openclaw_plugin_sdk_channel_policy = require("openclaw/plugin-sdk/channel-policy");
12
+ let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
13
+ let openclaw_plugin_sdk_interactive_runtime = require("openclaw/plugin-sdk/interactive-runtime");
14
+ let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
15
+ let openclaw_plugin_sdk_status_helpers = require("openclaw/plugin-sdk/status-helpers");
16
+ let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
17
+ let typebox = require("typebox");
18
+ let openclaw_plugin_sdk_approval_auth_runtime = require("openclaw/plugin-sdk/approval-auth-runtime");
19
+ let openclaw_plugin_sdk_channel_actions = require("openclaw/plugin-sdk/channel-actions");
20
+ let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
21
+ let openclaw_plugin_sdk_routing = require("openclaw/plugin-sdk/routing");
22
+ let openclaw_plugin_sdk_channel_targets = require("openclaw/plugin-sdk/channel-targets");
23
+ let openclaw_plugin_sdk_dangerous_name_runtime = require("openclaw/plugin-sdk/dangerous-name-runtime");
24
+ let openclaw_plugin_sdk_runtime_group_policy = require("openclaw/plugin-sdk/runtime-group-policy");
25
+ let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
26
+ let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunking");
27
+ let openclaw_plugin_sdk_channel_status = require("openclaw/plugin-sdk/channel-status");
20
28
  //#region extensions/msteams/src/approval-auth.ts
21
29
  const MSTEAMS_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22
30
  function normalizeMSTeamsApproverId(value) {
23
- const normalized = normalizeMSTeamsMessagingTarget(String(value));
31
+ const normalized = require_resolve_allowlist.normalizeMSTeamsMessagingTarget(String(value));
24
32
  if (!normalized?.startsWith("user:")) return;
25
- const id = normalizeOptionalLowercaseString(normalized.slice(5));
33
+ const id = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalLowercaseString)(normalized.slice(5));
26
34
  if (!id) return;
27
35
  return MSTEAMS_ID_RE.test(id) ? id : void 0;
28
36
  }
29
37
  function resolveMSTeamsChannelConfig$1(cfg) {
30
38
  return cfg.channels?.msteams;
31
39
  }
32
- const msTeamsApprovalAuth = createResolvedApproverActionAuthAdapter({
40
+ const msTeamsApprovalAuth = (0, openclaw_plugin_sdk_approval_auth_runtime.createChannelApprovalAuth)({
33
41
  channelLabel: "Microsoft Teams",
34
- resolveApprovers: ({ cfg }) => {
42
+ resolveInputs: ({ cfg }) => {
35
43
  const channel = resolveMSTeamsChannelConfig$1(cfg);
36
- return resolveApprovalApprovers({
44
+ return {
37
45
  allowFrom: channel?.allowFrom,
38
- defaultTo: channel?.defaultTo,
39
- normalizeApprover: normalizeMSTeamsApproverId
40
- });
46
+ defaultTo: channel?.defaultTo
47
+ };
41
48
  },
49
+ normalizeApprover: normalizeMSTeamsApproverId,
42
50
  normalizeSenderId: (value) => {
43
- const trimmed = normalizeOptionalLowercaseString(value);
51
+ const trimmed = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalLowercaseString)(value);
44
52
  if (!trimmed) return;
45
53
  return MSTEAMS_ID_RE.test(trimmed) ? trimmed : void 0;
46
54
  }
47
- });
55
+ }).approvalAuth;
48
56
  //#endregion
49
57
  //#region extensions/msteams/src/doctor.ts
50
58
  function isMSTeamsMutableAllowEntry(raw) {
@@ -53,7 +61,7 @@ function isMSTeamsMutableAllowEntry(raw) {
53
61
  const withoutPrefix = text.replace(/^(msteams|user):/i, "").trim();
54
62
  return /\s/.test(withoutPrefix) || withoutPrefix.includes("@");
55
63
  }
56
- const collectMSTeamsMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
64
+ const collectMSTeamsMutableAllowlistWarnings = (0, openclaw_plugin_sdk_channel_policy.createDangerousNameMatchingMutableAllowlistWarningCollector)({
57
65
  channel: "msteams",
58
66
  detector: isMSTeamsMutableAllowEntry,
59
67
  collectLists: (scope) => [{
@@ -66,6 +74,78 @@ const collectMSTeamsMutableAllowlistWarnings = createDangerousNameMatchingMutabl
66
74
  });
67
75
  //#endregion
68
76
  //#region extensions/msteams/src/policy.ts
77
+ const encodeScopeSegment = (value) => `${value.length}:${value}`;
78
+ const teamScopeKey = (teamKey) => `team:${encodeScopeSegment(teamKey)}`;
79
+ const channelScopeKey = (teamKey, channelKey) => `${teamScopeKey(teamKey)}/channel:${encodeScopeSegment(channelKey)}`;
80
+ function buildMSTeamsToolPolicyTree(teams) {
81
+ const scopes = {};
82
+ for (const [teamKey, team] of Object.entries(teams ?? {})) {
83
+ scopes[teamScopeKey(teamKey)] = {
84
+ tools: team.tools,
85
+ toolsBySender: team.toolsBySender
86
+ };
87
+ for (const [channelKey, channel] of Object.entries(team.channels ?? {})) scopes[channelScopeKey(teamKey, channelKey)] = {
88
+ tools: channel.tools,
89
+ toolsBySender: channel.toolsBySender
90
+ };
91
+ }
92
+ return { scopes };
93
+ }
94
+ function resolveMSTeamsToolPolicyScope(params) {
95
+ const teams = params.cfg.teams ?? {};
96
+ const tree = buildMSTeamsToolPolicyTree(teams);
97
+ const teamMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
98
+ entries: teams,
99
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(params.groupSpace?.trim()),
100
+ wildcardKey: "*",
101
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
102
+ });
103
+ const matchedTeamKey = teamMatch.matchKey ?? teamMatch.key;
104
+ if (teamMatch.entry && matchedTeamKey) {
105
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
106
+ entries: teamMatch.entry.channels ?? {},
107
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(params.groupId?.trim()),
108
+ wildcardKey: "*",
109
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
110
+ });
111
+ const matchedChannelKey = channelMatch.matchKey ?? channelMatch.key;
112
+ return {
113
+ tree,
114
+ path: [teamScopeKey(matchedTeamKey), ...channelMatch.entry && matchedChannelKey ? [channelScopeKey(matchedTeamKey, matchedChannelKey)] : []]
115
+ };
116
+ }
117
+ return {
118
+ tree,
119
+ path: []
120
+ };
121
+ }
122
+ function resolveMSTeamsCrossTeamScanScope(params) {
123
+ const teams = params.cfg.teams ?? {};
124
+ const tree = buildMSTeamsToolPolicyTree(teams);
125
+ const groupId = params.groupId?.trim();
126
+ if (!groupId) return {
127
+ tree,
128
+ path: []
129
+ };
130
+ const channelCandidates = (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(groupId);
131
+ for (const [teamKey, team] of Object.entries(teams)) {
132
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
133
+ entries: team.channels ?? {},
134
+ keys: channelCandidates,
135
+ wildcardKey: "*",
136
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
137
+ });
138
+ const matchedChannelKey = channelMatch.matchKey ?? channelMatch.key;
139
+ if (channelMatch.entry && matchedChannelKey) return {
140
+ tree,
141
+ path: [teamScopeKey(teamKey), channelScopeKey(teamKey, matchedChannelKey)]
142
+ };
143
+ }
144
+ return {
145
+ tree,
146
+ path: []
147
+ };
148
+ }
69
149
  function resolveMSTeamsRouteConfig(params) {
70
150
  const teamId = params.teamId?.trim();
71
151
  const teamName = params.teamName?.trim();
@@ -73,27 +153,27 @@ function resolveMSTeamsRouteConfig(params) {
73
153
  const channelName = params.channelName?.trim();
74
154
  const teams = params.cfg?.teams ?? {};
75
155
  const allowlistConfigured = Object.keys(teams).length > 0;
76
- const teamMatch = resolveChannelEntryMatchWithFallback({
156
+ const teamMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
77
157
  entries: teams,
78
- keys: buildChannelKeyCandidates(teamId, params.allowNameMatching ? teamName : void 0, params.allowNameMatching && teamName ? normalizeChannelSlug(teamName) : void 0),
158
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(teamId, params.allowNameMatching ? teamName : void 0, params.allowNameMatching && teamName ? (0, openclaw_plugin_sdk_channel_targets.normalizeChannelSlug)(teamName) : void 0),
79
159
  wildcardKey: "*",
80
- normalizeKey: normalizeChannelSlug
160
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
81
161
  });
82
162
  const teamConfig = teamMatch.entry;
83
163
  const channels = teamConfig?.channels ?? {};
84
164
  const channelAllowlistConfigured = Object.keys(channels).length > 0;
85
- const channelMatch = resolveChannelEntryMatchWithFallback({
165
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
86
166
  entries: channels,
87
- keys: buildChannelKeyCandidates(conversationId, params.allowNameMatching ? channelName : void 0, params.allowNameMatching && channelName ? normalizeChannelSlug(channelName) : void 0),
167
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(conversationId, params.allowNameMatching ? channelName : void 0, params.allowNameMatching && channelName ? (0, openclaw_plugin_sdk_channel_targets.normalizeChannelSlug)(channelName) : void 0),
88
168
  wildcardKey: "*",
89
- normalizeKey: normalizeChannelSlug
169
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
90
170
  });
91
171
  const channelConfig = channelMatch.entry;
92
172
  return {
93
173
  teamConfig,
94
174
  channelConfig,
95
175
  allowlistConfigured,
96
- allowed: resolveNestedAllowlistDecision({
176
+ allowed: (0, openclaw_plugin_sdk_channel_targets.resolveNestedAllowlistDecision)({
97
177
  outerConfigured: allowlistConfigured,
98
178
  outerMatched: Boolean(teamConfig),
99
179
  innerConfigured: channelAllowlistConfigured,
@@ -108,82 +188,33 @@ function resolveMSTeamsRouteConfig(params) {
108
188
  function resolveMSTeamsGroupToolPolicy(params) {
109
189
  const cfg = params.cfg.channels?.msteams;
110
190
  if (!cfg) return;
111
- const groupId = params.groupId?.trim();
112
- const groupChannel = params.groupChannel?.trim();
113
- const groupSpace = params.groupSpace?.trim();
114
- const allowNameMatching = isDangerousNameMatchingEnabled(cfg);
115
- const resolved = resolveMSTeamsRouteConfig({
191
+ const scope = resolveMSTeamsToolPolicyScope({
116
192
  cfg,
117
- teamId: groupSpace,
118
- teamName: groupSpace,
119
- conversationId: groupId,
120
- channelName: groupChannel,
121
- allowNameMatching
193
+ groupSpace: params.groupSpace,
194
+ groupId: params.groupId
195
+ });
196
+ const senderScope = {
197
+ senderId: params.senderId,
198
+ senderName: params.senderName,
199
+ senderUsername: params.senderUsername,
200
+ senderE164: params.senderE164
201
+ };
202
+ const resolved = (0, openclaw_plugin_sdk_channel_policy.resolveScopeToolsPolicy)({
203
+ ...scope,
204
+ ...senderScope
205
+ });
206
+ if (resolved !== void 0) return resolved;
207
+ if (scope.path.length > 1) return;
208
+ return (0, openclaw_plugin_sdk_channel_policy.resolveScopeToolsPolicy)({
209
+ ...resolveMSTeamsCrossTeamScanScope({
210
+ cfg,
211
+ groupId: params.groupId
212
+ }),
213
+ ...senderScope
122
214
  });
123
- if (resolved.channelConfig) {
124
- const senderPolicy = resolveToolsBySender({
125
- toolsBySender: resolved.channelConfig.toolsBySender,
126
- senderId: params.senderId,
127
- senderName: params.senderName,
128
- senderUsername: params.senderUsername,
129
- senderE164: params.senderE164
130
- });
131
- if (senderPolicy) return senderPolicy;
132
- if (resolved.channelConfig.tools) return resolved.channelConfig.tools;
133
- const teamSenderPolicy = resolveToolsBySender({
134
- toolsBySender: resolved.teamConfig?.toolsBySender,
135
- senderId: params.senderId,
136
- senderName: params.senderName,
137
- senderUsername: params.senderUsername,
138
- senderE164: params.senderE164
139
- });
140
- if (teamSenderPolicy) return teamSenderPolicy;
141
- return resolved.teamConfig?.tools;
142
- }
143
- if (resolved.teamConfig) {
144
- const teamSenderPolicy = resolveToolsBySender({
145
- toolsBySender: resolved.teamConfig.toolsBySender,
146
- senderId: params.senderId,
147
- senderName: params.senderName,
148
- senderUsername: params.senderUsername,
149
- senderE164: params.senderE164
150
- });
151
- if (teamSenderPolicy) return teamSenderPolicy;
152
- if (resolved.teamConfig.tools) return resolved.teamConfig.tools;
153
- }
154
- if (!groupId) return;
155
- const channelCandidates = buildChannelKeyCandidates(groupId, allowNameMatching ? groupChannel : void 0, allowNameMatching && groupChannel ? normalizeChannelSlug(groupChannel) : void 0);
156
- for (const teamConfig of Object.values(cfg.teams ?? {})) {
157
- const match = resolveChannelEntryMatchWithFallback({
158
- entries: teamConfig?.channels ?? {},
159
- keys: channelCandidates,
160
- wildcardKey: "*",
161
- normalizeKey: normalizeChannelSlug
162
- });
163
- if (match.entry) {
164
- const senderPolicy = resolveToolsBySender({
165
- toolsBySender: match.entry.toolsBySender,
166
- senderId: params.senderId,
167
- senderName: params.senderName,
168
- senderUsername: params.senderUsername,
169
- senderE164: params.senderE164
170
- });
171
- if (senderPolicy) return senderPolicy;
172
- if (match.entry.tools) return match.entry.tools;
173
- const teamSenderPolicy = resolveToolsBySender({
174
- toolsBySender: teamConfig?.toolsBySender,
175
- senderId: params.senderId,
176
- senderName: params.senderName,
177
- senderUsername: params.senderUsername,
178
- senderE164: params.senderE164
179
- });
180
- if (teamSenderPolicy) return teamSenderPolicy;
181
- return teamConfig?.tools;
182
- }
183
- }
184
215
  }
185
216
  function resolveMSTeamsAllowlistMatch(params) {
186
- return resolveAllowlistMatchSimple(params);
217
+ return (0, openclaw_plugin_sdk_allow_from.resolveAllowlistMatchSimple)(params);
187
218
  }
188
219
  function resolveMSTeamsReplyPolicy(params) {
189
220
  if (params.isDirectMessage) return {
@@ -214,13 +245,13 @@ const MSTEAMS_PRESENTATION_CAPABILITIES = {
214
245
  };
215
246
  function buildMSTeamsPresentationCard(params) {
216
247
  const body = [];
217
- const text = normalizeOptionalString(params.text);
248
+ const text = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.text);
218
249
  if (text) body.push({
219
250
  type: "TextBlock",
220
251
  text,
221
252
  wrap: true
222
253
  });
223
- const presentation = adaptMessagePresentationForChannel({
254
+ const presentation = (0, openclaw_plugin_sdk_interactive_runtime.adaptMessagePresentationForChannel)({
224
255
  presentation: params.presentation,
225
256
  capabilities: MSTEAMS_PRESENTATION_CAPABILITIES
226
257
  });
@@ -255,21 +286,28 @@ function buildMSTeamsPresentationCard(params) {
255
286
  continue;
256
287
  }
257
288
  if (block.type === "buttons") for (const button of block.buttons) {
258
- const targetUrl = button.url ?? button.webApp?.url ?? button.web_app?.url;
259
- if (targetUrl) {
289
+ const action = (0, openclaw_plugin_sdk_interactive_runtime.resolveMessagePresentationButtonAction)(button);
290
+ if (action?.type === "url" || action?.type === "web-app") {
260
291
  actions.push({
261
292
  type: "Action.OpenUrl",
262
293
  title: button.label,
263
- url: targetUrl
294
+ url: action.url
264
295
  });
265
296
  continue;
266
297
  }
267
- const value = resolveMessagePresentationControlValue(button);
268
- if (value) actions.push({
298
+ if (action?.type === "command") {
299
+ actions.push({
300
+ type: "Action.Submit",
301
+ title: button.label,
302
+ data: action.command
303
+ });
304
+ continue;
305
+ }
306
+ if (action?.type === "callback") actions.push({
269
307
  type: "Action.Submit",
270
308
  title: button.label,
271
- data: button.action?.type === "command" ? value : {
272
- value,
309
+ data: {
310
+ value: action.value,
273
311
  label: button.label
274
312
  }
275
313
  });
@@ -283,18 +321,231 @@ function buildMSTeamsPresentationCard(params) {
283
321
  };
284
322
  }
285
323
  //#endregion
286
- //#region extensions/msteams/src/inbound.ts
287
- /**
288
- * Decode common HTML entities to plain text.
289
- */
290
- function decodeHtmlEntities(html) {
291
- return html.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&#39;/g, "'").replace(/&#x27;/g, "'").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&");
324
+ //#region extensions/msteams/src/read-policy.ts
325
+ function normalizeTarget(raw) {
326
+ return raw ? require_resolve_allowlist.normalizeMSTeamsMessagingTarget(raw) ?? "" : "";
327
+ }
328
+ function sameAccount(ctx) {
329
+ const requested = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.accountId) ?? "default";
330
+ const requester = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.requesterAccountId);
331
+ return requester !== void 0 && requester === requested;
332
+ }
333
+ function isCurrentMSTeamsReadTarget(params) {
334
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.ctx.toolContext?.currentChannelProvider)?.toLowerCase() !== "msteams" || !sameAccount(params.ctx)) return false;
335
+ const candidates = [
336
+ params.ctx.toolContext?.currentChannelId,
337
+ params.ctx.toolContext?.currentMessagingTarget,
338
+ params.ctx.toolContext?.currentGraphChannelId
339
+ ];
340
+ const target = normalizeTarget(params.target);
341
+ return candidates.some((candidate) => normalizeTarget(candidate) === target);
342
+ }
343
+ function normalizeUserTarget(target) {
344
+ return target.replace(/^user:/i, "").trim().toLowerCase();
345
+ }
346
+ function isStableUserId(value) {
347
+ return /^[0-9a-f-]{16,}$/i.test(value);
348
+ }
349
+ async function resolveAllowedDmTarget(cfg, target) {
350
+ const teams = cfg.channels?.msteams;
351
+ if (teams?.dmPolicy === "disabled") return;
352
+ const userId = normalizeUserTarget(target);
353
+ if (!userId) return;
354
+ const normalizedEntries = (teams?.allowFrom ?? []).map((entry) => normalizeUserTarget(entry.replace(/^(msteams|teams):/i, "")));
355
+ const allowAll = (teams?.dmPolicy ?? "pairing") === "open" || normalizedEntries.includes("*");
356
+ if (isStableUserId(userId)) return allowAll || normalizedEntries.some((entry) => entry === userId) ? `user:${userId}` : void 0;
357
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)) return;
358
+ try {
359
+ const [resolvedTarget, ...resolvedEntries] = await require_resolve_allowlist.resolveMSTeamsUserAllowlist({
360
+ cfg,
361
+ entries: [userId, ...normalizedEntries.filter((entry) => entry !== "*")]
362
+ });
363
+ if (!resolvedTarget?.resolved || !resolvedTarget.id) return;
364
+ return allowAll || resolvedEntries.some((entry) => entry.resolved && entry.id?.toLowerCase() === resolvedTarget.id?.toLowerCase()) ? `user:${resolvedTarget.id}` : void 0;
365
+ } catch {
366
+ return;
367
+ }
368
+ }
369
+ async function resolveDirectDmTarget(cfg, target) {
370
+ if (cfg.channels?.msteams?.dmPolicy === "disabled") return;
371
+ const userId = normalizeUserTarget(target);
372
+ if (!userId) return;
373
+ if (isStableUserId(userId)) return `user:${userId}`;
374
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(cfg.channels?.msteams)) return;
375
+ try {
376
+ const [resolved] = await require_resolve_allowlist.resolveMSTeamsUserAllowlist({
377
+ cfg,
378
+ entries: [userId]
379
+ });
380
+ return resolved?.resolved && resolved.id ? `user:${resolved.id}` : void 0;
381
+ } catch {
382
+ return;
383
+ }
384
+ }
385
+ function resolveMSTeamsReadGroupPolicy(cfg) {
386
+ const teams = cfg.channels?.msteams;
387
+ return teams ? teams.groupPolicy ?? (0, openclaw_plugin_sdk_runtime_group_policy.resolveDefaultGroupPolicy)(cfg) ?? "allowlist" : "disabled";
388
+ }
389
+ function isStableChannelKey(value) {
390
+ return /^[0-9a-f-]{16,}$/i.test(value) || /^19:.+@thread\./i.test(value);
391
+ }
392
+ function isStableGraphTeamId(value) {
393
+ return /^[0-9a-f-]{16,}$/i.test(value);
394
+ }
395
+ function isStableGraphChannelTarget(target) {
396
+ const [teamId, channelId] = target.split("/", 2);
397
+ return Boolean(teamId && channelId && isStableGraphTeamId(teamId) && isStableChannelKey(channelId));
398
+ }
399
+ function hasMutableChannelConfig(cfg) {
400
+ const teams = cfg.channels?.msteams?.teams ?? {};
401
+ return Object.entries(teams).some(([teamKey, teamConfig]) => {
402
+ if (teamKey !== "*" && !isStableChannelKey(teamKey)) return true;
403
+ return Object.keys(teamConfig?.channels ?? {}).some((channelKey) => channelKey !== "*" && !isStableChannelKey(channelKey));
404
+ });
405
+ }
406
+ async function resolveConfiguredBotFrameworkTeamKey(cfg, graphTeamId) {
407
+ const configuredTeams = cfg.channels?.msteams?.teams;
408
+ if (!configuredTeams) return;
409
+ const stableConfiguredKeys = Object.keys(configuredTeams).filter((teamKey) => teamKey !== "*" && /^19:.+@thread\./i.test(teamKey));
410
+ if (stableConfiguredKeys.length === 0) return;
411
+ const channelResult = await require_resolve_allowlist.listChannelsForTeamWithPageInfo(await require_resolve_allowlist.resolveGraphToken(cfg), graphTeamId);
412
+ if (channelResult.truncated) return;
413
+ const channelIds = new Set(channelResult.items.map((channel) => channel.id?.trim()).filter((channelId) => Boolean(channelId)));
414
+ const matches = stableConfiguredKeys.filter((teamKey) => channelIds.has(teamKey));
415
+ return matches.length === 1 ? matches[0] : void 0;
416
+ }
417
+ async function resolveStableChannelTarget(cfg, target) {
418
+ if (isStableGraphChannelTarget(target)) return target;
419
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(cfg.channels?.msteams)) return;
420
+ try {
421
+ const [resolved] = await require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
422
+ cfg,
423
+ entries: [target]
424
+ });
425
+ return resolved?.resolved && resolved.graphTeamId && resolved.channelId ? `${resolved.graphTeamId}/${resolved.channelId}` : void 0;
426
+ } catch {
427
+ return;
428
+ }
292
429
  }
430
+ async function resolveAllowedChannelTarget(cfg, target) {
431
+ const teams = cfg.channels?.msteams;
432
+ const groupPolicy = resolveMSTeamsReadGroupPolicy(cfg);
433
+ if (groupPolicy === "disabled") return;
434
+ const [teamId, channelId] = target.split("/", 2);
435
+ if (!teamId || !channelId) return;
436
+ const directRoute = resolveMSTeamsRouteConfig({
437
+ cfg: teams,
438
+ teamId,
439
+ teamName: teamId,
440
+ conversationId: channelId,
441
+ channelName: channelId,
442
+ allowNameMatching: (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)
443
+ });
444
+ const stableTarget = await resolveStableChannelTarget(cfg, target);
445
+ if (directRoute.allowed) return stableTarget;
446
+ if (!directRoute.allowlistConfigured) return groupPolicy === "open" ? stableTarget : void 0;
447
+ if (!stableTarget || !teams?.teams) return;
448
+ const [stableTeamId, stableChannelId] = stableTarget.split("/", 2);
449
+ if (!stableTeamId || !stableChannelId) return;
450
+ try {
451
+ const botFrameworkTeamKey = await resolveConfiguredBotFrameworkTeamKey(cfg, stableTeamId);
452
+ if (botFrameworkTeamKey) {
453
+ if (resolveMSTeamsRouteConfig({
454
+ cfg: teams,
455
+ teamId: botFrameworkTeamKey,
456
+ conversationId: stableChannelId
457
+ }).allowed) return stableTarget;
458
+ }
459
+ if (!hasMutableChannelConfig(cfg)) return;
460
+ const resolved = await require_resolve_allowlist.resolveMSTeamsTeamsConfig({
461
+ cfg,
462
+ teamIdMode: "graph",
463
+ teams: teams.teams
464
+ });
465
+ return resolveMSTeamsRouteConfig({
466
+ cfg: {
467
+ ...teams,
468
+ teams: resolved.teams
469
+ },
470
+ teamId: stableTeamId,
471
+ conversationId: stableChannelId
472
+ }).allowed ? stableTarget : void 0;
473
+ } catch {
474
+ return;
475
+ }
476
+ }
477
+ function bothUnknownScopesAllowed(cfg) {
478
+ const teams = cfg.channels?.msteams;
479
+ return resolveMSTeamsReadGroupPolicy(cfg) === "open" && (teams?.dmPolicy ?? "pairing") === "open";
480
+ }
481
+ async function assertMSTeamsReadTargetAllowed(params) {
482
+ const target = normalizeTarget(params.target);
483
+ const isChannel = target.includes("/");
484
+ const isDm = /^user:/i.test(target);
485
+ const isChat = require_resolve_allowlist.looksLikeMSTeamsConversationId(target);
486
+ const current = isCurrentMSTeamsReadTarget({
487
+ ctx: params.ctx,
488
+ target
489
+ });
490
+ const directOperator = params.ctx.conversationReadOrigin === "direct-operator";
491
+ const currentChatType = params.ctx.toolContext?.currentChatType;
492
+ const allowedTarget = directOperator ? isChannel ? resolveMSTeamsReadGroupPolicy(params.cfg) !== "disabled" ? await resolveStableChannelTarget(params.cfg, target) : void 0 : isDm ? await resolveDirectDmTarget(params.cfg, target) : isChat && resolveMSTeamsReadGroupPolicy(params.cfg) !== "disabled" && params.cfg.channels?.msteams?.dmPolicy !== "disabled" ? target : void 0 : current ? isChannel ? resolveMSTeamsReadGroupPolicy(params.cfg) !== "disabled" ? target : void 0 : isDm ? params.cfg.channels?.msteams?.dmPolicy !== "disabled" ? target : void 0 : currentChatType === "direct" ? params.cfg.channels?.msteams?.dmPolicy !== "disabled" ? target : void 0 : currentChatType === "group" || currentChatType === "channel" ? resolveMSTeamsReadGroupPolicy(params.cfg) !== "disabled" ? target : void 0 : resolveMSTeamsReadGroupPolicy(params.cfg) !== "disabled" && params.cfg.channels?.msteams?.dmPolicy !== "disabled" ? target : void 0 : isChannel ? await resolveAllowedChannelTarget(params.cfg, target) : isDm ? await resolveAllowedDmTarget(params.cfg, target) : isChat ? bothUnknownScopesAllowed(params.cfg) ? target : void 0 : false;
493
+ if (!allowedTarget) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams read target is not allowed.");
494
+ return allowedTarget;
495
+ }
496
+ async function assertMSTeamsTeamEnumerationAllowed(params) {
497
+ const teams = params.cfg.channels?.msteams;
498
+ const groupPolicy = resolveMSTeamsReadGroupPolicy(params.cfg);
499
+ if (groupPolicy === "disabled") throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list is not allowed.");
500
+ const directRoute = resolveMSTeamsRouteConfig({
501
+ cfg: teams,
502
+ teamId: params.teamId,
503
+ teamName: params.teamId,
504
+ conversationId: "__openclaw_all_channels__",
505
+ allowNameMatching: (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)
506
+ });
507
+ const stableTeamId = isStableGraphTeamId(params.teamId) ? params.teamId : (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams) ? (await require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
508
+ cfg: params.cfg,
509
+ entries: [params.teamId]
510
+ }))[0]?.graphTeamId : void 0;
511
+ if (!stableTeamId) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list requires access to every channel in the team.");
512
+ if (params.ctx?.conversationReadOrigin === "direct-operator") return stableTeamId;
513
+ let allowed = directRoute.allowlistConfigured ? directRoute.allowed : groupPolicy === "open";
514
+ if (!allowed && teams?.teams) try {
515
+ const botFrameworkTeamKey = await resolveConfiguredBotFrameworkTeamKey(params.cfg, stableTeamId);
516
+ if (botFrameworkTeamKey) allowed = resolveMSTeamsRouteConfig({
517
+ cfg: teams,
518
+ teamId: botFrameworkTeamKey,
519
+ conversationId: "__openclaw_all_channels__"
520
+ }).allowed;
521
+ if (!allowed && hasMutableChannelConfig(params.cfg)) {
522
+ const resolved = await require_resolve_allowlist.resolveMSTeamsTeamsConfig({
523
+ cfg: params.cfg,
524
+ teamIdMode: "graph",
525
+ teams: teams.teams
526
+ });
527
+ allowed = resolveMSTeamsRouteConfig({
528
+ cfg: {
529
+ ...teams,
530
+ teams: resolved.teams
531
+ },
532
+ teamId: stableTeamId,
533
+ conversationId: "__openclaw_all_channels__"
534
+ }).allowed;
535
+ }
536
+ } catch {
537
+ allowed = false;
538
+ }
539
+ if (!allowed) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list requires access to every channel in the team.");
540
+ return stableTeamId;
541
+ }
542
+ //#endregion
543
+ //#region extensions/msteams/src/inbound.ts
293
544
  /**
294
545
  * Strip HTML tags, preserving text content.
295
546
  */
296
547
  function htmlToPlainText(html) {
297
- return decodeHtmlEntities(html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim());
548
+ return (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(html.replace(/<[^>]*>/g, " ")).replaceAll("\xA0", " ").replace(/\s+/g, " ").trim();
298
549
  }
299
550
  /**
300
551
  * Extract quote info from MS Teams HTML reply attachments.
@@ -312,11 +563,13 @@ function extractMSTeamsQuoteInfo(attachments) {
312
563
  if (!content.includes("http://schema.skype.com/Reply")) continue;
313
564
  const senderMatch = /<strong[^>]*itemprop=["']mri["'][^>]*>(.*?)<\/strong>/i.exec(content);
314
565
  const sender = senderMatch?.[1] ? htmlToPlainText(senderMatch[1]) : void 0;
315
- const bodyMatch = /<p[^>]*itemprop=["']copy["'][^>]*>(.*?)<\/p>/is.exec(content);
566
+ const bodyMatch = /<p[^>]*itemprop=["']copy["'][^>]*>(.*?)<\/p>/is.exec(content) ?? /<p[^>]*itemprop=["']preview["'][^>]*>(.*?)<\/p>/is.exec(content);
316
567
  const body = bodyMatch?.[1] ? htmlToPlainText(bodyMatch[1]) : void 0;
568
+ const id = /<blockquote[^>]*\bitemid=["']([^"']+)["'][^>]*>/is.exec(content)?.[1]?.trim() || void 0;
317
569
  if (body) return {
318
570
  sender: sender ?? "unknown",
319
- body
571
+ body,
572
+ ...id ? { id } : {}
320
573
  };
321
574
  }
322
575
  }
@@ -337,22 +590,6 @@ function parseMSTeamsActivityTimestamp(value) {
337
590
  function stripMSTeamsMentionTags(text) {
338
591
  return text.replace(/<at[^>]*>.*?<\/at>/gi, "").trim();
339
592
  }
340
- /**
341
- * Bot Framework uses 'a:xxx' conversation IDs for personal chats, but Graph API
342
- * requires the '19:{userId}_{botAppId}@unq.gbl.spaces' format.
343
- *
344
- * This is the documented Graph API format for 1:1 chat thread IDs between a user
345
- * and a bot/app. See Microsoft docs "Get chat between user and app":
346
- * https://learn.microsoft.com/en-us/graph/api/userscopeteamsappinstallation-get-chat
347
- *
348
- * The format is only synthesized when the Bot Framework conversation ID starts with
349
- * 'a:' (the opaque format used by BF but not recognized by Graph). If the ID already
350
- * has the '19:...' Graph format, it is passed through unchanged.
351
- */
352
- function translateMSTeamsDmConversationIdForGraph(params) {
353
- const { isDirectMessage, conversationId, aadObjectId, appId } = params;
354
- return isDirectMessage && conversationId.startsWith("a:") && aadObjectId && appId ? `19:${aadObjectId}_${appId}@unq.gbl.spaces` : conversationId;
355
- }
356
593
  function wasMSTeamsBotMentioned(activity) {
357
594
  const botId = activity.recipient?.id;
358
595
  if (!botId) return false;
@@ -364,7 +601,7 @@ const TRAILING_THREAD_SUFFIX = /(?::thread:[^:]+)+$/;
364
601
  function resolveMSTeamsRouteSessionKey(params) {
365
602
  const channelThreadId = params.isChannel ? params.conversationMessageId ?? params.replyToId ?? void 0 : void 0;
366
603
  const cleanBase = params.baseSessionKey.replace(TRAILING_THREAD_SUFFIX, "");
367
- return resolveThreadSessionKeys({
604
+ return (0, openclaw_plugin_sdk_routing.resolveThreadSessionKeys)({
368
605
  baseSessionKey: cleanBase,
369
606
  threadId: channelThreadId,
370
607
  parentSessionKey: channelThreadId ? cleanBase : void 0
@@ -373,10 +610,10 @@ function resolveMSTeamsRouteSessionKey(params) {
373
610
  //#endregion
374
611
  //#region extensions/msteams/src/session-route.ts
375
612
  function resolveMSTeamsOutboundSessionRoute(params) {
376
- const trimmed = stripChannelTargetPrefix(params.target, "msteams", "teams");
613
+ const trimmed = (0, openclaw_plugin_sdk_channel_core.stripChannelTargetPrefix)(params.target, "msteams", "teams");
377
614
  if (!trimmed) return null;
378
- const isUser = normalizeLowercaseStringOrEmpty(trimmed).startsWith("user:");
379
- const rawId = stripTargetKindPrefix(trimmed);
615
+ const isUser = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(trimmed).startsWith("user:");
616
+ const rawId = (0, openclaw_plugin_sdk_channel_core.stripTargetKindPrefix)(trimmed);
380
617
  if (!rawId) return null;
381
618
  const conversationId = normalizeMSTeamsConversationId(rawId);
382
619
  const isChannel = !isUser && /@thread\.tacv2/i.test(conversationId);
@@ -386,7 +623,7 @@ function resolveMSTeamsOutboundSessionRoute(params) {
386
623
  const resolvedKind = params.resolvedTarget?.kind;
387
624
  const isCanonicalUserId = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(conversationId);
388
625
  const recipientSessionExact = (isUser || resolvedKind === "user") && isCanonicalUserId || (isChannel ? channelThreadId !== void 0 : resolvedKind === "group");
389
- const route = buildChannelOutboundSessionRoute({
626
+ const route = (0, openclaw_plugin_sdk_channel_core.buildChannelOutboundSessionRoute)({
390
627
  cfg: params.cfg,
391
628
  agentId: params.agentId,
392
629
  channel: "msteams",
@@ -436,26 +673,26 @@ const MSTEAMS_GROUP_MANAGEMENT_ACTIONS = /* @__PURE__ */ new Set([
436
673
  "removeParticipant",
437
674
  "renameGroup"
438
675
  ]);
439
- const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarningCollector({
676
+ const collectMSTeamsSecurityWarnings = (0, openclaw_plugin_sdk_channel_policy.createAllowlistProviderGroupPolicyWarningCollector)({
440
677
  providerConfigPresent: (cfg) => cfg.channels?.msteams !== void 0,
441
678
  resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
442
679
  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."] : []
443
680
  });
444
- const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-Bwu6Tjhf.js"), "msTeamsChannelRuntime");
681
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-DQTOzzet.cjs")), "msTeamsChannelRuntime");
445
682
  const resolveMSTeamsChannelConfig = (cfg) => ({
446
683
  allowFrom: cfg.channels?.msteams?.allowFrom,
447
684
  defaultTo: cfg.channels?.msteams?.defaultTo
448
685
  });
449
- const msteamsConfigAdapter = createTopLevelChannelConfigAdapter({
686
+ const msteamsConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createTopLevelChannelConfigAdapter)({
450
687
  sectionKey: "msteams",
451
688
  resolveAccount: (cfg) => ({
452
- accountId: DEFAULT_ACCOUNT_ID,
689
+ accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
453
690
  enabled: cfg.channels?.msteams?.enabled !== false,
454
- configured: Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams))
691
+ configured: Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams))
455
692
  }),
456
693
  resolveAccessorAccount: ({ cfg }) => resolveMSTeamsChannelConfig(cfg),
457
694
  resolveAllowFrom: (account) => account.allowFrom,
458
- formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
695
+ formatAllowFrom: (allowFrom) => (0, openclaw_plugin_sdk_allow_from.formatAllowFromLowercase)({ allowFrom }),
459
696
  resolveDefaultTo: (account) => account.defaultTo
460
697
  });
461
698
  function jsonActionResult(data) {
@@ -526,17 +763,28 @@ function requireMSTeamsGroupManagementAuthorization(ctx) {
526
763
  function resolveActionTarget(params, currentChannelId) {
527
764
  return typeof params.to === "string" ? params.to.trim() : typeof params.target === "string" ? params.target.trim() : currentChannelId?.trim() ?? "";
528
765
  }
529
- function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelId) {
530
- return resolveActionTarget(params, currentGraphChannelId ?? currentChannelId);
766
+ function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelId, currentChatType) {
767
+ const explicitTarget = resolveActionTarget(params);
768
+ const currentChannelTarget = currentChannelId?.trim();
769
+ const currentGraphTarget = currentGraphChannelId?.trim();
770
+ if (explicitTarget) {
771
+ if (currentChatType === "channel" && currentGraphTarget && currentChannelTarget && explicitTarget === currentChannelTarget) return currentGraphTarget;
772
+ return explicitTarget;
773
+ }
774
+ if (currentGraphTarget) return currentGraphTarget;
775
+ return currentChatType === "channel" ? "" : currentChannelTarget ?? "";
776
+ }
777
+ function resolveCurrentGraphActionTarget(toolContext) {
778
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentGraphChannelId) ?? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentMessagingTarget);
531
779
  }
532
780
  function resolveActionMessageId(params) {
533
- return normalizeOptionalString(params.messageId) ?? "";
781
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.messageId) ?? "";
534
782
  }
535
783
  function resolveActionPinnedMessageId(params) {
536
784
  return typeof params.pinnedMessageId === "string" ? params.pinnedMessageId.trim() : typeof params.messageId === "string" ? params.messageId.trim() : "";
537
785
  }
538
786
  function resolveActionQuery(params) {
539
- return normalizeOptionalString(params.query) ?? "";
787
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.query) ?? "";
540
788
  }
541
789
  function resolveActionContent(params) {
542
790
  return typeof params.text === "string" ? params.text : typeof params.content === "string" ? params.content : typeof params.message === "string" ? params.message : "";
@@ -555,12 +803,12 @@ function resolveActionUploadFilePath(params) {
555
803
  }
556
804
  }
557
805
  function resolveRequiredActionTarget(params) {
558
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
806
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
559
807
  if (!to) return actionError(`${params.actionLabel} requires a target (to).`);
560
808
  return to;
561
809
  }
562
810
  function resolveRequiredActionMessageTarget(params) {
563
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
811
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
564
812
  const messageId = resolveActionMessageId(params.toolParams);
565
813
  if (!to || !messageId) return actionError(`${params.actionLabel} requires a target (to) and messageId.`);
566
814
  return {
@@ -569,7 +817,7 @@ function resolveRequiredActionMessageTarget(params) {
569
817
  };
570
818
  }
571
819
  function resolveRequiredActionPinnedMessageTarget(params) {
572
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
820
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
573
821
  const pinnedMessageId = resolveActionPinnedMessageId(params.toolParams);
574
822
  if (!to || !pinnedMessageId) return actionError(`${params.actionLabel} requires a target (to) and pinnedMessageId.`);
575
823
  return {
@@ -583,6 +831,7 @@ async function runWithRequiredActionTarget(params) {
583
831
  toolParams: params.toolParams,
584
832
  currentChannelId: params.currentChannelId,
585
833
  currentGraphChannelId: params.currentGraphChannelId,
834
+ currentChatType: params.currentChatType,
586
835
  graphOnly: params.graphOnly
587
836
  });
588
837
  if (typeof to !== "string") return to;
@@ -594,6 +843,7 @@ async function runWithRequiredActionMessageTarget(params) {
594
843
  toolParams: params.toolParams,
595
844
  currentChannelId: params.currentChannelId,
596
845
  currentGraphChannelId: params.currentGraphChannelId,
846
+ currentChatType: params.currentChatType,
597
847
  graphOnly: params.graphOnly
598
848
  });
599
849
  if ("isError" in target) return target;
@@ -605,13 +855,14 @@ async function runWithRequiredActionPinnedMessageTarget(params) {
605
855
  toolParams: params.toolParams,
606
856
  currentChannelId: params.currentChannelId,
607
857
  currentGraphChannelId: params.currentGraphChannelId,
858
+ currentChatType: params.currentChatType,
608
859
  graphOnly: params.graphOnly
609
860
  });
610
861
  if ("isError" in target) return target;
611
862
  return await params.run(target);
612
863
  }
613
864
  function describeMSTeamsMessageTool({ cfg }) {
614
- const enabled = cfg.channels?.msteams?.enabled !== false && Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams));
865
+ const enabled = cfg.channels?.msteams?.enabled !== false && Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams));
615
866
  return {
616
867
  actions: enabled ? [
617
868
  "upload-file",
@@ -635,13 +886,13 @@ function describeMSTeamsMessageTool({ cfg }) {
635
886
  capabilities: enabled ? ["presentation"] : [],
636
887
  schema: enabled ? {
637
888
  actions: ["unpin"],
638
- properties: { pinnedMessageId: Type.Optional(Type.String({ description: "Pinned message resource ID for unpin (from pin or list-pins, not the chat message ID)." })) }
889
+ properties: { pinnedMessageId: typebox.Type.Optional(typebox.Type.String({ description: "Pinned message resource ID for unpin (from pin or list-pins, not the chat message ID)." })) }
639
890
  } : null
640
891
  };
641
892
  }
642
893
  const msteamsChannelOutbound = {
643
894
  deliveryMode: "direct",
644
- chunker: chunkTextForOutbound,
895
+ chunker: openclaw_plugin_sdk_text_chunking.chunkTextForOutbound,
645
896
  chunkerMode: "markdown",
646
897
  textChunkLimit: 4e3,
647
898
  pollMaxOptions: 12,
@@ -652,7 +903,7 @@ const msteamsChannelOutbound = {
652
903
  messageSendingHooks: true
653
904
  } },
654
905
  presentationCapabilities: MSTEAMS_PRESENTATION_CAPABILITIES,
655
- ...createRuntimeOutboundDelegates({
906
+ ...(0, openclaw_plugin_sdk_channel_outbound.createRuntimeOutboundDelegates)({
656
907
  getRuntime: loadMSTeamsChannelRuntime,
657
908
  renderPresentation: { resolve: (runtime) => runtime.msteamsOutbound.renderPresentation },
658
909
  sendPayload: { resolve: (runtime) => runtime.msteamsOutbound.sendPayload },
@@ -661,7 +912,7 @@ const msteamsChannelOutbound = {
661
912
  sendPoll: { resolve: (runtime) => runtime.msteamsOutbound.sendPoll }
662
913
  })
663
914
  };
664
- const msteamsMessageAdapter = createChannelMessageAdapterFromOutbound({
915
+ const msteamsMessageAdapter = (0, openclaw_plugin_sdk_channel_outbound.createChannelMessageAdapterFromOutbound)({
665
916
  id: "msteams",
666
917
  outbound: msteamsChannelOutbound,
667
918
  live: {
@@ -678,14 +929,14 @@ const msteamsMessageAdapter = createChannelMessageAdapterFromOutbound({
678
929
  } }
679
930
  }
680
931
  });
681
- const msteamsPlugin = createChatChannelPlugin({
932
+ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlugin)({
682
933
  base: {
683
934
  id: "msteams",
684
935
  meta: {
685
936
  ...meta,
686
937
  aliases: [...meta.aliases]
687
938
  },
688
- setupWizard: msteamsSetupWizard,
939
+ setupWizard: require_setup_surface.msteamsSetupWizard,
689
940
  capabilities: {
690
941
  chatTypes: [
691
942
  "direct",
@@ -703,11 +954,11 @@ const msteamsPlugin = createChatChannelPlugin({
703
954
  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."] },
704
955
  groups: { resolveToolPolicy: resolveMSTeamsGroupToolPolicy },
705
956
  reload: { configPrefixes: ["channels.msteams"] },
706
- configSchema: MSTeamsChannelConfigSchema,
957
+ configSchema: require_config_schema.MSTeamsChannelConfigSchema,
707
958
  config: {
708
959
  ...msteamsConfigAdapter,
709
- isConfigured: (_account, cfg) => Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams)),
710
- describeAccount: (account) => describeAccountSnapshot({
960
+ isConfigured: (_account, cfg) => Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams)),
961
+ describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
711
962
  account,
712
963
  configured: account.configured
713
964
  })
@@ -720,20 +971,20 @@ const msteamsPlugin = createChatChannelPlugin({
720
971
  warnOnEmptyGroupSenderAllowlist: true,
721
972
  collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings
722
973
  },
723
- setup: msteamsSetupAdapter,
974
+ setup: require_setup_surface.msteamsSetupAdapter,
724
975
  messaging: {
725
976
  targetPrefixes: ["msteams", "teams"],
726
- normalizeTarget: normalizeMSTeamsMessagingTarget,
977
+ normalizeTarget: require_resolve_allowlist.normalizeMSTeamsMessagingTarget,
727
978
  resolveOutboundSessionRoute: (params) => resolveMSTeamsOutboundSessionRoute(params),
728
979
  targetResolver: {
729
- looksLikeId: (raw) => looksLikeMSTeamsTargetId(raw),
980
+ looksLikeId: (raw) => require_resolve_allowlist.looksLikeMSTeamsTargetId(raw),
730
981
  hint: "<conversationId|user:ID|conversation:ID>"
731
982
  }
732
983
  },
733
984
  message: msteamsMessageAdapter,
734
- directory: createChannelDirectoryAdapter({
985
+ directory: (0, openclaw_plugin_sdk_directory_runtime.createChannelDirectoryAdapter)({
735
986
  self: async ({ cfg }) => {
736
- const creds = resolveMSTeamsCredentials(cfg.channels?.msteams);
987
+ const creds = require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams);
737
988
  if (!creds) return null;
738
989
  return {
739
990
  kind: "user",
@@ -741,26 +992,26 @@ const msteamsPlugin = createChatChannelPlugin({
741
992
  name: creds.appId
742
993
  };
743
994
  },
744
- listPeers: async ({ cfg, query, limit }) => listDirectoryEntriesFromSources({
995
+ listPeers: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
745
996
  kind: "user",
746
997
  sources: [cfg.channels?.msteams?.allowFrom ?? [], Object.keys(cfg.channels?.msteams?.dms ?? {})],
747
998
  query,
748
999
  limit,
749
1000
  normalizeId: (raw) => {
750
- const normalized = normalizeMSTeamsMessagingTarget(raw) ?? raw;
1001
+ const normalized = require_resolve_allowlist.normalizeMSTeamsMessagingTarget(raw) ?? raw;
751
1002
  const lowered = normalized.toLowerCase();
752
1003
  if (lowered.startsWith("user:") || lowered.startsWith("conversation:")) return normalized;
753
1004
  return `user:${normalized}`;
754
1005
  }
755
1006
  }),
756
- listGroups: async ({ cfg, query, limit }) => listDirectoryEntriesFromSources({
1007
+ listGroups: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
757
1008
  kind: "group",
758
1009
  sources: [Object.values(cfg.channels?.msteams?.teams ?? {}).flatMap((team) => Object.keys(team.channels ?? {}))],
759
1010
  query,
760
1011
  limit,
761
1012
  normalizeId: (raw) => `conversation:${raw.replace(/^conversation:/i, "").trim()}`
762
1013
  }),
763
- ...createRuntimeDirectoryLiveAdapter({
1014
+ ...(0, openclaw_plugin_sdk_directory_runtime.createRuntimeDirectoryLiveAdapter)({
764
1015
  getRuntime: loadMSTeamsChannelRuntime,
765
1016
  listPeersLive: (runtime) => runtime.listMSTeamsDirectoryPeersLive,
766
1017
  listGroupsLive: (runtime) => runtime.listMSTeamsDirectoryGroupsLive
@@ -774,7 +1025,7 @@ const msteamsPlugin = createChatChannelPlugin({
774
1025
  name: void 0,
775
1026
  note: void 0
776
1027
  }));
777
- const stripPrefix = (value) => normalizeMSTeamsUserInput(value);
1028
+ const stripPrefix = (value) => require_resolve_allowlist.normalizeMSTeamsUserInput(value);
778
1029
  const markPendingLookupFailed = (pending) => {
779
1030
  pending.forEach(({ index }) => {
780
1031
  const entry = results[index];
@@ -814,7 +1065,7 @@ const msteamsPlugin = createChatChannelPlugin({
814
1065
  index
815
1066
  });
816
1067
  });
817
- await resolvePending(pending, (entries) => resolveMSTeamsUserAllowlist({
1068
+ await resolvePending(pending, (entries) => require_resolve_allowlist.resolveMSTeamsUserAllowlist({
818
1069
  cfg,
819
1070
  entries
820
1071
  }), (target, entry) => {
@@ -832,14 +1083,14 @@ const msteamsPlugin = createChatChannelPlugin({
832
1083
  entry.note = "empty input";
833
1084
  return;
834
1085
  }
835
- const conversationId = parseMSTeamsConversationId(trimmed);
1086
+ const conversationId = require_resolve_allowlist.parseMSTeamsConversationId(trimmed);
836
1087
  if (conversationId !== null) {
837
1088
  entry.resolved = Boolean(conversationId);
838
1089
  entry.id = conversationId || void 0;
839
1090
  entry.note = conversationId ? "conversation id" : "empty conversation id";
840
1091
  return;
841
1092
  }
842
- const parsed = parseMSTeamsTeamChannelInput(trimmed);
1093
+ const parsed = require_resolve_allowlist.parseMSTeamsTeamChannelInput(trimmed);
843
1094
  if (!parsed.team) {
844
1095
  entry.note = "missing team";
845
1096
  return;
@@ -851,7 +1102,7 @@ const msteamsPlugin = createChatChannelPlugin({
851
1102
  index
852
1103
  });
853
1104
  });
854
- await resolvePending(pending, (entries) => resolveMSTeamsChannelAllowlist({
1105
+ await resolvePending(pending, (entries) => require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
855
1106
  cfg,
856
1107
  entries
857
1108
  }), (target, entry) => {
@@ -875,13 +1126,13 @@ const msteamsPlugin = createChatChannelPlugin({
875
1126
  } },
876
1127
  actions: {
877
1128
  describeMessageTool: describeMSTeamsMessageTool,
878
- requiresTrustedRequesterSender: ({ action, toolContext }) => normalizeOptionalString(toolContext?.currentChannelProvider)?.toLowerCase() === "msteams" && MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(action),
1129
+ requiresTrustedRequesterSender: ({ action, toolContext }) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentChannelProvider)?.toLowerCase() === "msteams" && MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(action),
879
1130
  handleAction: async (ctx) => {
880
1131
  if (MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(ctx.action)) {
881
1132
  const authError = requireMSTeamsGroupManagementAuthorization(ctx);
882
1133
  if (authError) return authError;
883
1134
  }
884
- const presentation = ctx.action === "send" ? normalizeMessagePresentation(ctx.params.presentation) : void 0;
1135
+ const presentation = ctx.action === "send" ? (0, openclaw_plugin_sdk_interactive_runtime.normalizeMessagePresentation)(ctx.params.presentation) : void 0;
885
1136
  if (ctx.action === "send" && presentation) {
886
1137
  const card = buildMSTeamsPresentationCard({
887
1138
  presentation,
@@ -952,10 +1203,15 @@ const msteamsPlugin = createChatChannelPlugin({
952
1203
  toolParams: ctx.params,
953
1204
  currentChannelId: ctx.toolContext?.currentChannelId,
954
1205
  run: async (target) => {
1206
+ const to = await assertMSTeamsReadTargetAllowed({
1207
+ cfg: ctx.cfg,
1208
+ ctx,
1209
+ target: target.to
1210
+ });
955
1211
  const { editMessageMSTeams } = await loadMSTeamsChannelRuntime();
956
1212
  return jsonMSTeamsConversationResult((await editMessageMSTeams({
957
1213
  cfg: ctx.cfg,
958
- to: target.to,
1214
+ to,
959
1215
  activityId: target.messageId,
960
1216
  text: content
961
1217
  })).conversationId);
@@ -967,10 +1223,15 @@ const msteamsPlugin = createChatChannelPlugin({
967
1223
  toolParams: ctx.params,
968
1224
  currentChannelId: ctx.toolContext?.currentChannelId,
969
1225
  run: async (target) => {
1226
+ const to = await assertMSTeamsReadTargetAllowed({
1227
+ cfg: ctx.cfg,
1228
+ ctx,
1229
+ target: target.to
1230
+ });
970
1231
  const { deleteMessageMSTeams } = await loadMSTeamsChannelRuntime();
971
1232
  return jsonMSTeamsConversationResult((await deleteMessageMSTeams({
972
1233
  cfg: ctx.cfg,
973
- to: target.to,
1234
+ to,
974
1235
  activityId: target.messageId
975
1236
  })).conversationId);
976
1237
  }
@@ -979,13 +1240,19 @@ const msteamsPlugin = createChatChannelPlugin({
979
1240
  actionLabel: "Read",
980
1241
  toolParams: ctx.params,
981
1242
  currentChannelId: ctx.toolContext?.currentChannelId,
982
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1243
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1244
+ currentChatType: ctx.toolContext?.currentChatType,
983
1245
  graphOnly: true,
984
1246
  run: async (target) => {
1247
+ const to = await assertMSTeamsReadTargetAllowed({
1248
+ cfg: ctx.cfg,
1249
+ ctx,
1250
+ target: target.to
1251
+ });
985
1252
  const { getMessageMSTeams } = await loadMSTeamsChannelRuntime();
986
1253
  return jsonMSTeamsOkActionResult("read", { message: await getMessageMSTeams({
987
1254
  cfg: ctx.cfg,
988
- to: target.to,
1255
+ to,
989
1256
  messageId: target.messageId
990
1257
  }) });
991
1258
  }
@@ -994,13 +1261,19 @@ const msteamsPlugin = createChatChannelPlugin({
994
1261
  actionLabel: "Pin",
995
1262
  toolParams: ctx.params,
996
1263
  currentChannelId: ctx.toolContext?.currentChannelId,
997
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1264
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1265
+ currentChatType: ctx.toolContext?.currentChatType,
998
1266
  graphOnly: true,
999
1267
  run: async (target) => {
1268
+ const to = await assertMSTeamsReadTargetAllowed({
1269
+ cfg: ctx.cfg,
1270
+ ctx,
1271
+ target: target.to
1272
+ });
1000
1273
  const { pinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1001
1274
  return jsonMSTeamsActionResult("pin", await pinMessageMSTeams({
1002
1275
  cfg: ctx.cfg,
1003
- to: target.to,
1276
+ to,
1004
1277
  messageId: target.messageId
1005
1278
  }));
1006
1279
  }
@@ -1009,13 +1282,19 @@ const msteamsPlugin = createChatChannelPlugin({
1009
1282
  actionLabel: "Unpin",
1010
1283
  toolParams: ctx.params,
1011
1284
  currentChannelId: ctx.toolContext?.currentChannelId,
1012
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1285
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1286
+ currentChatType: ctx.toolContext?.currentChatType,
1013
1287
  graphOnly: true,
1014
1288
  run: async (target) => {
1289
+ const to = await assertMSTeamsReadTargetAllowed({
1290
+ cfg: ctx.cfg,
1291
+ ctx,
1292
+ target: target.to
1293
+ });
1015
1294
  const { unpinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1016
1295
  return jsonMSTeamsActionResult("unpin", await unpinMessageMSTeams({
1017
1296
  cfg: ctx.cfg,
1018
- to: target.to,
1297
+ to,
1019
1298
  pinnedMessageId: target.pinnedMessageId
1020
1299
  }));
1021
1300
  }
@@ -1024,13 +1303,19 @@ const msteamsPlugin = createChatChannelPlugin({
1024
1303
  actionLabel: "List-pins",
1025
1304
  toolParams: ctx.params,
1026
1305
  currentChannelId: ctx.toolContext?.currentChannelId,
1027
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1306
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1307
+ currentChatType: ctx.toolContext?.currentChatType,
1028
1308
  graphOnly: true,
1029
1309
  run: async (to) => {
1310
+ const allowedTarget = await assertMSTeamsReadTargetAllowed({
1311
+ cfg: ctx.cfg,
1312
+ ctx,
1313
+ target: to
1314
+ });
1030
1315
  const { listPinsMSTeams } = await loadMSTeamsChannelRuntime();
1031
1316
  return jsonMSTeamsOkActionResult("list-pins", await listPinsMSTeams({
1032
1317
  cfg: ctx.cfg,
1033
- to
1318
+ to: allowedTarget
1034
1319
  }));
1035
1320
  }
1036
1321
  });
@@ -1038,7 +1323,8 @@ const msteamsPlugin = createChatChannelPlugin({
1038
1323
  actionLabel: "React",
1039
1324
  toolParams: ctx.params,
1040
1325
  currentChannelId: ctx.toolContext?.currentChannelId,
1041
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1326
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1327
+ currentChatType: ctx.toolContext?.currentChatType,
1042
1328
  graphOnly: true,
1043
1329
  run: async (target) => {
1044
1330
  const emoji = typeof ctx.params.emoji === "string" ? ctx.params.emoji.trim() : "";
@@ -1054,6 +1340,11 @@ const msteamsPlugin = createChatChannelPlugin({
1054
1340
  validTypes: [...MSTEAMS_REACTION_TYPES]
1055
1341
  }
1056
1342
  };
1343
+ const to = await assertMSTeamsReadTargetAllowed({
1344
+ cfg: ctx.cfg,
1345
+ ctx,
1346
+ target: target.to
1347
+ });
1057
1348
  if (remove) {
1058
1349
  const { unreactMessageMSTeams } = await loadMSTeamsChannelRuntime();
1059
1350
  return jsonMSTeamsActionResult("react", {
@@ -1061,7 +1352,7 @@ const msteamsPlugin = createChatChannelPlugin({
1061
1352
  reactionType: emoji,
1062
1353
  ...await unreactMessageMSTeams({
1063
1354
  cfg: ctx.cfg,
1064
- to: target.to,
1355
+ to,
1065
1356
  messageId: target.messageId,
1066
1357
  reactionType: emoji
1067
1358
  })
@@ -1072,7 +1363,7 @@ const msteamsPlugin = createChatChannelPlugin({
1072
1363
  reactionType: emoji,
1073
1364
  ...await reactMessageMSTeams({
1074
1365
  cfg: ctx.cfg,
1075
- to: target.to,
1366
+ to,
1076
1367
  messageId: target.messageId,
1077
1368
  reactionType: emoji
1078
1369
  })
@@ -1083,13 +1374,19 @@ const msteamsPlugin = createChatChannelPlugin({
1083
1374
  actionLabel: "Reactions",
1084
1375
  toolParams: ctx.params,
1085
1376
  currentChannelId: ctx.toolContext?.currentChannelId,
1086
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1377
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1378
+ currentChatType: ctx.toolContext?.currentChatType,
1087
1379
  graphOnly: true,
1088
1380
  run: async (target) => {
1381
+ const to = await assertMSTeamsReadTargetAllowed({
1382
+ cfg: ctx.cfg,
1383
+ ctx,
1384
+ target: target.to
1385
+ });
1089
1386
  const { listReactionsMSTeams } = await loadMSTeamsChannelRuntime();
1090
1387
  return jsonMSTeamsOkActionResult("reactions", await listReactionsMSTeams({
1091
1388
  cfg: ctx.cfg,
1092
- to: target.to,
1389
+ to,
1093
1390
  messageId: target.messageId
1094
1391
  }));
1095
1392
  }
@@ -1098,9 +1395,15 @@ const msteamsPlugin = createChatChannelPlugin({
1098
1395
  actionLabel: "Search",
1099
1396
  toolParams: ctx.params,
1100
1397
  currentChannelId: ctx.toolContext?.currentChannelId,
1101
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1398
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1399
+ currentChatType: ctx.toolContext?.currentChatType,
1102
1400
  graphOnly: true,
1103
1401
  run: async (to) => {
1402
+ const allowedTarget = await assertMSTeamsReadTargetAllowed({
1403
+ cfg: ctx.cfg,
1404
+ ctx,
1405
+ target: to
1406
+ });
1104
1407
  const query = resolveActionQuery(ctx.params);
1105
1408
  if (!query) return actionError("Search requires a target (to) and query.");
1106
1409
  const limit = typeof ctx.params.limit === "number" ? ctx.params.limit : void 0;
@@ -1108,7 +1411,7 @@ const msteamsPlugin = createChatChannelPlugin({
1108
1411
  const { searchMessagesMSTeams } = await loadMSTeamsChannelRuntime();
1109
1412
  return jsonMSTeamsOkActionResult("search", await searchMessagesMSTeams({
1110
1413
  cfg: ctx.cfg,
1111
- to,
1414
+ to: allowedTarget,
1112
1415
  query,
1113
1416
  from: from || void 0,
1114
1417
  limit
@@ -1116,32 +1419,64 @@ const msteamsPlugin = createChatChannelPlugin({
1116
1419
  }
1117
1420
  });
1118
1421
  if (ctx.action === "member-info") {
1119
- const userId = normalizeOptionalString(ctx.params.userId) ?? "";
1422
+ const userId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.userId) ?? "";
1120
1423
  if (!userId) return actionError("member-info requires a userId.");
1121
- const { getMemberInfoMSTeams } = await loadMSTeamsChannelRuntime();
1122
- return jsonMSTeamsOkActionResult("member-info", await getMemberInfoMSTeams({
1123
- cfg: ctx.cfg,
1124
- userId
1125
- }));
1424
+ return await runWithRequiredActionTarget({
1425
+ actionLabel: "member-info",
1426
+ toolParams: ctx.params,
1427
+ currentChannelId: ctx.toolContext?.currentChannelId,
1428
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1429
+ currentChatType: ctx.toolContext?.currentChatType,
1430
+ graphOnly: true,
1431
+ run: async (target) => {
1432
+ const to = await assertMSTeamsReadTargetAllowed({
1433
+ cfg: ctx.cfg,
1434
+ ctx,
1435
+ target
1436
+ });
1437
+ const currentRequesterId = isCurrentMSTeamsReadTarget({
1438
+ ctx,
1439
+ target: to
1440
+ }) ? ctx.requesterSenderId : void 0;
1441
+ const { getMemberInfoMSTeams } = await loadMSTeamsChannelRuntime();
1442
+ return jsonMSTeamsOkActionResult("member-info", await getMemberInfoMSTeams({
1443
+ cfg: ctx.cfg,
1444
+ to,
1445
+ userId,
1446
+ currentRequesterId
1447
+ }));
1448
+ }
1449
+ });
1126
1450
  }
1127
1451
  if (ctx.action === "channel-list") {
1128
- const teamId = normalizeOptionalString(ctx.params.teamId) ?? "";
1452
+ const teamId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.teamId) ?? "";
1129
1453
  if (!teamId) return actionError("channel-list requires a teamId.");
1454
+ const graphTeamId = await assertMSTeamsTeamEnumerationAllowed({
1455
+ cfg: ctx.cfg,
1456
+ ctx,
1457
+ teamId
1458
+ });
1130
1459
  const { listChannelsMSTeams } = await loadMSTeamsChannelRuntime();
1131
1460
  return jsonMSTeamsOkActionResult("channel-list", await listChannelsMSTeams({
1132
1461
  cfg: ctx.cfg,
1133
- teamId
1462
+ teamId: graphTeamId
1134
1463
  }));
1135
1464
  }
1136
1465
  if (ctx.action === "channel-info") {
1137
- const teamId = normalizeOptionalString(ctx.params.teamId) ?? "";
1138
- const channelId = normalizeOptionalString(ctx.params.channelId) ?? "";
1466
+ const teamId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.teamId) ?? "";
1467
+ const channelId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.channelId) ?? "";
1139
1468
  if (!teamId || !channelId) return actionError("channel-info requires teamId and channelId.");
1469
+ const [graphTeamId, graphChannelId] = (await assertMSTeamsReadTargetAllowed({
1470
+ cfg: ctx.cfg,
1471
+ ctx,
1472
+ target: `${teamId}/${channelId}`
1473
+ })).split("/", 2);
1474
+ if (!graphTeamId || !graphChannelId) throw new Error("Authorized Microsoft Teams channel target is invalid.");
1140
1475
  const { getChannelInfoMSTeams } = await loadMSTeamsChannelRuntime();
1141
1476
  return jsonMSTeamsOkActionResult("channel-info", { channelInfo: (await getChannelInfoMSTeams({
1142
1477
  cfg: ctx.cfg,
1143
- teamId,
1144
- channelId
1478
+ teamId: graphTeamId,
1479
+ channelId: graphChannelId
1145
1480
  })).channel });
1146
1481
  }
1147
1482
  if (ctx.action === "addParticipant") {
@@ -1200,9 +1535,9 @@ const msteamsPlugin = createChatChannelPlugin({
1200
1535
  return null;
1201
1536
  }
1202
1537
  },
1203
- status: createComputedAccountStatusAdapter({
1204
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID, { port: null }),
1205
- buildChannelSummary: ({ snapshot }) => buildProbeChannelStatusSummary(snapshot, { port: snapshot.port ?? null }),
1538
+ status: (0, openclaw_plugin_sdk_status_helpers.createComputedAccountStatusAdapter)({
1539
+ defaultRuntime: (0, openclaw_plugin_sdk_channel_status.createDefaultChannelRuntimeState)(openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID, { port: null }),
1540
+ buildChannelSummary: ({ snapshot }) => (0, openclaw_plugin_sdk_channel_status.buildProbeChannelStatusSummary)(snapshot, { port: snapshot.port ?? null }),
1206
1541
  probeAccount: async ({ cfg }) => await (await loadMSTeamsChannelRuntime()).probeMSTeams(cfg.channels?.msteams),
1207
1542
  formatCapabilitiesProbe: ({ probe }) => {
1208
1543
  const teamsProbe = probe;
@@ -1211,8 +1546,8 @@ const msteamsPlugin = createChatChannelPlugin({
1211
1546
  if (appId) lines.push({ text: `App: ${appId}` });
1212
1547
  const graph = teamsProbe?.graph;
1213
1548
  if (graph) {
1214
- const roles = Array.isArray(graph.roles) ? normalizeStringEntries(graph.roles) : [];
1215
- const scopes = Array.isArray(graph.scopes) ? normalizeStringEntries(graph.scopes) : [];
1549
+ const roles = Array.isArray(graph.roles) ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeStringEntries)(graph.roles) : [];
1550
+ const scopes = Array.isArray(graph.scopes) ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeStringEntries)(graph.scopes) : [];
1216
1551
  const formatPermission = (permission) => {
1217
1552
  const hint = TEAMS_GRAPH_PERMISSION_HINTS[permission];
1218
1553
  return hint ? `${permission} (${hint})` : permission;
@@ -1236,7 +1571,7 @@ const msteamsPlugin = createChatChannelPlugin({
1236
1571
  })
1237
1572
  }),
1238
1573
  gateway: { startAccount: async (ctx) => {
1239
- const { monitorMSTeamsProvider } = await import("./src-DZFs5XtZ.js");
1574
+ const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-CUMz2B6f.cjs"));
1240
1575
  const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1241
1576
  ctx.setStatus({
1242
1577
  accountId: ctx.accountId,
@@ -1250,11 +1585,11 @@ const msteamsPlugin = createChatChannelPlugin({
1250
1585
  });
1251
1586
  } }
1252
1587
  },
1253
- security: { collectWarnings: projectConfigWarningCollector(collectMSTeamsSecurityWarnings) },
1588
+ security: { collectWarnings: (0, openclaw_plugin_sdk_channel_policy.projectConfigWarningCollector)(collectMSTeamsSecurityWarnings) },
1254
1589
  pairing: { text: {
1255
1590
  idLabel: "msteamsUserId",
1256
- message: PAIRING_APPROVED_MESSAGE,
1257
- normalizeAllowEntry: createPairingPrefixStripper(/^(msteams|user):/i),
1591
+ message: openclaw_plugin_sdk_channel_status.PAIRING_APPROVED_MESSAGE,
1592
+ normalizeAllowEntry: (0, openclaw_plugin_sdk_channel_pairing.createPairingPrefixStripper)(/^(msteams|user):/i),
1258
1593
  notify: async ({ cfg, id, message }) => {
1259
1594
  const { sendMessageMSTeams } = await loadMSTeamsChannelRuntime();
1260
1595
  await sendMessageMSTeams({
@@ -1268,7 +1603,9 @@ const msteamsPlugin = createChatChannelPlugin({
1268
1603
  const nativeChannelId = context.NativeChannelId?.trim();
1269
1604
  const hasChannelRoute = Boolean(nativeChannelId && nativeChannelId.includes("/"));
1270
1605
  return {
1271
- currentChannelId: normalizeOptionalString(context.To),
1606
+ currentChannelId: (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(context.To),
1607
+ currentChatType: context.ChatType === "direct" || context.ChatType === "group" || context.ChatType === "channel" ? context.ChatType : void 0,
1608
+ currentMessagingTarget: hasChannelRoute ? nativeChannelId : void 0,
1272
1609
  currentGraphChannelId: hasChannelRoute ? nativeChannelId : void 0,
1273
1610
  currentThreadTs: context.ReplyToId,
1274
1611
  hasRepliedRef
@@ -1277,4 +1614,81 @@ const msteamsPlugin = createChatChannelPlugin({
1277
1614
  outbound: msteamsChannelOutbound
1278
1615
  });
1279
1616
  //#endregion
1280
- export { normalizeMSTeamsConversationId as a, translateMSTeamsDmConversationIdForGraph as c, buildMSTeamsPresentationCard as d, resolveMSTeamsAllowlistMatch as f, extractMSTeamsQuoteInfo as i, wasMSTeamsBotMentioned as l, resolveMSTeamsRouteConfig as m, resolveMSTeamsRouteSessionKey as n, parseMSTeamsActivityTimestamp as o, resolveMSTeamsReplyPolicy as p, extractMSTeamsConversationMessageId as r, stripMSTeamsMentionTags as s, msteamsPlugin as t, MSTEAMS_PRESENTATION_CAPABILITIES as u };
1617
+ Object.defineProperty(exports, "MSTEAMS_PRESENTATION_CAPABILITIES", {
1618
+ enumerable: true,
1619
+ get: function() {
1620
+ return MSTEAMS_PRESENTATION_CAPABILITIES;
1621
+ }
1622
+ });
1623
+ Object.defineProperty(exports, "buildMSTeamsPresentationCard", {
1624
+ enumerable: true,
1625
+ get: function() {
1626
+ return buildMSTeamsPresentationCard;
1627
+ }
1628
+ });
1629
+ Object.defineProperty(exports, "extractMSTeamsConversationMessageId", {
1630
+ enumerable: true,
1631
+ get: function() {
1632
+ return extractMSTeamsConversationMessageId;
1633
+ }
1634
+ });
1635
+ Object.defineProperty(exports, "extractMSTeamsQuoteInfo", {
1636
+ enumerable: true,
1637
+ get: function() {
1638
+ return extractMSTeamsQuoteInfo;
1639
+ }
1640
+ });
1641
+ Object.defineProperty(exports, "msteamsPlugin", {
1642
+ enumerable: true,
1643
+ get: function() {
1644
+ return msteamsPlugin;
1645
+ }
1646
+ });
1647
+ Object.defineProperty(exports, "normalizeMSTeamsConversationId", {
1648
+ enumerable: true,
1649
+ get: function() {
1650
+ return normalizeMSTeamsConversationId;
1651
+ }
1652
+ });
1653
+ Object.defineProperty(exports, "parseMSTeamsActivityTimestamp", {
1654
+ enumerable: true,
1655
+ get: function() {
1656
+ return parseMSTeamsActivityTimestamp;
1657
+ }
1658
+ });
1659
+ Object.defineProperty(exports, "resolveMSTeamsAllowlistMatch", {
1660
+ enumerable: true,
1661
+ get: function() {
1662
+ return resolveMSTeamsAllowlistMatch;
1663
+ }
1664
+ });
1665
+ Object.defineProperty(exports, "resolveMSTeamsReplyPolicy", {
1666
+ enumerable: true,
1667
+ get: function() {
1668
+ return resolveMSTeamsReplyPolicy;
1669
+ }
1670
+ });
1671
+ Object.defineProperty(exports, "resolveMSTeamsRouteConfig", {
1672
+ enumerable: true,
1673
+ get: function() {
1674
+ return resolveMSTeamsRouteConfig;
1675
+ }
1676
+ });
1677
+ Object.defineProperty(exports, "resolveMSTeamsRouteSessionKey", {
1678
+ enumerable: true,
1679
+ get: function() {
1680
+ return resolveMSTeamsRouteSessionKey;
1681
+ }
1682
+ });
1683
+ Object.defineProperty(exports, "stripMSTeamsMentionTags", {
1684
+ enumerable: true,
1685
+ get: function() {
1686
+ return stripMSTeamsMentionTags;
1687
+ }
1688
+ });
1689
+ Object.defineProperty(exports, "wasMSTeamsBotMentioned", {
1690
+ enumerable: true,
1691
+ get: function() {
1692
+ return wasMSTeamsBotMentioned;
1693
+ }
1694
+ });