@openclaw/msteams 2026.7.1 → 2026.7.2-beta.2

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-BKc8zroK.cjs} +648 -240
  3. package/dist/channel-config-api.cjs +3 -0
  4. package/dist/channel-plugin-api.cjs +3 -0
  5. package/dist/channel.runtime-hd1Zsoo2.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-BVcKl6dv.cjs} +436 -891
  11. package/dist/{oauth-BifWxWzq.js → oauth-yNoKtU_3.cjs} +21 -21
  12. package/dist/{polls-B_hs4aKm.js → polls-BhoI4VaN.cjs} +188 -38
  13. package/dist/{resolve-allowlist-Dnw4aNOu.js → resolve-allowlist-DXd097EP.cjs} +849 -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-D4f6x5cx.cjs} +127 -61
  21. package/dist/{src-DZFs5XtZ.js → src-20YasZEp.cjs} +686 -748
  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,71 +1,142 @@
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-DXd097EP.cjs");
3
+ const require_config_schema = require("./config-schema-BSNLJUta.cjs");
4
+ const require_setup_surface = require("./setup-surface-D4f6x5cx.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
- function isMSTeamsMutableAllowEntry(raw) {
51
- const text = raw.trim();
52
- if (!text || text === "*") return false;
53
- const withoutPrefix = text.replace(/^(msteams|user):/i, "").trim();
54
- return /\s/.test(withoutPrefix) || withoutPrefix.includes("@");
55
- }
56
- const collectMSTeamsMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
58
+ const isMSTeamsMutableAllowEntry = (0, openclaw_plugin_sdk_channel_policy.buildMutableAllowEntryDetector)({
59
+ prefixes: ["msteams:", "user:"],
60
+ stableIdPattern: /^[^\s@]+$/
61
+ });
62
+ const collectMSTeamsMutableAllowlistWarnings = (0, openclaw_plugin_sdk_channel_policy.createDangerousNameMatchingMutableAllowlistWarningCollector)({
57
63
  channel: "msteams",
58
64
  detector: isMSTeamsMutableAllowEntry,
59
- collectLists: (scope) => [{
60
- pathLabel: `${scope.prefix}.allowFrom`,
61
- list: scope.account.allowFrom
62
- }, {
63
- pathLabel: `${scope.prefix}.groupAllowFrom`,
64
- list: scope.account.groupAllowFrom
65
- }]
65
+ collectLists: (scope) => (0, openclaw_plugin_sdk_channel_policy.collectStandardAllowlistLists)(scope)
66
66
  });
67
67
  //#endregion
68
68
  //#region extensions/msteams/src/policy.ts
69
+ const teamScopeKey = (teamKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey]);
70
+ const channelScopeKey = (teamKey, channelKey) => (0, openclaw_plugin_sdk_channel_policy.scopeKey)(["team", teamKey], ["channel", channelKey]);
71
+ function buildMSTeamsToolPolicyTree(teams) {
72
+ const scopes = {};
73
+ for (const [teamKey, team] of Object.entries(teams ?? {})) {
74
+ scopes[teamScopeKey(teamKey)] = {
75
+ tools: team.tools,
76
+ toolsBySender: team.toolsBySender
77
+ };
78
+ for (const [channelKey, channel] of Object.entries(team.channels ?? {})) scopes[channelScopeKey(teamKey, channelKey)] = {
79
+ tools: channel.tools,
80
+ toolsBySender: channel.toolsBySender
81
+ };
82
+ }
83
+ return { scopes };
84
+ }
85
+ function resolveMSTeamsToolPolicyScope(params) {
86
+ const teams = params.cfg.teams ?? {};
87
+ const tree = buildMSTeamsToolPolicyTree(teams);
88
+ const teamMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
89
+ entries: teams,
90
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(params.groupSpace?.trim()),
91
+ wildcardKey: "*",
92
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
93
+ });
94
+ const matchedTeamKey = teamMatch.matchKey ?? teamMatch.key;
95
+ if (teamMatch.entry && matchedTeamKey) {
96
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
97
+ entries: teamMatch.entry.channels ?? {},
98
+ keys: (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(params.groupId?.trim()),
99
+ wildcardKey: "*",
100
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
101
+ });
102
+ const matchedChannelKey = channelMatch.matchKey ?? channelMatch.key;
103
+ return {
104
+ tree,
105
+ path: [teamScopeKey(matchedTeamKey), ...channelMatch.entry && matchedChannelKey ? [channelScopeKey(matchedTeamKey, matchedChannelKey)] : []]
106
+ };
107
+ }
108
+ return {
109
+ tree,
110
+ path: []
111
+ };
112
+ }
113
+ function resolveMSTeamsCrossTeamScanScope(params) {
114
+ const teams = params.cfg.teams ?? {};
115
+ const tree = buildMSTeamsToolPolicyTree(teams);
116
+ const groupId = params.groupId?.trim();
117
+ if (!groupId) return {
118
+ tree,
119
+ path: []
120
+ };
121
+ const channelCandidates = (0, openclaw_plugin_sdk_channel_targets.buildChannelKeyCandidates)(groupId);
122
+ for (const [teamKey, team] of Object.entries(teams)) {
123
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
124
+ entries: team.channels ?? {},
125
+ keys: channelCandidates,
126
+ wildcardKey: "*",
127
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
128
+ });
129
+ const matchedChannelKey = channelMatch.matchKey ?? channelMatch.key;
130
+ if (channelMatch.entry && matchedChannelKey) return {
131
+ tree,
132
+ path: [teamScopeKey(teamKey), channelScopeKey(teamKey, matchedChannelKey)]
133
+ };
134
+ }
135
+ return {
136
+ tree,
137
+ path: []
138
+ };
139
+ }
69
140
  function resolveMSTeamsRouteConfig(params) {
70
141
  const teamId = params.teamId?.trim();
71
142
  const teamName = params.teamName?.trim();
@@ -73,27 +144,27 @@ function resolveMSTeamsRouteConfig(params) {
73
144
  const channelName = params.channelName?.trim();
74
145
  const teams = params.cfg?.teams ?? {};
75
146
  const allowlistConfigured = Object.keys(teams).length > 0;
76
- const teamMatch = resolveChannelEntryMatchWithFallback({
147
+ const teamMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
77
148
  entries: teams,
78
- keys: buildChannelKeyCandidates(teamId, params.allowNameMatching ? teamName : void 0, params.allowNameMatching && teamName ? normalizeChannelSlug(teamName) : void 0),
149
+ 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
150
  wildcardKey: "*",
80
- normalizeKey: normalizeChannelSlug
151
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
81
152
  });
82
153
  const teamConfig = teamMatch.entry;
83
154
  const channels = teamConfig?.channels ?? {};
84
155
  const channelAllowlistConfigured = Object.keys(channels).length > 0;
85
- const channelMatch = resolveChannelEntryMatchWithFallback({
156
+ const channelMatch = (0, openclaw_plugin_sdk_channel_targets.resolveChannelEntryMatchWithFallback)({
86
157
  entries: channels,
87
- keys: buildChannelKeyCandidates(conversationId, params.allowNameMatching ? channelName : void 0, params.allowNameMatching && channelName ? normalizeChannelSlug(channelName) : void 0),
158
+ 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
159
  wildcardKey: "*",
89
- normalizeKey: normalizeChannelSlug
160
+ normalizeKey: openclaw_plugin_sdk_channel_targets.normalizeChannelSlug
90
161
  });
91
162
  const channelConfig = channelMatch.entry;
92
163
  return {
93
164
  teamConfig,
94
165
  channelConfig,
95
166
  allowlistConfigured,
96
- allowed: resolveNestedAllowlistDecision({
167
+ allowed: (0, openclaw_plugin_sdk_channel_targets.resolveNestedAllowlistDecision)({
97
168
  outerConfigured: allowlistConfigured,
98
169
  outerMatched: Boolean(teamConfig),
99
170
  innerConfigured: channelAllowlistConfigured,
@@ -108,82 +179,33 @@ function resolveMSTeamsRouteConfig(params) {
108
179
  function resolveMSTeamsGroupToolPolicy(params) {
109
180
  const cfg = params.cfg.channels?.msteams;
110
181
  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({
182
+ const scope = resolveMSTeamsToolPolicyScope({
116
183
  cfg,
117
- teamId: groupSpace,
118
- teamName: groupSpace,
119
- conversationId: groupId,
120
- channelName: groupChannel,
121
- allowNameMatching
184
+ groupSpace: params.groupSpace,
185
+ groupId: params.groupId
186
+ });
187
+ const senderScope = {
188
+ senderId: params.senderId,
189
+ senderName: params.senderName,
190
+ senderUsername: params.senderUsername,
191
+ senderE164: params.senderE164
192
+ };
193
+ const resolved = (0, openclaw_plugin_sdk_channel_policy.resolveScopeToolsPolicy)({
194
+ ...scope,
195
+ ...senderScope
196
+ });
197
+ if (resolved !== void 0) return resolved;
198
+ if (scope.path.length > 1) return;
199
+ return (0, openclaw_plugin_sdk_channel_policy.resolveScopeToolsPolicy)({
200
+ ...resolveMSTeamsCrossTeamScanScope({
201
+ cfg,
202
+ groupId: params.groupId
203
+ }),
204
+ ...senderScope
122
205
  });
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
206
  }
185
207
  function resolveMSTeamsAllowlistMatch(params) {
186
- return resolveAllowlistMatchSimple(params);
208
+ return (0, openclaw_plugin_sdk_allow_from.resolveAllowlistMatchSimple)(params);
187
209
  }
188
210
  function resolveMSTeamsReplyPolicy(params) {
189
211
  if (params.isDirectMessage) return {
@@ -214,13 +236,13 @@ const MSTEAMS_PRESENTATION_CAPABILITIES = {
214
236
  };
215
237
  function buildMSTeamsPresentationCard(params) {
216
238
  const body = [];
217
- const text = normalizeOptionalString(params.text);
239
+ const text = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.text);
218
240
  if (text) body.push({
219
241
  type: "TextBlock",
220
242
  text,
221
243
  wrap: true
222
244
  });
223
- const presentation = adaptMessagePresentationForChannel({
245
+ const presentation = (0, openclaw_plugin_sdk_interactive_runtime.adaptMessagePresentationForChannel)({
224
246
  presentation: params.presentation,
225
247
  capabilities: MSTEAMS_PRESENTATION_CAPABILITIES
226
248
  });
@@ -255,21 +277,30 @@ function buildMSTeamsPresentationCard(params) {
255
277
  continue;
256
278
  }
257
279
  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) {
280
+ const action = (0, openclaw_plugin_sdk_interactive_runtime.resolveMessagePresentationButtonAction)(button);
281
+ if (action?.type === "url" || action?.type === "web-app") {
282
+ const url = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(action.url);
283
+ if (!url) continue;
260
284
  actions.push({
261
285
  type: "Action.OpenUrl",
262
286
  title: button.label,
263
- url: targetUrl
287
+ url
288
+ });
289
+ continue;
290
+ }
291
+ if (action?.type === "command") {
292
+ actions.push({
293
+ type: "Action.Submit",
294
+ title: button.label,
295
+ data: action.command
264
296
  });
265
297
  continue;
266
298
  }
267
- const value = resolveMessagePresentationControlValue(button);
268
- if (value) actions.push({
299
+ if (action?.type === "callback") actions.push({
269
300
  type: "Action.Submit",
270
301
  title: button.label,
271
- data: button.action?.type === "command" ? value : {
272
- value,
302
+ data: {
303
+ value: action.value,
273
304
  label: button.label
274
305
  }
275
306
  });
@@ -283,18 +314,231 @@ function buildMSTeamsPresentationCard(params) {
283
314
  };
284
315
  }
285
316
  //#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, "&");
317
+ //#region extensions/msteams/src/read-policy.ts
318
+ function normalizeTarget(raw) {
319
+ return raw ? require_resolve_allowlist.normalizeMSTeamsMessagingTarget(raw) ?? "" : "";
320
+ }
321
+ function sameAccount(ctx) {
322
+ const requested = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.accountId) ?? "default";
323
+ const requester = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.requesterAccountId);
324
+ return requester !== void 0 && requester === requested;
325
+ }
326
+ function isCurrentMSTeamsReadTarget(params) {
327
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.ctx.toolContext?.currentChannelProvider)?.toLowerCase() !== "msteams" || !sameAccount(params.ctx)) return false;
328
+ const candidates = [
329
+ params.ctx.toolContext?.currentChannelId,
330
+ params.ctx.toolContext?.currentMessagingTarget,
331
+ params.ctx.toolContext?.currentGraphChannelId
332
+ ];
333
+ const target = normalizeTarget(params.target);
334
+ return candidates.some((candidate) => normalizeTarget(candidate) === target);
335
+ }
336
+ function normalizeUserTarget(target) {
337
+ return target.replace(/^user:/i, "").trim().toLowerCase();
338
+ }
339
+ function isStableUserId(value) {
340
+ return /^[0-9a-f-]{16,}$/i.test(value);
341
+ }
342
+ async function resolveAllowedDmTarget(cfg, target) {
343
+ const teams = cfg.channels?.msteams;
344
+ if (teams?.dmPolicy === "disabled") return;
345
+ const userId = normalizeUserTarget(target);
346
+ if (!userId) return;
347
+ const normalizedEntries = (teams?.allowFrom ?? []).map((entry) => normalizeUserTarget(entry.replace(/^(msteams|teams):/i, "")));
348
+ const allowAll = (teams?.dmPolicy ?? "pairing") === "open" || normalizedEntries.includes("*");
349
+ if (isStableUserId(userId)) return allowAll || normalizedEntries.some((entry) => entry === userId) ? `user:${userId}` : void 0;
350
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)) return;
351
+ try {
352
+ const [resolvedTarget, ...resolvedEntries] = await require_resolve_allowlist.resolveMSTeamsUserAllowlist({
353
+ cfg,
354
+ entries: [userId, ...normalizedEntries.filter((entry) => entry !== "*")]
355
+ });
356
+ if (!resolvedTarget?.resolved || !resolvedTarget.id) return;
357
+ return allowAll || resolvedEntries.some((entry) => entry.resolved && entry.id?.toLowerCase() === resolvedTarget.id?.toLowerCase()) ? `user:${resolvedTarget.id}` : void 0;
358
+ } catch {
359
+ return;
360
+ }
361
+ }
362
+ async function resolveDirectDmTarget(cfg, target) {
363
+ if (cfg.channels?.msteams?.dmPolicy === "disabled") return;
364
+ const userId = normalizeUserTarget(target);
365
+ if (!userId) return;
366
+ if (isStableUserId(userId)) return `user:${userId}`;
367
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(cfg.channels?.msteams)) return;
368
+ try {
369
+ const [resolved] = await require_resolve_allowlist.resolveMSTeamsUserAllowlist({
370
+ cfg,
371
+ entries: [userId]
372
+ });
373
+ return resolved?.resolved && resolved.id ? `user:${resolved.id}` : void 0;
374
+ } catch {
375
+ return;
376
+ }
377
+ }
378
+ function resolveMSTeamsReadGroupPolicy(cfg) {
379
+ const teams = cfg.channels?.msteams;
380
+ return teams ? teams.groupPolicy ?? (0, openclaw_plugin_sdk_runtime_group_policy.resolveDefaultGroupPolicy)(cfg) ?? "allowlist" : "disabled";
381
+ }
382
+ function isStableChannelKey(value) {
383
+ return /^[0-9a-f-]{16,}$/i.test(value) || /^19:.+@thread\./i.test(value);
384
+ }
385
+ function isStableGraphTeamId(value) {
386
+ return /^[0-9a-f-]{16,}$/i.test(value);
387
+ }
388
+ function isStableGraphChannelTarget(target) {
389
+ const [teamId, channelId] = target.split("/", 2);
390
+ return Boolean(teamId && channelId && isStableGraphTeamId(teamId) && isStableChannelKey(channelId));
391
+ }
392
+ function hasMutableChannelConfig(cfg) {
393
+ const teams = cfg.channels?.msteams?.teams ?? {};
394
+ return Object.entries(teams).some(([teamKey, teamConfig]) => {
395
+ if (teamKey !== "*" && !isStableChannelKey(teamKey)) return true;
396
+ return Object.keys(teamConfig?.channels ?? {}).some((channelKey) => channelKey !== "*" && !isStableChannelKey(channelKey));
397
+ });
398
+ }
399
+ async function resolveConfiguredBotFrameworkTeamKey(cfg, graphTeamId) {
400
+ const configuredTeams = cfg.channels?.msteams?.teams;
401
+ if (!configuredTeams) return;
402
+ const stableConfiguredKeys = Object.keys(configuredTeams).filter((teamKey) => teamKey !== "*" && /^19:.+@thread\./i.test(teamKey));
403
+ if (stableConfiguredKeys.length === 0) return;
404
+ const channelResult = await require_resolve_allowlist.listChannelsForTeamWithPageInfo(await require_resolve_allowlist.resolveGraphToken(cfg), graphTeamId);
405
+ if (channelResult.truncated) return;
406
+ const channelIds = new Set(channelResult.items.map((channel) => channel.id?.trim()).filter((channelId) => Boolean(channelId)));
407
+ const matches = stableConfiguredKeys.filter((teamKey) => channelIds.has(teamKey));
408
+ return matches.length === 1 ? matches[0] : void 0;
409
+ }
410
+ async function resolveStableChannelTarget(cfg, target) {
411
+ if (isStableGraphChannelTarget(target)) return target;
412
+ if (!(0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(cfg.channels?.msteams)) return;
413
+ try {
414
+ const [resolved] = await require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
415
+ cfg,
416
+ entries: [target]
417
+ });
418
+ return resolved?.resolved && resolved.graphTeamId && resolved.channelId ? `${resolved.graphTeamId}/${resolved.channelId}` : void 0;
419
+ } catch {
420
+ return;
421
+ }
422
+ }
423
+ async function resolveAllowedChannelTarget(cfg, target) {
424
+ const teams = cfg.channels?.msteams;
425
+ const groupPolicy = resolveMSTeamsReadGroupPolicy(cfg);
426
+ if (groupPolicy === "disabled") return;
427
+ const [teamId, channelId] = target.split("/", 2);
428
+ if (!teamId || !channelId) return;
429
+ const directRoute = resolveMSTeamsRouteConfig({
430
+ cfg: teams,
431
+ teamId,
432
+ teamName: teamId,
433
+ conversationId: channelId,
434
+ channelName: channelId,
435
+ allowNameMatching: (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)
436
+ });
437
+ const stableTarget = await resolveStableChannelTarget(cfg, target);
438
+ if (directRoute.allowed) return stableTarget;
439
+ if (!directRoute.allowlistConfigured) return groupPolicy === "open" ? stableTarget : void 0;
440
+ if (!stableTarget || !teams?.teams) return;
441
+ const [stableTeamId, stableChannelId] = stableTarget.split("/", 2);
442
+ if (!stableTeamId || !stableChannelId) return;
443
+ try {
444
+ const botFrameworkTeamKey = await resolveConfiguredBotFrameworkTeamKey(cfg, stableTeamId);
445
+ if (botFrameworkTeamKey) {
446
+ if (resolveMSTeamsRouteConfig({
447
+ cfg: teams,
448
+ teamId: botFrameworkTeamKey,
449
+ conversationId: stableChannelId
450
+ }).allowed) return stableTarget;
451
+ }
452
+ if (!hasMutableChannelConfig(cfg)) return;
453
+ const resolved = await require_resolve_allowlist.resolveMSTeamsTeamsConfig({
454
+ cfg,
455
+ teamIdMode: "graph",
456
+ teams: teams.teams
457
+ });
458
+ return resolveMSTeamsRouteConfig({
459
+ cfg: {
460
+ ...teams,
461
+ teams: resolved.teams
462
+ },
463
+ teamId: stableTeamId,
464
+ conversationId: stableChannelId
465
+ }).allowed ? stableTarget : void 0;
466
+ } catch {
467
+ return;
468
+ }
469
+ }
470
+ function bothUnknownScopesAllowed(cfg) {
471
+ const teams = cfg.channels?.msteams;
472
+ return resolveMSTeamsReadGroupPolicy(cfg) === "open" && (teams?.dmPolicy ?? "pairing") === "open";
473
+ }
474
+ async function assertMSTeamsReadTargetAllowed(params) {
475
+ const target = normalizeTarget(params.target);
476
+ const isChannel = target.includes("/");
477
+ const isDm = /^user:/i.test(target);
478
+ const isChat = require_resolve_allowlist.looksLikeMSTeamsConversationId(target);
479
+ const current = isCurrentMSTeamsReadTarget({
480
+ ctx: params.ctx,
481
+ target
482
+ });
483
+ const directOperator = params.ctx.conversationReadOrigin === "direct-operator";
484
+ const currentChatType = params.ctx.toolContext?.currentChatType;
485
+ 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;
486
+ if (!allowedTarget) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams read target is not allowed.");
487
+ return allowedTarget;
292
488
  }
489
+ async function assertMSTeamsTeamEnumerationAllowed(params) {
490
+ const teams = params.cfg.channels?.msteams;
491
+ const groupPolicy = resolveMSTeamsReadGroupPolicy(params.cfg);
492
+ if (groupPolicy === "disabled") throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list is not allowed.");
493
+ const directRoute = resolveMSTeamsRouteConfig({
494
+ cfg: teams,
495
+ teamId: params.teamId,
496
+ teamName: params.teamId,
497
+ conversationId: "__openclaw_all_channels__",
498
+ allowNameMatching: (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams)
499
+ });
500
+ const stableTeamId = isStableGraphTeamId(params.teamId) ? params.teamId : (0, openclaw_plugin_sdk_dangerous_name_runtime.isDangerousNameMatchingEnabled)(teams) ? (await require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
501
+ cfg: params.cfg,
502
+ entries: [params.teamId]
503
+ }))[0]?.graphTeamId : void 0;
504
+ if (!stableTeamId) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list requires access to every channel in the team.");
505
+ if (params.ctx?.conversationReadOrigin === "direct-operator") return stableTeamId;
506
+ let allowed = directRoute.allowlistConfigured ? directRoute.allowed : groupPolicy === "open";
507
+ if (!allowed && teams?.teams) try {
508
+ const botFrameworkTeamKey = await resolveConfiguredBotFrameworkTeamKey(params.cfg, stableTeamId);
509
+ if (botFrameworkTeamKey) allowed = resolveMSTeamsRouteConfig({
510
+ cfg: teams,
511
+ teamId: botFrameworkTeamKey,
512
+ conversationId: "__openclaw_all_channels__"
513
+ }).allowed;
514
+ if (!allowed && hasMutableChannelConfig(params.cfg)) {
515
+ const resolved = await require_resolve_allowlist.resolveMSTeamsTeamsConfig({
516
+ cfg: params.cfg,
517
+ teamIdMode: "graph",
518
+ teams: teams.teams
519
+ });
520
+ allowed = resolveMSTeamsRouteConfig({
521
+ cfg: {
522
+ ...teams,
523
+ teams: resolved.teams
524
+ },
525
+ teamId: stableTeamId,
526
+ conversationId: "__openclaw_all_channels__"
527
+ }).allowed;
528
+ }
529
+ } catch {
530
+ allowed = false;
531
+ }
532
+ if (!allowed) throw new openclaw_plugin_sdk_channel_actions.ToolAuthorizationError("Microsoft Teams channel list requires access to every channel in the team.");
533
+ return stableTeamId;
534
+ }
535
+ //#endregion
536
+ //#region extensions/msteams/src/inbound.ts
293
537
  /**
294
538
  * Strip HTML tags, preserving text content.
295
539
  */
296
540
  function htmlToPlainText(html) {
297
- return decodeHtmlEntities(html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim());
541
+ return (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(html.replace(/<[^>]*>/g, " ")).replaceAll("\xA0", " ").replace(/\s+/g, " ").trim();
298
542
  }
299
543
  /**
300
544
  * Extract quote info from MS Teams HTML reply attachments.
@@ -312,11 +556,13 @@ function extractMSTeamsQuoteInfo(attachments) {
312
556
  if (!content.includes("http://schema.skype.com/Reply")) continue;
313
557
  const senderMatch = /<strong[^>]*itemprop=["']mri["'][^>]*>(.*?)<\/strong>/i.exec(content);
314
558
  const sender = senderMatch?.[1] ? htmlToPlainText(senderMatch[1]) : void 0;
315
- const bodyMatch = /<p[^>]*itemprop=["']copy["'][^>]*>(.*?)<\/p>/is.exec(content);
559
+ const bodyMatch = /<p[^>]*itemprop=["']copy["'][^>]*>(.*?)<\/p>/is.exec(content) ?? /<p[^>]*itemprop=["']preview["'][^>]*>(.*?)<\/p>/is.exec(content);
316
560
  const body = bodyMatch?.[1] ? htmlToPlainText(bodyMatch[1]) : void 0;
561
+ const id = /<blockquote[^>]*\bitemid=["']([^"']+)["'][^>]*>/is.exec(content)?.[1]?.trim() || void 0;
317
562
  if (body) return {
318
563
  sender: sender ?? "unknown",
319
- body
564
+ body,
565
+ ...id ? { id } : {}
320
566
  };
321
567
  }
322
568
  }
@@ -337,22 +583,6 @@ function parseMSTeamsActivityTimestamp(value) {
337
583
  function stripMSTeamsMentionTags(text) {
338
584
  return text.replace(/<at[^>]*>.*?<\/at>/gi, "").trim();
339
585
  }
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
586
  function wasMSTeamsBotMentioned(activity) {
357
587
  const botId = activity.recipient?.id;
358
588
  if (!botId) return false;
@@ -364,7 +594,7 @@ const TRAILING_THREAD_SUFFIX = /(?::thread:[^:]+)+$/;
364
594
  function resolveMSTeamsRouteSessionKey(params) {
365
595
  const channelThreadId = params.isChannel ? params.conversationMessageId ?? params.replyToId ?? void 0 : void 0;
366
596
  const cleanBase = params.baseSessionKey.replace(TRAILING_THREAD_SUFFIX, "");
367
- return resolveThreadSessionKeys({
597
+ return (0, openclaw_plugin_sdk_routing.resolveThreadSessionKeys)({
368
598
  baseSessionKey: cleanBase,
369
599
  threadId: channelThreadId,
370
600
  parentSessionKey: channelThreadId ? cleanBase : void 0
@@ -373,10 +603,10 @@ function resolveMSTeamsRouteSessionKey(params) {
373
603
  //#endregion
374
604
  //#region extensions/msteams/src/session-route.ts
375
605
  function resolveMSTeamsOutboundSessionRoute(params) {
376
- const trimmed = stripChannelTargetPrefix(params.target, "msteams", "teams");
606
+ const trimmed = (0, openclaw_plugin_sdk_channel_core.stripChannelTargetPrefix)(params.target, "msteams", "teams");
377
607
  if (!trimmed) return null;
378
- const isUser = normalizeLowercaseStringOrEmpty(trimmed).startsWith("user:");
379
- const rawId = stripTargetKindPrefix(trimmed);
608
+ const isUser = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(trimmed).startsWith("user:");
609
+ const rawId = (0, openclaw_plugin_sdk_channel_core.stripTargetKindPrefix)(trimmed);
380
610
  if (!rawId) return null;
381
611
  const conversationId = normalizeMSTeamsConversationId(rawId);
382
612
  const isChannel = !isUser && /@thread\.tacv2/i.test(conversationId);
@@ -386,7 +616,7 @@ function resolveMSTeamsOutboundSessionRoute(params) {
386
616
  const resolvedKind = params.resolvedTarget?.kind;
387
617
  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
618
  const recipientSessionExact = (isUser || resolvedKind === "user") && isCanonicalUserId || (isChannel ? channelThreadId !== void 0 : resolvedKind === "group");
389
- const route = buildChannelOutboundSessionRoute({
619
+ const route = (0, openclaw_plugin_sdk_channel_core.buildChannelOutboundSessionRoute)({
390
620
  cfg: params.cfg,
391
621
  agentId: params.agentId,
392
622
  channel: "msteams",
@@ -436,26 +666,26 @@ const MSTEAMS_GROUP_MANAGEMENT_ACTIONS = /* @__PURE__ */ new Set([
436
666
  "removeParticipant",
437
667
  "renameGroup"
438
668
  ]);
439
- const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarningCollector({
669
+ const collectMSTeamsSecurityWarnings = (0, openclaw_plugin_sdk_channel_policy.createAllowlistProviderGroupPolicyWarningCollector)({
440
670
  providerConfigPresent: (cfg) => cfg.channels?.msteams !== void 0,
441
671
  resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
442
672
  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
673
  });
444
- const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-Bwu6Tjhf.js"), "msTeamsChannelRuntime");
674
+ const loadMSTeamsChannelRuntime = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeNamedExport)(() => Promise.resolve().then(() => require("./channel.runtime-hd1Zsoo2.cjs")), "msTeamsChannelRuntime");
445
675
  const resolveMSTeamsChannelConfig = (cfg) => ({
446
676
  allowFrom: cfg.channels?.msteams?.allowFrom,
447
677
  defaultTo: cfg.channels?.msteams?.defaultTo
448
678
  });
449
- const msteamsConfigAdapter = createTopLevelChannelConfigAdapter({
679
+ const msteamsConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createTopLevelChannelConfigAdapter)({
450
680
  sectionKey: "msteams",
451
681
  resolveAccount: (cfg) => ({
452
- accountId: DEFAULT_ACCOUNT_ID,
682
+ accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
453
683
  enabled: cfg.channels?.msteams?.enabled !== false,
454
- configured: Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams))
684
+ configured: Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams))
455
685
  }),
456
686
  resolveAccessorAccount: ({ cfg }) => resolveMSTeamsChannelConfig(cfg),
457
687
  resolveAllowFrom: (account) => account.allowFrom,
458
- formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
688
+ formatAllowFrom: (allowFrom) => (0, openclaw_plugin_sdk_allow_from.formatAllowFromLowercase)({ allowFrom }),
459
689
  resolveDefaultTo: (account) => account.defaultTo
460
690
  });
461
691
  function jsonActionResult(data) {
@@ -526,17 +756,28 @@ function requireMSTeamsGroupManagementAuthorization(ctx) {
526
756
  function resolveActionTarget(params, currentChannelId) {
527
757
  return typeof params.to === "string" ? params.to.trim() : typeof params.target === "string" ? params.target.trim() : currentChannelId?.trim() ?? "";
528
758
  }
529
- function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelId) {
530
- return resolveActionTarget(params, currentGraphChannelId ?? currentChannelId);
759
+ function resolveGraphActionTarget(params, currentChannelId, currentGraphChannelId, currentChatType) {
760
+ const explicitTarget = resolveActionTarget(params);
761
+ const currentChannelTarget = currentChannelId?.trim();
762
+ const currentGraphTarget = currentGraphChannelId?.trim();
763
+ if (explicitTarget) {
764
+ if (currentChatType === "channel" && currentGraphTarget && currentChannelTarget && explicitTarget === currentChannelTarget) return currentGraphTarget;
765
+ return explicitTarget;
766
+ }
767
+ if (currentGraphTarget) return currentGraphTarget;
768
+ return currentChatType === "channel" ? "" : currentChannelTarget ?? "";
769
+ }
770
+ function resolveCurrentGraphActionTarget(toolContext) {
771
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentGraphChannelId) ?? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentMessagingTarget);
531
772
  }
532
773
  function resolveActionMessageId(params) {
533
- return normalizeOptionalString(params.messageId) ?? "";
774
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.messageId) ?? "";
534
775
  }
535
776
  function resolveActionPinnedMessageId(params) {
536
777
  return typeof params.pinnedMessageId === "string" ? params.pinnedMessageId.trim() : typeof params.messageId === "string" ? params.messageId.trim() : "";
537
778
  }
538
779
  function resolveActionQuery(params) {
539
- return normalizeOptionalString(params.query) ?? "";
780
+ return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(params.query) ?? "";
540
781
  }
541
782
  function resolveActionContent(params) {
542
783
  return typeof params.text === "string" ? params.text : typeof params.content === "string" ? params.content : typeof params.message === "string" ? params.message : "";
@@ -555,12 +796,12 @@ function resolveActionUploadFilePath(params) {
555
796
  }
556
797
  }
557
798
  function resolveRequiredActionTarget(params) {
558
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
799
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
559
800
  if (!to) return actionError(`${params.actionLabel} requires a target (to).`);
560
801
  return to;
561
802
  }
562
803
  function resolveRequiredActionMessageTarget(params) {
563
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
804
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
564
805
  const messageId = resolveActionMessageId(params.toolParams);
565
806
  if (!to || !messageId) return actionError(`${params.actionLabel} requires a target (to) and messageId.`);
566
807
  return {
@@ -569,7 +810,7 @@ function resolveRequiredActionMessageTarget(params) {
569
810
  };
570
811
  }
571
812
  function resolveRequiredActionPinnedMessageTarget(params) {
572
- const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId) : resolveActionTarget(params.toolParams, params.currentChannelId);
813
+ const to = params.graphOnly ? resolveGraphActionTarget(params.toolParams, params.currentChannelId, params.currentGraphChannelId, params.currentChatType) : resolveActionTarget(params.toolParams, params.currentChannelId);
573
814
  const pinnedMessageId = resolveActionPinnedMessageId(params.toolParams);
574
815
  if (!to || !pinnedMessageId) return actionError(`${params.actionLabel} requires a target (to) and pinnedMessageId.`);
575
816
  return {
@@ -583,6 +824,7 @@ async function runWithRequiredActionTarget(params) {
583
824
  toolParams: params.toolParams,
584
825
  currentChannelId: params.currentChannelId,
585
826
  currentGraphChannelId: params.currentGraphChannelId,
827
+ currentChatType: params.currentChatType,
586
828
  graphOnly: params.graphOnly
587
829
  });
588
830
  if (typeof to !== "string") return to;
@@ -594,6 +836,7 @@ async function runWithRequiredActionMessageTarget(params) {
594
836
  toolParams: params.toolParams,
595
837
  currentChannelId: params.currentChannelId,
596
838
  currentGraphChannelId: params.currentGraphChannelId,
839
+ currentChatType: params.currentChatType,
597
840
  graphOnly: params.graphOnly
598
841
  });
599
842
  if ("isError" in target) return target;
@@ -605,13 +848,14 @@ async function runWithRequiredActionPinnedMessageTarget(params) {
605
848
  toolParams: params.toolParams,
606
849
  currentChannelId: params.currentChannelId,
607
850
  currentGraphChannelId: params.currentGraphChannelId,
851
+ currentChatType: params.currentChatType,
608
852
  graphOnly: params.graphOnly
609
853
  });
610
854
  if ("isError" in target) return target;
611
855
  return await params.run(target);
612
856
  }
613
857
  function describeMSTeamsMessageTool({ cfg }) {
614
- const enabled = cfg.channels?.msteams?.enabled !== false && Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams));
858
+ const enabled = cfg.channels?.msteams?.enabled !== false && Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams));
615
859
  return {
616
860
  actions: enabled ? [
617
861
  "upload-file",
@@ -635,13 +879,13 @@ function describeMSTeamsMessageTool({ cfg }) {
635
879
  capabilities: enabled ? ["presentation"] : [],
636
880
  schema: enabled ? {
637
881
  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)." })) }
882
+ 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
883
  } : null
640
884
  };
641
885
  }
642
886
  const msteamsChannelOutbound = {
643
887
  deliveryMode: "direct",
644
- chunker: chunkTextForOutbound,
888
+ chunker: openclaw_plugin_sdk_text_chunking.chunkTextForOutbound,
645
889
  chunkerMode: "markdown",
646
890
  textChunkLimit: 4e3,
647
891
  pollMaxOptions: 12,
@@ -652,7 +896,7 @@ const msteamsChannelOutbound = {
652
896
  messageSendingHooks: true
653
897
  } },
654
898
  presentationCapabilities: MSTEAMS_PRESENTATION_CAPABILITIES,
655
- ...createRuntimeOutboundDelegates({
899
+ ...(0, openclaw_plugin_sdk_channel_outbound.createRuntimeOutboundDelegates)({
656
900
  getRuntime: loadMSTeamsChannelRuntime,
657
901
  renderPresentation: { resolve: (runtime) => runtime.msteamsOutbound.renderPresentation },
658
902
  sendPayload: { resolve: (runtime) => runtime.msteamsOutbound.sendPayload },
@@ -661,7 +905,7 @@ const msteamsChannelOutbound = {
661
905
  sendPoll: { resolve: (runtime) => runtime.msteamsOutbound.sendPoll }
662
906
  })
663
907
  };
664
- const msteamsMessageAdapter = createChannelMessageAdapterFromOutbound({
908
+ const msteamsMessageAdapter = (0, openclaw_plugin_sdk_channel_outbound.createChannelMessageAdapterFromOutbound)({
665
909
  id: "msteams",
666
910
  outbound: msteamsChannelOutbound,
667
911
  live: {
@@ -678,14 +922,14 @@ const msteamsMessageAdapter = createChannelMessageAdapterFromOutbound({
678
922
  } }
679
923
  }
680
924
  });
681
- const msteamsPlugin = createChatChannelPlugin({
925
+ const msteamsPlugin = (0, openclaw_plugin_sdk_channel_core.createChatChannelPlugin)({
682
926
  base: {
683
927
  id: "msteams",
684
928
  meta: {
685
929
  ...meta,
686
930
  aliases: [...meta.aliases]
687
931
  },
688
- setupWizard: msteamsSetupWizard,
932
+ setupWizard: require_setup_surface.msteamsSetupWizard,
689
933
  capabilities: {
690
934
  chatTypes: [
691
935
  "direct",
@@ -703,11 +947,11 @@ const msteamsPlugin = createChatChannelPlugin({
703
947
  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
948
  groups: { resolveToolPolicy: resolveMSTeamsGroupToolPolicy },
705
949
  reload: { configPrefixes: ["channels.msteams"] },
706
- configSchema: MSTeamsChannelConfigSchema,
950
+ configSchema: require_config_schema.MSTeamsChannelConfigSchema,
707
951
  config: {
708
952
  ...msteamsConfigAdapter,
709
- isConfigured: (_account, cfg) => Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams)),
710
- describeAccount: (account) => describeAccountSnapshot({
953
+ isConfigured: (_account, cfg) => Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams)),
954
+ describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
711
955
  account,
712
956
  configured: account.configured
713
957
  })
@@ -720,20 +964,21 @@ const msteamsPlugin = createChatChannelPlugin({
720
964
  warnOnEmptyGroupSenderAllowlist: true,
721
965
  collectMutableAllowlistWarnings: collectMSTeamsMutableAllowlistWarnings
722
966
  },
723
- setup: msteamsSetupAdapter,
967
+ setup: require_setup_surface.msteamsSetupAdapter,
724
968
  messaging: {
725
969
  targetPrefixes: ["msteams", "teams"],
726
- normalizeTarget: normalizeMSTeamsMessagingTarget,
970
+ directTargetStyle: "user-prefixed",
971
+ normalizeTarget: require_resolve_allowlist.normalizeMSTeamsMessagingTarget,
727
972
  resolveOutboundSessionRoute: (params) => resolveMSTeamsOutboundSessionRoute(params),
728
973
  targetResolver: {
729
- looksLikeId: (raw) => looksLikeMSTeamsTargetId(raw),
974
+ looksLikeId: (raw) => require_resolve_allowlist.looksLikeMSTeamsTargetId(raw),
730
975
  hint: "<conversationId|user:ID|conversation:ID>"
731
976
  }
732
977
  },
733
978
  message: msteamsMessageAdapter,
734
- directory: createChannelDirectoryAdapter({
979
+ directory: (0, openclaw_plugin_sdk_directory_runtime.createChannelDirectoryAdapter)({
735
980
  self: async ({ cfg }) => {
736
- const creds = resolveMSTeamsCredentials(cfg.channels?.msteams);
981
+ const creds = require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams);
737
982
  if (!creds) return null;
738
983
  return {
739
984
  kind: "user",
@@ -741,26 +986,26 @@ const msteamsPlugin = createChatChannelPlugin({
741
986
  name: creds.appId
742
987
  };
743
988
  },
744
- listPeers: async ({ cfg, query, limit }) => listDirectoryEntriesFromSources({
989
+ listPeers: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
745
990
  kind: "user",
746
991
  sources: [cfg.channels?.msteams?.allowFrom ?? [], Object.keys(cfg.channels?.msteams?.dms ?? {})],
747
992
  query,
748
993
  limit,
749
994
  normalizeId: (raw) => {
750
- const normalized = normalizeMSTeamsMessagingTarget(raw) ?? raw;
995
+ const normalized = require_resolve_allowlist.normalizeMSTeamsMessagingTarget(raw) ?? raw;
751
996
  const lowered = normalized.toLowerCase();
752
997
  if (lowered.startsWith("user:") || lowered.startsWith("conversation:")) return normalized;
753
998
  return `user:${normalized}`;
754
999
  }
755
1000
  }),
756
- listGroups: async ({ cfg, query, limit }) => listDirectoryEntriesFromSources({
1001
+ listGroups: async ({ cfg, query, limit }) => (0, openclaw_plugin_sdk_directory_runtime.listDirectoryEntriesFromSources)({
757
1002
  kind: "group",
758
1003
  sources: [Object.values(cfg.channels?.msteams?.teams ?? {}).flatMap((team) => Object.keys(team.channels ?? {}))],
759
1004
  query,
760
1005
  limit,
761
1006
  normalizeId: (raw) => `conversation:${raw.replace(/^conversation:/i, "").trim()}`
762
1007
  }),
763
- ...createRuntimeDirectoryLiveAdapter({
1008
+ ...(0, openclaw_plugin_sdk_directory_runtime.createRuntimeDirectoryLiveAdapter)({
764
1009
  getRuntime: loadMSTeamsChannelRuntime,
765
1010
  listPeersLive: (runtime) => runtime.listMSTeamsDirectoryPeersLive,
766
1011
  listGroupsLive: (runtime) => runtime.listMSTeamsDirectoryGroupsLive
@@ -774,7 +1019,7 @@ const msteamsPlugin = createChatChannelPlugin({
774
1019
  name: void 0,
775
1020
  note: void 0
776
1021
  }));
777
- const stripPrefix = (value) => normalizeMSTeamsUserInput(value);
1022
+ const stripPrefix = (value) => require_resolve_allowlist.normalizeMSTeamsUserInput(value);
778
1023
  const markPendingLookupFailed = (pending) => {
779
1024
  pending.forEach(({ index }) => {
780
1025
  const entry = results[index];
@@ -814,7 +1059,7 @@ const msteamsPlugin = createChatChannelPlugin({
814
1059
  index
815
1060
  });
816
1061
  });
817
- await resolvePending(pending, (entries) => resolveMSTeamsUserAllowlist({
1062
+ await resolvePending(pending, (entries) => require_resolve_allowlist.resolveMSTeamsUserAllowlist({
818
1063
  cfg,
819
1064
  entries
820
1065
  }), (target, entry) => {
@@ -832,14 +1077,14 @@ const msteamsPlugin = createChatChannelPlugin({
832
1077
  entry.note = "empty input";
833
1078
  return;
834
1079
  }
835
- const conversationId = parseMSTeamsConversationId(trimmed);
1080
+ const conversationId = require_resolve_allowlist.parseMSTeamsConversationId(trimmed);
836
1081
  if (conversationId !== null) {
837
1082
  entry.resolved = Boolean(conversationId);
838
1083
  entry.id = conversationId || void 0;
839
1084
  entry.note = conversationId ? "conversation id" : "empty conversation id";
840
1085
  return;
841
1086
  }
842
- const parsed = parseMSTeamsTeamChannelInput(trimmed);
1087
+ const parsed = require_resolve_allowlist.parseMSTeamsTeamChannelInput(trimmed);
843
1088
  if (!parsed.team) {
844
1089
  entry.note = "missing team";
845
1090
  return;
@@ -851,7 +1096,7 @@ const msteamsPlugin = createChatChannelPlugin({
851
1096
  index
852
1097
  });
853
1098
  });
854
- await resolvePending(pending, (entries) => resolveMSTeamsChannelAllowlist({
1099
+ await resolvePending(pending, (entries) => require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
855
1100
  cfg,
856
1101
  entries
857
1102
  }), (target, entry) => {
@@ -875,13 +1120,13 @@ const msteamsPlugin = createChatChannelPlugin({
875
1120
  } },
876
1121
  actions: {
877
1122
  describeMessageTool: describeMSTeamsMessageTool,
878
- requiresTrustedRequesterSender: ({ action, toolContext }) => normalizeOptionalString(toolContext?.currentChannelProvider)?.toLowerCase() === "msteams" && MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(action),
1123
+ requiresTrustedRequesterSender: ({ action, toolContext }) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(toolContext?.currentChannelProvider)?.toLowerCase() === "msteams" && MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(action),
879
1124
  handleAction: async (ctx) => {
880
1125
  if (MSTEAMS_GROUP_MANAGEMENT_ACTIONS.has(ctx.action)) {
881
1126
  const authError = requireMSTeamsGroupManagementAuthorization(ctx);
882
1127
  if (authError) return authError;
883
1128
  }
884
- const presentation = ctx.action === "send" ? normalizeMessagePresentation(ctx.params.presentation) : void 0;
1129
+ const presentation = ctx.action === "send" ? (0, openclaw_plugin_sdk_interactive_runtime.normalizeMessagePresentation)(ctx.params.presentation) : void 0;
885
1130
  if (ctx.action === "send" && presentation) {
886
1131
  const card = buildMSTeamsPresentationCard({
887
1132
  presentation,
@@ -952,10 +1197,15 @@ const msteamsPlugin = createChatChannelPlugin({
952
1197
  toolParams: ctx.params,
953
1198
  currentChannelId: ctx.toolContext?.currentChannelId,
954
1199
  run: async (target) => {
1200
+ const to = await assertMSTeamsReadTargetAllowed({
1201
+ cfg: ctx.cfg,
1202
+ ctx,
1203
+ target: target.to
1204
+ });
955
1205
  const { editMessageMSTeams } = await loadMSTeamsChannelRuntime();
956
1206
  return jsonMSTeamsConversationResult((await editMessageMSTeams({
957
1207
  cfg: ctx.cfg,
958
- to: target.to,
1208
+ to,
959
1209
  activityId: target.messageId,
960
1210
  text: content
961
1211
  })).conversationId);
@@ -967,10 +1217,15 @@ const msteamsPlugin = createChatChannelPlugin({
967
1217
  toolParams: ctx.params,
968
1218
  currentChannelId: ctx.toolContext?.currentChannelId,
969
1219
  run: async (target) => {
1220
+ const to = await assertMSTeamsReadTargetAllowed({
1221
+ cfg: ctx.cfg,
1222
+ ctx,
1223
+ target: target.to
1224
+ });
970
1225
  const { deleteMessageMSTeams } = await loadMSTeamsChannelRuntime();
971
1226
  return jsonMSTeamsConversationResult((await deleteMessageMSTeams({
972
1227
  cfg: ctx.cfg,
973
- to: target.to,
1228
+ to,
974
1229
  activityId: target.messageId
975
1230
  })).conversationId);
976
1231
  }
@@ -979,13 +1234,19 @@ const msteamsPlugin = createChatChannelPlugin({
979
1234
  actionLabel: "Read",
980
1235
  toolParams: ctx.params,
981
1236
  currentChannelId: ctx.toolContext?.currentChannelId,
982
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1237
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1238
+ currentChatType: ctx.toolContext?.currentChatType,
983
1239
  graphOnly: true,
984
1240
  run: async (target) => {
1241
+ const to = await assertMSTeamsReadTargetAllowed({
1242
+ cfg: ctx.cfg,
1243
+ ctx,
1244
+ target: target.to
1245
+ });
985
1246
  const { getMessageMSTeams } = await loadMSTeamsChannelRuntime();
986
1247
  return jsonMSTeamsOkActionResult("read", { message: await getMessageMSTeams({
987
1248
  cfg: ctx.cfg,
988
- to: target.to,
1249
+ to,
989
1250
  messageId: target.messageId
990
1251
  }) });
991
1252
  }
@@ -994,13 +1255,19 @@ const msteamsPlugin = createChatChannelPlugin({
994
1255
  actionLabel: "Pin",
995
1256
  toolParams: ctx.params,
996
1257
  currentChannelId: ctx.toolContext?.currentChannelId,
997
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1258
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1259
+ currentChatType: ctx.toolContext?.currentChatType,
998
1260
  graphOnly: true,
999
1261
  run: async (target) => {
1262
+ const to = await assertMSTeamsReadTargetAllowed({
1263
+ cfg: ctx.cfg,
1264
+ ctx,
1265
+ target: target.to
1266
+ });
1000
1267
  const { pinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1001
1268
  return jsonMSTeamsActionResult("pin", await pinMessageMSTeams({
1002
1269
  cfg: ctx.cfg,
1003
- to: target.to,
1270
+ to,
1004
1271
  messageId: target.messageId
1005
1272
  }));
1006
1273
  }
@@ -1009,13 +1276,19 @@ const msteamsPlugin = createChatChannelPlugin({
1009
1276
  actionLabel: "Unpin",
1010
1277
  toolParams: ctx.params,
1011
1278
  currentChannelId: ctx.toolContext?.currentChannelId,
1012
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1279
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1280
+ currentChatType: ctx.toolContext?.currentChatType,
1013
1281
  graphOnly: true,
1014
1282
  run: async (target) => {
1283
+ const to = await assertMSTeamsReadTargetAllowed({
1284
+ cfg: ctx.cfg,
1285
+ ctx,
1286
+ target: target.to
1287
+ });
1015
1288
  const { unpinMessageMSTeams } = await loadMSTeamsChannelRuntime();
1016
1289
  return jsonMSTeamsActionResult("unpin", await unpinMessageMSTeams({
1017
1290
  cfg: ctx.cfg,
1018
- to: target.to,
1291
+ to,
1019
1292
  pinnedMessageId: target.pinnedMessageId
1020
1293
  }));
1021
1294
  }
@@ -1024,13 +1297,19 @@ const msteamsPlugin = createChatChannelPlugin({
1024
1297
  actionLabel: "List-pins",
1025
1298
  toolParams: ctx.params,
1026
1299
  currentChannelId: ctx.toolContext?.currentChannelId,
1027
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1300
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1301
+ currentChatType: ctx.toolContext?.currentChatType,
1028
1302
  graphOnly: true,
1029
1303
  run: async (to) => {
1304
+ const allowedTarget = await assertMSTeamsReadTargetAllowed({
1305
+ cfg: ctx.cfg,
1306
+ ctx,
1307
+ target: to
1308
+ });
1030
1309
  const { listPinsMSTeams } = await loadMSTeamsChannelRuntime();
1031
1310
  return jsonMSTeamsOkActionResult("list-pins", await listPinsMSTeams({
1032
1311
  cfg: ctx.cfg,
1033
- to
1312
+ to: allowedTarget
1034
1313
  }));
1035
1314
  }
1036
1315
  });
@@ -1038,7 +1317,8 @@ const msteamsPlugin = createChatChannelPlugin({
1038
1317
  actionLabel: "React",
1039
1318
  toolParams: ctx.params,
1040
1319
  currentChannelId: ctx.toolContext?.currentChannelId,
1041
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1320
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1321
+ currentChatType: ctx.toolContext?.currentChatType,
1042
1322
  graphOnly: true,
1043
1323
  run: async (target) => {
1044
1324
  const emoji = typeof ctx.params.emoji === "string" ? ctx.params.emoji.trim() : "";
@@ -1054,6 +1334,11 @@ const msteamsPlugin = createChatChannelPlugin({
1054
1334
  validTypes: [...MSTEAMS_REACTION_TYPES]
1055
1335
  }
1056
1336
  };
1337
+ const to = await assertMSTeamsReadTargetAllowed({
1338
+ cfg: ctx.cfg,
1339
+ ctx,
1340
+ target: target.to
1341
+ });
1057
1342
  if (remove) {
1058
1343
  const { unreactMessageMSTeams } = await loadMSTeamsChannelRuntime();
1059
1344
  return jsonMSTeamsActionResult("react", {
@@ -1061,7 +1346,7 @@ const msteamsPlugin = createChatChannelPlugin({
1061
1346
  reactionType: emoji,
1062
1347
  ...await unreactMessageMSTeams({
1063
1348
  cfg: ctx.cfg,
1064
- to: target.to,
1349
+ to,
1065
1350
  messageId: target.messageId,
1066
1351
  reactionType: emoji
1067
1352
  })
@@ -1072,7 +1357,7 @@ const msteamsPlugin = createChatChannelPlugin({
1072
1357
  reactionType: emoji,
1073
1358
  ...await reactMessageMSTeams({
1074
1359
  cfg: ctx.cfg,
1075
- to: target.to,
1360
+ to,
1076
1361
  messageId: target.messageId,
1077
1362
  reactionType: emoji
1078
1363
  })
@@ -1083,13 +1368,19 @@ const msteamsPlugin = createChatChannelPlugin({
1083
1368
  actionLabel: "Reactions",
1084
1369
  toolParams: ctx.params,
1085
1370
  currentChannelId: ctx.toolContext?.currentChannelId,
1086
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1371
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1372
+ currentChatType: ctx.toolContext?.currentChatType,
1087
1373
  graphOnly: true,
1088
1374
  run: async (target) => {
1375
+ const to = await assertMSTeamsReadTargetAllowed({
1376
+ cfg: ctx.cfg,
1377
+ ctx,
1378
+ target: target.to
1379
+ });
1089
1380
  const { listReactionsMSTeams } = await loadMSTeamsChannelRuntime();
1090
1381
  return jsonMSTeamsOkActionResult("reactions", await listReactionsMSTeams({
1091
1382
  cfg: ctx.cfg,
1092
- to: target.to,
1383
+ to,
1093
1384
  messageId: target.messageId
1094
1385
  }));
1095
1386
  }
@@ -1098,9 +1389,15 @@ const msteamsPlugin = createChatChannelPlugin({
1098
1389
  actionLabel: "Search",
1099
1390
  toolParams: ctx.params,
1100
1391
  currentChannelId: ctx.toolContext?.currentChannelId,
1101
- currentGraphChannelId: ctx.toolContext?.currentGraphChannelId,
1392
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1393
+ currentChatType: ctx.toolContext?.currentChatType,
1102
1394
  graphOnly: true,
1103
1395
  run: async (to) => {
1396
+ const allowedTarget = await assertMSTeamsReadTargetAllowed({
1397
+ cfg: ctx.cfg,
1398
+ ctx,
1399
+ target: to
1400
+ });
1104
1401
  const query = resolveActionQuery(ctx.params);
1105
1402
  if (!query) return actionError("Search requires a target (to) and query.");
1106
1403
  const limit = typeof ctx.params.limit === "number" ? ctx.params.limit : void 0;
@@ -1108,7 +1405,7 @@ const msteamsPlugin = createChatChannelPlugin({
1108
1405
  const { searchMessagesMSTeams } = await loadMSTeamsChannelRuntime();
1109
1406
  return jsonMSTeamsOkActionResult("search", await searchMessagesMSTeams({
1110
1407
  cfg: ctx.cfg,
1111
- to,
1408
+ to: allowedTarget,
1112
1409
  query,
1113
1410
  from: from || void 0,
1114
1411
  limit
@@ -1116,32 +1413,64 @@ const msteamsPlugin = createChatChannelPlugin({
1116
1413
  }
1117
1414
  });
1118
1415
  if (ctx.action === "member-info") {
1119
- const userId = normalizeOptionalString(ctx.params.userId) ?? "";
1416
+ const userId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.userId) ?? "";
1120
1417
  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
- }));
1418
+ return await runWithRequiredActionTarget({
1419
+ actionLabel: "member-info",
1420
+ toolParams: ctx.params,
1421
+ currentChannelId: ctx.toolContext?.currentChannelId,
1422
+ currentGraphChannelId: resolveCurrentGraphActionTarget(ctx.toolContext),
1423
+ currentChatType: ctx.toolContext?.currentChatType,
1424
+ graphOnly: true,
1425
+ run: async (target) => {
1426
+ const to = await assertMSTeamsReadTargetAllowed({
1427
+ cfg: ctx.cfg,
1428
+ ctx,
1429
+ target
1430
+ });
1431
+ const currentRequesterId = isCurrentMSTeamsReadTarget({
1432
+ ctx,
1433
+ target: to
1434
+ }) ? ctx.requesterSenderId : void 0;
1435
+ const { getMemberInfoMSTeams } = await loadMSTeamsChannelRuntime();
1436
+ return jsonMSTeamsOkActionResult("member-info", await getMemberInfoMSTeams({
1437
+ cfg: ctx.cfg,
1438
+ to,
1439
+ userId,
1440
+ currentRequesterId
1441
+ }));
1442
+ }
1443
+ });
1126
1444
  }
1127
1445
  if (ctx.action === "channel-list") {
1128
- const teamId = normalizeOptionalString(ctx.params.teamId) ?? "";
1446
+ const teamId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.teamId) ?? "";
1129
1447
  if (!teamId) return actionError("channel-list requires a teamId.");
1448
+ const graphTeamId = await assertMSTeamsTeamEnumerationAllowed({
1449
+ cfg: ctx.cfg,
1450
+ ctx,
1451
+ teamId
1452
+ });
1130
1453
  const { listChannelsMSTeams } = await loadMSTeamsChannelRuntime();
1131
1454
  return jsonMSTeamsOkActionResult("channel-list", await listChannelsMSTeams({
1132
1455
  cfg: ctx.cfg,
1133
- teamId
1456
+ teamId: graphTeamId
1134
1457
  }));
1135
1458
  }
1136
1459
  if (ctx.action === "channel-info") {
1137
- const teamId = normalizeOptionalString(ctx.params.teamId) ?? "";
1138
- const channelId = normalizeOptionalString(ctx.params.channelId) ?? "";
1460
+ const teamId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.teamId) ?? "";
1461
+ const channelId = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(ctx.params.channelId) ?? "";
1139
1462
  if (!teamId || !channelId) return actionError("channel-info requires teamId and channelId.");
1463
+ const [graphTeamId, graphChannelId] = (await assertMSTeamsReadTargetAllowed({
1464
+ cfg: ctx.cfg,
1465
+ ctx,
1466
+ target: `${teamId}/${channelId}`
1467
+ })).split("/", 2);
1468
+ if (!graphTeamId || !graphChannelId) throw new Error("Authorized Microsoft Teams channel target is invalid.");
1140
1469
  const { getChannelInfoMSTeams } = await loadMSTeamsChannelRuntime();
1141
1470
  return jsonMSTeamsOkActionResult("channel-info", { channelInfo: (await getChannelInfoMSTeams({
1142
1471
  cfg: ctx.cfg,
1143
- teamId,
1144
- channelId
1472
+ teamId: graphTeamId,
1473
+ channelId: graphChannelId
1145
1474
  })).channel });
1146
1475
  }
1147
1476
  if (ctx.action === "addParticipant") {
@@ -1200,9 +1529,9 @@ const msteamsPlugin = createChatChannelPlugin({
1200
1529
  return null;
1201
1530
  }
1202
1531
  },
1203
- status: createComputedAccountStatusAdapter({
1204
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID, { port: null }),
1205
- buildChannelSummary: ({ snapshot }) => buildProbeChannelStatusSummary(snapshot, { port: snapshot.port ?? null }),
1532
+ status: (0, openclaw_plugin_sdk_status_helpers.createComputedAccountStatusAdapter)({
1533
+ defaultRuntime: (0, openclaw_plugin_sdk_channel_status.createDefaultChannelRuntimeState)(openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID, { port: null }),
1534
+ buildChannelSummary: ({ snapshot }) => (0, openclaw_plugin_sdk_channel_status.buildProbeChannelStatusSummary)(snapshot, { port: snapshot.port ?? null }),
1206
1535
  probeAccount: async ({ cfg }) => await (await loadMSTeamsChannelRuntime()).probeMSTeams(cfg.channels?.msteams),
1207
1536
  formatCapabilitiesProbe: ({ probe }) => {
1208
1537
  const teamsProbe = probe;
@@ -1211,8 +1540,8 @@ const msteamsPlugin = createChatChannelPlugin({
1211
1540
  if (appId) lines.push({ text: `App: ${appId}` });
1212
1541
  const graph = teamsProbe?.graph;
1213
1542
  if (graph) {
1214
- const roles = Array.isArray(graph.roles) ? normalizeStringEntries(graph.roles) : [];
1215
- const scopes = Array.isArray(graph.scopes) ? normalizeStringEntries(graph.scopes) : [];
1543
+ const roles = Array.isArray(graph.roles) ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeStringEntries)(graph.roles) : [];
1544
+ const scopes = Array.isArray(graph.scopes) ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeStringEntries)(graph.scopes) : [];
1216
1545
  const formatPermission = (permission) => {
1217
1546
  const hint = TEAMS_GRAPH_PERMISSION_HINTS[permission];
1218
1547
  return hint ? `${permission} (${hint})` : permission;
@@ -1236,7 +1565,7 @@ const msteamsPlugin = createChatChannelPlugin({
1236
1565
  })
1237
1566
  }),
1238
1567
  gateway: { startAccount: async (ctx) => {
1239
- const { monitorMSTeamsProvider } = await import("./src-DZFs5XtZ.js");
1568
+ const { monitorMSTeamsProvider } = await Promise.resolve().then(() => require("./src-20YasZEp.cjs"));
1240
1569
  const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
1241
1570
  ctx.setStatus({
1242
1571
  accountId: ctx.accountId,
@@ -1250,11 +1579,11 @@ const msteamsPlugin = createChatChannelPlugin({
1250
1579
  });
1251
1580
  } }
1252
1581
  },
1253
- security: { collectWarnings: projectConfigWarningCollector(collectMSTeamsSecurityWarnings) },
1582
+ security: { collectWarnings: (0, openclaw_plugin_sdk_channel_policy.projectConfigWarningCollector)(collectMSTeamsSecurityWarnings) },
1254
1583
  pairing: { text: {
1255
1584
  idLabel: "msteamsUserId",
1256
- message: PAIRING_APPROVED_MESSAGE,
1257
- normalizeAllowEntry: createPairingPrefixStripper(/^(msteams|user):/i),
1585
+ message: openclaw_plugin_sdk_channel_status.PAIRING_APPROVED_MESSAGE,
1586
+ normalizeAllowEntry: (0, openclaw_plugin_sdk_channel_pairing.createPairingPrefixStripper)(/^(msteams|user):/i),
1258
1587
  notify: async ({ cfg, id, message }) => {
1259
1588
  const { sendMessageMSTeams } = await loadMSTeamsChannelRuntime();
1260
1589
  await sendMessageMSTeams({
@@ -1268,7 +1597,9 @@ const msteamsPlugin = createChatChannelPlugin({
1268
1597
  const nativeChannelId = context.NativeChannelId?.trim();
1269
1598
  const hasChannelRoute = Boolean(nativeChannelId && nativeChannelId.includes("/"));
1270
1599
  return {
1271
- currentChannelId: normalizeOptionalString(context.To),
1600
+ currentChannelId: (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(context.To),
1601
+ currentChatType: context.ChatType === "direct" || context.ChatType === "group" || context.ChatType === "channel" ? context.ChatType : void 0,
1602
+ currentMessagingTarget: hasChannelRoute ? nativeChannelId : void 0,
1272
1603
  currentGraphChannelId: hasChannelRoute ? nativeChannelId : void 0,
1273
1604
  currentThreadTs: context.ReplyToId,
1274
1605
  hasRepliedRef
@@ -1277,4 +1608,81 @@ const msteamsPlugin = createChatChannelPlugin({
1277
1608
  outbound: msteamsChannelOutbound
1278
1609
  });
1279
1610
  //#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 };
1611
+ Object.defineProperty(exports, "MSTEAMS_PRESENTATION_CAPABILITIES", {
1612
+ enumerable: true,
1613
+ get: function() {
1614
+ return MSTEAMS_PRESENTATION_CAPABILITIES;
1615
+ }
1616
+ });
1617
+ Object.defineProperty(exports, "buildMSTeamsPresentationCard", {
1618
+ enumerable: true,
1619
+ get: function() {
1620
+ return buildMSTeamsPresentationCard;
1621
+ }
1622
+ });
1623
+ Object.defineProperty(exports, "extractMSTeamsConversationMessageId", {
1624
+ enumerable: true,
1625
+ get: function() {
1626
+ return extractMSTeamsConversationMessageId;
1627
+ }
1628
+ });
1629
+ Object.defineProperty(exports, "extractMSTeamsQuoteInfo", {
1630
+ enumerable: true,
1631
+ get: function() {
1632
+ return extractMSTeamsQuoteInfo;
1633
+ }
1634
+ });
1635
+ Object.defineProperty(exports, "msteamsPlugin", {
1636
+ enumerable: true,
1637
+ get: function() {
1638
+ return msteamsPlugin;
1639
+ }
1640
+ });
1641
+ Object.defineProperty(exports, "normalizeMSTeamsConversationId", {
1642
+ enumerable: true,
1643
+ get: function() {
1644
+ return normalizeMSTeamsConversationId;
1645
+ }
1646
+ });
1647
+ Object.defineProperty(exports, "parseMSTeamsActivityTimestamp", {
1648
+ enumerable: true,
1649
+ get: function() {
1650
+ return parseMSTeamsActivityTimestamp;
1651
+ }
1652
+ });
1653
+ Object.defineProperty(exports, "resolveMSTeamsAllowlistMatch", {
1654
+ enumerable: true,
1655
+ get: function() {
1656
+ return resolveMSTeamsAllowlistMatch;
1657
+ }
1658
+ });
1659
+ Object.defineProperty(exports, "resolveMSTeamsReplyPolicy", {
1660
+ enumerable: true,
1661
+ get: function() {
1662
+ return resolveMSTeamsReplyPolicy;
1663
+ }
1664
+ });
1665
+ Object.defineProperty(exports, "resolveMSTeamsRouteConfig", {
1666
+ enumerable: true,
1667
+ get: function() {
1668
+ return resolveMSTeamsRouteConfig;
1669
+ }
1670
+ });
1671
+ Object.defineProperty(exports, "resolveMSTeamsRouteSessionKey", {
1672
+ enumerable: true,
1673
+ get: function() {
1674
+ return resolveMSTeamsRouteSessionKey;
1675
+ }
1676
+ });
1677
+ Object.defineProperty(exports, "stripMSTeamsMentionTags", {
1678
+ enumerable: true,
1679
+ get: function() {
1680
+ return stripMSTeamsMentionTags;
1681
+ }
1682
+ });
1683
+ Object.defineProperty(exports, "wasMSTeamsBotMentioned", {
1684
+ enumerable: true,
1685
+ get: function() {
1686
+ return wasMSTeamsBotMentioned;
1687
+ }
1688
+ });