@openclaw/msteams 2026.10.5-beta.4 → 2026.10.10-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/.setup/{adapter.runtime-JoPydWqP.cjs → adapter.runtime-B-6Q3nMI.cjs} +6 -4
  2. package/dist/.setup/{approval-handler.runtime-bUN9icMr.cjs → approval-handler.runtime-DccVf5AY.cjs} +16 -6
  3. package/dist/.setup/{bot-framework-service-url-CPp4d-Q6.cjs → bot-framework-service-url-B3FWn2SV.cjs} +13 -0
  4. package/dist/.setup/{channel-Cifn9fsv.cjs → channel-B7Gy3QUW.cjs} +261 -175
  5. package/dist/.setup/{channel.runtime-DWRAolil.cjs → channel.runtime-DzKeQAqd.cjs} +84 -49
  6. package/dist/.setup/channel.setup-B5ClEcNI.cjs +990 -0
  7. package/dist/.setup/config-schema-CkKdphSp.cjs +293 -0
  8. package/dist/.setup/{conversation-store-state-DprmOfl7.cjs → conversation-store-state-C3__T9mK.cjs} +79 -91
  9. package/dist/.setup/delegated-state-Bv5cWuec.cjs +110 -0
  10. package/dist/.setup/{monitor-C9x_CJhY.cjs → monitor-CzRI-Hsc.cjs} +283 -240
  11. package/dist/.setup/{oauth-CWJ85AMw.cjs → oauth-D9u8sPCD.cjs} +1 -1
  12. package/dist/.setup/{reaction-types-Ig9sQJuR.cjs → reaction-types-DSQWVA4Z.cjs} +15 -9
  13. package/dist/.setup/{resolve-allowlist-DdDBVCzl.cjs → resolve-allowlist-tYgAHx0t.cjs} +252 -38
  14. package/dist/.setup/{secret-contract-api-ChQdBeU1.cjs → secret-contract-api-YY3v6MP8.cjs} +1 -1
  15. package/dist/.setup/secret-contract-api-wAyY5UHv.cjs +85 -0
  16. package/dist/.setup/{send-rJpcVtRp.cjs → send-Bgm8RYUa.cjs} +45 -24
  17. package/dist/.setup/{setup-plugin-api-DfoVOqMJ.cjs → setup-plugin-api-BACfeF7_.cjs} +1 -1
  18. package/dist/.setup/{thread-session-B74FC1Id.cjs → thread-session-C7KTMwLU.cjs} +11 -4
  19. package/dist/.setup/token-config-bEpua_Q7.cjs +93 -0
  20. package/dist/api.cjs +2 -2
  21. package/dist/channel-config-api.cjs +1 -1
  22. package/dist/channel-plugin-api.cjs +1 -1
  23. package/dist/directory-contract-api.cjs +30 -22
  24. package/dist/doctor-contract-api.cjs +11 -10
  25. package/dist/qa-runner-api.cjs +1 -1
  26. package/dist/runtime-api.cjs +2 -2
  27. package/dist/secret-contract-api.cjs +1 -1
  28. package/dist/setup-entry.cjs +2 -2
  29. package/dist/setup-plugin-api.cjs +1 -1
  30. package/openclaw.plugin.json +715 -0
  31. package/package.json +57 -6
  32. package/dist/.setup/channel.setup-BjbHugkL.cjs +0 -632
  33. package/dist/.setup/config-schema-Dk0mRIam.cjs +0 -160
  34. package/dist/.setup/secret-contract-api-ipiUsANg.cjs +0 -28
  35. package/dist/.setup/token-config-CqIh8z7Q.cjs +0 -138
@@ -0,0 +1,990 @@
1
+ const require_token_config = require("./token-config-bEpua_Q7.cjs");
2
+ const require_resolve_allowlist = require("./resolve-allowlist-tYgAHx0t.cjs");
3
+ require("../runtime-api.cjs");
4
+ const require_delegated_state = require("./delegated-state-Bv5cWuec.cjs");
5
+ const require_config_schema = require("./config-schema-CkKdphSp.cjs");
6
+ let openclaw_plugin_sdk_channel_policy = require("openclaw/plugin-sdk/channel-policy");
7
+ let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
8
+ let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
9
+ let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
10
+ let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
11
+ let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
12
+ let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
13
+ let openclaw_plugin_sdk_channel_setup = require("openclaw/plugin-sdk/channel-setup");
14
+ let openclaw_plugin_sdk_setup = require("openclaw/plugin-sdk/setup");
15
+ let openclaw_plugin_sdk_setup_tools = require("openclaw/plugin-sdk/setup-tools");
16
+ let openclaw_plugin_sdk_channel_dm_policy = require("openclaw/plugin-sdk/channel-dm-policy");
17
+ let openclaw_plugin_sdk_setup_runtime = require("openclaw/plugin-sdk/setup-runtime");
18
+ let openclaw_plugin_sdk_retry_runtime = require("openclaw/plugin-sdk/retry-runtime");
19
+ //#region extensions/msteams/src/accounts-mutations.ts
20
+ function splitRootIdentity(msteams) {
21
+ const { appId, appPassword, ...root } = msteams;
22
+ return {
23
+ root,
24
+ defaultAccount: {
25
+ ...msteams.enabled === false && (appId !== void 0 || appPassword !== void 0 || require_token_config.hasConfiguredMSTeamsCredentials(msteams)) ? { enabled: false } : {},
26
+ ...appId !== void 0 ? { appId } : {},
27
+ ...appPassword !== void 0 ? { appPassword } : {}
28
+ }
29
+ };
30
+ }
31
+ function patchMSTeamsAccountConfig(params) {
32
+ const accountId = (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(params.accountId);
33
+ const msteams = params.cfg.channels?.msteams ?? {};
34
+ const ensureEnabled = params.ensureEnabled ?? true;
35
+ const scopeDefaultToAccounts = params.scopeDefaultToAccounts ?? (accountId === openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID && Object.keys(msteams.accounts ?? {}).length > 0);
36
+ if (accountId === openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID && !scopeDefaultToAccounts) return {
37
+ ...params.cfg,
38
+ channels: {
39
+ ...params.cfg.channels,
40
+ msteams: {
41
+ ...msteams,
42
+ ...ensureEnabled ? { enabled: true } : {},
43
+ ...params.patch
44
+ }
45
+ }
46
+ };
47
+ const { root: baseMsteams, defaultAccount } = splitRootIdentity(msteams);
48
+ const baseAccounts = ensureEnabled && msteams.enabled === false ? Object.fromEntries(Object.entries(baseMsteams.accounts ?? {}).map(([key, account]) => [key, {
49
+ ...account,
50
+ enabled: false
51
+ }])) : baseMsteams.accounts ?? {};
52
+ const hasPromotedDefaultIdentity = Object.keys(defaultAccount).length > 0;
53
+ const promotedDefaultKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(baseAccounts, openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID) ?? openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID;
54
+ const accounts = hasPromotedDefaultIdentity && accountId !== openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID ? {
55
+ ...baseAccounts,
56
+ [promotedDefaultKey]: {
57
+ ...defaultAccount,
58
+ ...baseAccounts[promotedDefaultKey]
59
+ }
60
+ } : baseAccounts;
61
+ const rawAccountKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(accounts, accountId) ?? accountId;
62
+ const existing = accountId === openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID ? {
63
+ ...defaultAccount,
64
+ ...accounts[rawAccountKey]
65
+ } : accounts[rawAccountKey] ?? {};
66
+ return {
67
+ ...params.cfg,
68
+ channels: {
69
+ ...params.cfg.channels,
70
+ msteams: {
71
+ ...baseMsteams,
72
+ ...ensureEnabled ? { enabled: true } : {},
73
+ accounts: {
74
+ ...accounts,
75
+ [rawAccountKey]: {
76
+ ...existing,
77
+ ...ensureEnabled ? { enabled: true } : {},
78
+ ...params.patch
79
+ }
80
+ }
81
+ }
82
+ }
83
+ };
84
+ }
85
+ //#endregion
86
+ //#region extensions/msteams/src/channel-config.ts
87
+ const msteamsMeta = {
88
+ id: "msteams",
89
+ label: "Microsoft Teams",
90
+ selectionLabel: "Microsoft Teams (Bot Framework)",
91
+ docsPath: "/channels/msteams",
92
+ docsLabel: "msteams",
93
+ blurb: "Teams SDK; enterprise support.",
94
+ aliases: ["teams"],
95
+ order: 60
96
+ };
97
+ function resolveMSTeamsSecurityWarningAccount(params) {
98
+ const accountId = (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(params.accountId ?? require_resolve_allowlist.resolveDefaultMSTeamsAccountId(params.cfg));
99
+ return {
100
+ accountId,
101
+ config: require_resolve_allowlist.resolveMSTeamsAccountConfig(params.cfg, accountId)
102
+ };
103
+ }
104
+ const collectMSTeamsSecurityWarnings = (0, openclaw_plugin_sdk_channel_policy.createAllowlistProviderGroupPolicyWarningCollector)({
105
+ providerConfigPresent: (cfg) => cfg.channels?.msteams !== void 0,
106
+ resolveGroupPolicy: (params) => resolveMSTeamsSecurityWarningAccount(params).config.groupPolicy,
107
+ collect: ({ cfg, accountId, groupPolicy }) => {
108
+ if (groupPolicy !== "open") return [];
109
+ const account = resolveMSTeamsSecurityWarningAccount({
110
+ cfg,
111
+ accountId
112
+ });
113
+ const accounts = cfg.channels?.msteams?.accounts;
114
+ const rawAccountKey = accounts ? Object.keys(accounts).find((key) => (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(key) === account.accountId) : void 0;
115
+ const hasAccountPolicyOverride = rawAccountKey !== void 0 && accounts?.[rawAccountKey]?.groupPolicy !== void 0;
116
+ const configPath = account.accountId === openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID && !hasAccountPolicyOverride ? "channels.msteams" : `channels.msteams.accounts.${rawAccountKey ?? account.accountId}`;
117
+ return [`- ${configPath === "channels.msteams" ? "MS Teams" : `MS Teams[${account.accountId}]`} groups: groupPolicy="open" allows any member to trigger (mention-gated). Set ${configPath}.groupPolicy="allowlist" + ${configPath}.groupAllowFrom to restrict senders.`];
118
+ }
119
+ });
120
+ function deleteMSTeamsDefaultAccountIdentity(cfg) {
121
+ const { appId: _appId, appPassword: _appPassword, accounts, defaultAccount, ...rest } = cfg.channels?.msteams ?? {};
122
+ const defaultKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(accounts, openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID) ?? openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID;
123
+ const nextAccounts = {
124
+ ...accounts,
125
+ [defaultKey]: { enabled: false }
126
+ };
127
+ return {
128
+ ...cfg,
129
+ channels: {
130
+ ...cfg.channels,
131
+ msteams: {
132
+ ...rest,
133
+ ...defaultAccount && (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(defaultAccount) !== openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID ? { defaultAccount } : {},
134
+ accounts: nextAccounts
135
+ }
136
+ }
137
+ };
138
+ }
139
+ const msteamsBaseConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createHybridChannelConfigAdapter)({
140
+ sectionKey: "msteams",
141
+ listAccountIds: require_resolve_allowlist.listMSTeamsAccountIds,
142
+ resolveAccount: (0, openclaw_plugin_sdk_channel_config_helpers.adaptScopedAccountAccessor)(require_resolve_allowlist.resolveMSTeamsAccount),
143
+ resolveAccessorAccount: ({ cfg, accountId }) => require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId),
144
+ inspectAccount: (0, openclaw_plugin_sdk_channel_config_helpers.adaptScopedAccountAccessor)(require_resolve_allowlist.inspectMSTeamsAccount),
145
+ defaultAccountId: require_resolve_allowlist.resolveDefaultMSTeamsAccountId,
146
+ clearBaseFields: ["appId", "appPassword"],
147
+ preserveSectionOnDefaultDelete: true,
148
+ resolveAllowFrom: (account) => account.allowFrom,
149
+ formatAllowFrom: (allowFrom) => (0, openclaw_plugin_sdk_allow_from.formatAllowFromLowercase)({ allowFrom }),
150
+ resolveDefaultTo: (account) => account.defaultTo
151
+ });
152
+ function deleteExplicitMSTeamsAccount(params) {
153
+ const channel = params.cfg.channels?.msteams;
154
+ const accounts = channel?.accounts;
155
+ const rawKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(accounts, (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(params.accountId));
156
+ if (!channel || !accounts || !rawKey) return;
157
+ const nextAccounts = { ...accounts };
158
+ delete nextAccounts[rawKey];
159
+ const deletedDefault = (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(channel.defaultAccount) === (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(rawKey);
160
+ return {
161
+ ...params.cfg,
162
+ channels: {
163
+ ...params.cfg.channels,
164
+ msteams: {
165
+ ...channel,
166
+ accounts: Object.keys(nextAccounts).length > 0 ? nextAccounts : void 0,
167
+ defaultAccount: deletedDefault ? void 0 : channel.defaultAccount
168
+ }
169
+ }
170
+ };
171
+ }
172
+ const msteamsConfigAdapter = {
173
+ ...msteamsBaseConfigAdapter,
174
+ setAccountEnabled: (params) => patchMSTeamsAccountConfig({
175
+ cfg: params.cfg,
176
+ accountId: params.accountId,
177
+ patch: { enabled: params.enabled },
178
+ ensureEnabled: params.enabled && params.cfg.channels?.msteams?.enabled === false && require_resolve_allowlist.listMSTeamsAccountIds(params.cfg).length === 1,
179
+ scopeDefaultToAccounts: true
180
+ }),
181
+ deleteAccount: (params) => (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(params.accountId) === openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID ? deleteMSTeamsDefaultAccountIdentity(params.cfg) : deleteExplicitMSTeamsAccount({
182
+ cfg: params.cfg,
183
+ accountId: params.accountId
184
+ }) ?? msteamsBaseConfigAdapter.deleteAccount(params)
185
+ };
186
+ //#endregion
187
+ //#region extensions/msteams/src/setup-core.ts
188
+ const t$1 = (0, openclaw_plugin_sdk_setup.createSetupTranslator)();
189
+ const channel$1 = "msteams";
190
+ function applySecretAuthCredentials(patch, existing) {
191
+ return {
192
+ ...patch,
193
+ authType: "secret",
194
+ ...existing.certificatePath !== void 0 ? { certificatePath: void 0 } : {},
195
+ ...existing.certificateThumbprint !== void 0 ? { certificateThumbprint: void 0 } : {},
196
+ ...existing.useManagedIdentity !== void 0 ? { useManagedIdentity: void 0 } : {},
197
+ ...existing.managedIdentityClientId !== void 0 ? { managedIdentityClientId: void 0 } : {}
198
+ };
199
+ }
200
+ function resolveSetupAccountId(cfg, accountId) {
201
+ return (0, openclaw_plugin_sdk_setup.normalizeAccountId)(accountId ?? require_resolve_allowlist.resolveDefaultMSTeamsAccountId(cfg));
202
+ }
203
+ function resolveRawMSTeamsAccountConfig(cfg, accountId) {
204
+ const normalized = (0, openclaw_plugin_sdk_setup.normalizeAccountId)(accountId);
205
+ const msteams = cfg.channels?.msteams ?? {};
206
+ if (normalized === openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID) {
207
+ const rawAccountKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(msteams.accounts, normalized);
208
+ return (rawAccountKey ? msteams.accounts?.[rawAccountKey] : void 0) ?? msteams;
209
+ }
210
+ const rawAccountKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(msteams.accounts, normalized);
211
+ return (rawAccountKey ? msteams.accounts?.[rawAccountKey] : void 0) ?? {};
212
+ }
213
+ function resolveCredentialsForSetup(cfg, accountId) {
214
+ return require_token_config.resolveMSTeamsCredentials(require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId), {
215
+ allowEnvFallback: accountId === openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID,
216
+ pathPrefix: require_resolve_allowlist.resolveMSTeamsAccountConfigPath(cfg, accountId)
217
+ });
218
+ }
219
+ function resolveEnvironmentCredentialsForSetup() {
220
+ return require_token_config.resolveMSTeamsCredentials(void 0, { allowEnvFallback: true });
221
+ }
222
+ const MSTEAMS_SHARED_CREDENTIAL_FIELDS = [
223
+ "tenantId",
224
+ "authType",
225
+ "certificatePath",
226
+ "certificateThumbprint",
227
+ "useManagedIdentity",
228
+ "managedIdentityClientId"
229
+ ];
230
+ const MSTEAMS_CREDENTIAL_FIELDS = [
231
+ "appId",
232
+ "appPassword",
233
+ ...MSTEAMS_SHARED_CREDENTIAL_FIELDS
234
+ ];
235
+ function removeMSTeamsCredentialFields(config) {
236
+ const next = { ...config };
237
+ for (const field of MSTEAMS_CREDENTIAL_FIELDS) delete next[field];
238
+ return next;
239
+ }
240
+ function selectMSTeamsEnvironmentCredentials(cfg) {
241
+ const scoped = patchMSTeamsAccountConfig({
242
+ cfg,
243
+ accountId: openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID,
244
+ patch: {},
245
+ scopeDefaultToAccounts: true
246
+ });
247
+ const msteams = scoped.channels?.msteams ?? {};
248
+ const accounts = Object.fromEntries(Object.entries(msteams.accounts ?? {}).map(([key, account]) => {
249
+ const current = account ?? {};
250
+ if ((0, openclaw_plugin_sdk_setup.normalizeAccountId)(key) === openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID) return [key, removeMSTeamsCredentialFields(current)];
251
+ return [key, {
252
+ ...Object.fromEntries(MSTEAMS_SHARED_CREDENTIAL_FIELDS.flatMap((field) => current[field] === void 0 && msteams[field] !== void 0 ? [[field, msteams[field]]] : [])),
253
+ ...current
254
+ }];
255
+ }));
256
+ return {
257
+ ...scoped,
258
+ channels: {
259
+ ...scoped.channels,
260
+ msteams: {
261
+ ...removeMSTeamsCredentialFields(msteams),
262
+ accounts
263
+ }
264
+ }
265
+ };
266
+ }
267
+ function hasConfiguredCredentialsForSetup(cfg, accountId, input) {
268
+ const resolved = require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId);
269
+ const appId = input?.appId?.trim();
270
+ const appPassword = input?.appPassword?.trim();
271
+ const tenantId = input?.tenantId?.trim();
272
+ const replacesWithSecretAuth = Boolean(appId && appPassword && (tenantId || resolved.tenantId?.trim()));
273
+ return require_token_config.hasConfiguredMSTeamsCredentials({
274
+ ...resolved,
275
+ ...appId ? { appId } : {},
276
+ ...appPassword ? { appPassword } : {},
277
+ ...tenantId ? { tenantId } : {},
278
+ ...replacesWithSecretAuth ? { authType: "secret" } : {}
279
+ }, { allowEnvFallback: accountId === openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID });
280
+ }
281
+ const msteamsSetupAdapter = {
282
+ configPromotion: "preserve-root",
283
+ resolveAccountId: ({ cfg, accountId }) => resolveSetupAccountId(cfg, accountId),
284
+ applyAccountName: ({ cfg, accountId, name }) => {
285
+ const trimmed = name?.trim();
286
+ return trimmed ? patchMSTeamsAccountConfig({
287
+ cfg,
288
+ accountId: resolveSetupAccountId(cfg, accountId),
289
+ patch: { name: trimmed },
290
+ scopeDefaultToAccounts: true
291
+ }) : cfg;
292
+ },
293
+ validateInput: ({ cfg, accountId, input }) => {
294
+ const resolvedAccountId = resolveSetupAccountId(cfg, accountId);
295
+ const appId = input.appId;
296
+ const appPassword = input.appPassword;
297
+ const tenantId = input.tenantId;
298
+ const hasAnyExplicitCredential = Boolean(appId || appPassword || tenantId);
299
+ const hasCompleteExplicitCredentials = Boolean(appId?.trim() && appPassword?.trim() && tenantId?.trim());
300
+ if (input.useEnv && resolvedAccountId !== openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID) return "MSTEAMS_* environment variables can only be used for the default account.";
301
+ if (input.useEnv && hasAnyExplicitCredential && !hasCompleteExplicitCredentials) return "MS Teams requires appId, appPassword, and tenantId when replacing environment credentials.";
302
+ if (input.useEnv && !hasCompleteExplicitCredentials && !resolveEnvironmentCredentialsForSetup()) return "MS Teams --use-env requires complete secret, certificate, or managed-identity environment credentials.";
303
+ if (!input.useEnv && !hasCompleteExplicitCredentials && !hasConfiguredCredentialsForSetup(cfg, resolvedAccountId, input)) return "MS Teams requires appId, appPassword, and tenantId (or --use-env for the default account).";
304
+ if (input.webhookPath !== void 0 && !input.webhookPath.trim().startsWith("/")) return "MS Teams webhook path must start with /.";
305
+ return null;
306
+ },
307
+ applyAccountConfig: ({ cfg, accountId, input }) => {
308
+ const resolvedAccountId = resolveSetupAccountId(cfg, accountId);
309
+ const appId = input.appId;
310
+ const appPassword = input.appPassword;
311
+ const tenantId = input.tenantId;
312
+ const existing = resolveRawMSTeamsAccountConfig(cfg, resolvedAccountId);
313
+ const patch = {};
314
+ if (appId?.trim()) patch.appId = appId.trim();
315
+ if (appPassword?.trim()) patch.appPassword = appPassword.trim();
316
+ if (tenantId?.trim()) patch.tenantId = tenantId.trim();
317
+ if (input.webhookPath !== void 0) patch.webhook = {
318
+ ...existing.webhook,
319
+ path: input.webhookPath.trim()
320
+ };
321
+ const inheritedTenantId = require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, resolvedAccountId).tenantId?.trim();
322
+ const replacesWithSecretAuth = Boolean(appId?.trim() && appPassword?.trim() && (tenantId?.trim() || inheritedTenantId));
323
+ const credentialPatch = replacesWithSecretAuth ? applySecretAuthCredentials(patch, existing) : patch;
324
+ return patchMSTeamsAccountConfig({
325
+ cfg: input.useEnv && !replacesWithSecretAuth ? selectMSTeamsEnvironmentCredentials(cfg) : cfg,
326
+ accountId: resolvedAccountId,
327
+ patch: credentialPatch,
328
+ scopeDefaultToAccounts: true
329
+ });
330
+ }
331
+ };
332
+ const msteamsSetupContract = (0, openclaw_plugin_sdk_channel_setup.defineChannelSetupContract)({
333
+ fields: {
334
+ appId: {
335
+ kind: "string",
336
+ cli: {
337
+ flags: "--app-id <id>",
338
+ description: "Microsoft Teams application id"
339
+ }
340
+ },
341
+ appPassword: {
342
+ kind: "string",
343
+ sensitive: true,
344
+ cli: {
345
+ flags: "--app-password <secret>",
346
+ description: "Microsoft Teams app password"
347
+ }
348
+ },
349
+ tenantId: {
350
+ kind: "string",
351
+ cli: {
352
+ flags: "--tenant-id <id>",
353
+ description: "Microsoft Teams tenant id"
354
+ }
355
+ },
356
+ webhookPath: {
357
+ kind: "string",
358
+ cli: {
359
+ flags: "--webhook-path <path>",
360
+ description: "Microsoft Teams webhook path"
361
+ }
362
+ },
363
+ useEnv: {
364
+ kind: "boolean",
365
+ cli: {
366
+ flags: "--use-env",
367
+ description: "Use Microsoft Teams environment credentials"
368
+ },
369
+ envVars: [
370
+ "MSTEAMS_APP_ID",
371
+ "MSTEAMS_APP_PASSWORD",
372
+ "MSTEAMS_TENANT_ID",
373
+ "MSTEAMS_AUTH_TYPE",
374
+ "MSTEAMS_CERTIFICATE_PATH",
375
+ "MSTEAMS_USE_MANAGED_IDENTITY"
376
+ ],
377
+ envVarMode: "any"
378
+ }
379
+ },
380
+ adapter: msteamsSetupAdapter
381
+ });
382
+ async function promptMSTeamsCredentials(prompter) {
383
+ const promptRequired = async (message) => (await prompter.text({
384
+ message,
385
+ validate: (value) => value?.trim() ? void 0 : t$1("common.required")
386
+ })).trim();
387
+ return {
388
+ appId: await promptRequired(t$1("wizard.msteams.appIdPrompt")),
389
+ appPassword: await promptRequired(t$1("wizard.msteams.appPasswordPrompt")),
390
+ tenantId: await promptRequired(t$1("wizard.msteams.tenantIdPrompt"))
391
+ };
392
+ }
393
+ async function noteMSTeamsCredentialHelp(prompter) {
394
+ await prompter.note([
395
+ t$1("wizard.msteams.helpAzureBot"),
396
+ t$1("wizard.msteams.helpClientSecret"),
397
+ t$1("wizard.msteams.helpWebhook"),
398
+ t$1("wizard.msteams.helpEnvTip"),
399
+ t$1("wizard.channels.docs", { link: (0, openclaw_plugin_sdk_setup_tools.formatDocsLink)("/channels/msteams", "msteams") })
400
+ ].join("\n"), t$1("wizard.msteams.credentialsTitle"));
401
+ }
402
+ function createMSTeamsSetupWizardBase() {
403
+ return {
404
+ channel: channel$1,
405
+ resolveAccountIdForConfigure: ({ cfg, accountOverride, defaultAccountId }) => resolveSetupAccountId(cfg, accountOverride ?? defaultAccountId),
406
+ resolveShouldPromptAccountIds: ({ shouldPromptAccountIds }) => shouldPromptAccountIds,
407
+ status: (0, openclaw_plugin_sdk_setup.createStandardChannelSetupStatus)({
408
+ channelLabel: "MS Teams",
409
+ configuredLabel: t$1("wizard.channels.statusConfigured"),
410
+ unconfiguredLabel: t$1("wizard.channels.statusNeedsAppCredentials"),
411
+ configuredHint: t$1("wizard.channels.statusConfigured"),
412
+ unconfiguredHint: t$1("wizard.channels.statusNeedsAppCreds"),
413
+ configuredScore: 2,
414
+ unconfiguredScore: 0,
415
+ includeStatusLine: true,
416
+ resolveConfigured: ({ cfg, accountId }) => {
417
+ const resolvedAccountId = resolveSetupAccountId(cfg, accountId);
418
+ return Boolean(resolveCredentialsForSetup(cfg, resolvedAccountId)) || hasConfiguredCredentialsForSetup(cfg, resolvedAccountId);
419
+ }
420
+ }),
421
+ credentials: [],
422
+ finalize: async ({ cfg, accountId, prompter }) => {
423
+ const resolvedAccountId = resolveSetupAccountId(cfg, accountId);
424
+ const resolved = resolveCredentialsForSetup(cfg, resolvedAccountId);
425
+ const hasConfigCreds = require_token_config.hasConfiguredMSTeamsCredentials(require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, resolvedAccountId), { allowEnvFallback: false });
426
+ const canUseEnv = Boolean(resolvedAccountId === openclaw_plugin_sdk_setup.DEFAULT_ACCOUNT_ID && !hasConfigCreds && resolveEnvironmentCredentialsForSetup());
427
+ let next = cfg;
428
+ if (!resolved && !hasConfigCreds) await noteMSTeamsCredentialHelp(prompter);
429
+ const keep = (canUseEnv || hasConfigCreds) && await prompter.confirm({
430
+ message: t$1(canUseEnv ? "wizard.msteams.envPrompt" : "wizard.msteams.credentialsKeep"),
431
+ initialValue: true
432
+ });
433
+ next = msteamsSetupAdapter.applyAccountConfig({
434
+ cfg: next,
435
+ accountId: resolvedAccountId,
436
+ input: keep ? { useEnv: canUseEnv } : await promptMSTeamsCredentials(prompter)
437
+ });
438
+ return {
439
+ cfg: next,
440
+ accountId: resolvedAccountId
441
+ };
442
+ }
443
+ };
444
+ }
445
+ //#endregion
446
+ //#region extensions/msteams/src/errors.ts
447
+ const MAX_SAFE_RETRY_AFTER_SECONDS = Number.MAX_SAFE_INTEGER / 1e3;
448
+ function formatUnknownError(err) {
449
+ if (err instanceof Error) return err.message;
450
+ if (typeof err === "symbol") return err.description ?? err.toString();
451
+ if (typeof err === "function") return err.name ? `[function ${err.name}]` : "[function]";
452
+ if (err === null || typeof err !== "object") return String(err);
453
+ try {
454
+ return JSON.stringify(err) ?? "unknown error";
455
+ } catch {
456
+ return "unknown error";
457
+ }
458
+ }
459
+ function extractStatusCode(err) {
460
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(err)) return null;
461
+ const parseStatusCode = (value) => {
462
+ if (typeof value === "number") return Number.isInteger(value) && value >= 100 && value <= 599 ? value : null;
463
+ if (typeof value === "string") {
464
+ const trimmed = value.trim();
465
+ if (!/^\d{3}$/.test(trimmed)) return null;
466
+ const parsed = Number(trimmed);
467
+ return parsed >= 100 && parsed <= 599 ? parsed : null;
468
+ }
469
+ return null;
470
+ };
471
+ const directStatus = parseStatusCode(err.statusCode ?? err.status);
472
+ if (directStatus !== null) return directStatus;
473
+ const response = err.response;
474
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(response)) {
475
+ const responseStatus = parseStatusCode(response.status);
476
+ if (responseStatus !== null) return responseStatus;
477
+ }
478
+ return null;
479
+ }
480
+ function extractErrorCode(err) {
481
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(err)) return null;
482
+ const direct = err.code;
483
+ if (typeof direct === "string" && direct.trim()) return direct;
484
+ const response = err.response;
485
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(response)) return null;
486
+ const body = response.body;
487
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(body)) {
488
+ const error = body.error;
489
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(error) && typeof error.code === "string" && error.code.trim()) return error.code;
490
+ }
491
+ return null;
492
+ }
493
+ function extractRetryAfterMs(err) {
494
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(err)) return null;
495
+ const direct = err.retryAfterMs ?? err.retry_after_ms;
496
+ const directMs = (0, openclaw_plugin_sdk_number_runtime.asFiniteNumberInRange)(direct, {
497
+ min: 0,
498
+ max: Number.MAX_SAFE_INTEGER
499
+ });
500
+ if (directMs !== void 0) return directMs;
501
+ const retryAfter = err.retryAfter ?? err.retry_after;
502
+ const retryAfterSeconds = (0, openclaw_plugin_sdk_number_runtime.asFiniteNumberInRange)(retryAfter, {
503
+ min: 0,
504
+ max: MAX_SAFE_RETRY_AFTER_SECONDS
505
+ });
506
+ if (retryAfterSeconds !== void 0) return retryAfterSeconds * 1e3;
507
+ if (typeof retryAfter === "string") {
508
+ const parsed = parseNonNegativeRetryAfterSeconds(retryAfter);
509
+ if (parsed !== void 0) return parsed * 1e3;
510
+ }
511
+ const response = err.response;
512
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(response)) return null;
513
+ const headers = response.headers;
514
+ if (!headers) return null;
515
+ if ((0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(headers)) {
516
+ const raw = headers["retry-after"] ?? headers["Retry-After"];
517
+ if (typeof raw === "string") {
518
+ const parsed = (0, openclaw_plugin_sdk_retry_runtime.parseRetryAfterHeaderSeconds)(raw);
519
+ if (parsed !== void 0) return parsed * 1e3;
520
+ }
521
+ }
522
+ if (typeof headers === "object" && headers !== null && "get" in headers && typeof headers.get === "function") {
523
+ const raw = headers.get("retry-after");
524
+ if (raw) {
525
+ const parsed = (0, openclaw_plugin_sdk_retry_runtime.parseRetryAfterHeaderSeconds)(raw);
526
+ if (parsed !== void 0) return parsed * 1e3;
527
+ }
528
+ }
529
+ return null;
530
+ }
531
+ function parseNonNegativeRetryAfterSeconds(raw) {
532
+ const trimmed = raw.trim();
533
+ if (!/^\d+(?:\.\d+)?$/.test(trimmed)) return;
534
+ return (0, openclaw_plugin_sdk_number_runtime.asFiniteNumberInRange)((0, openclaw_plugin_sdk_number_runtime.parseStrictFiniteNumber)(trimmed), {
535
+ min: 0,
536
+ max: MAX_SAFE_RETRY_AFTER_SECONDS
537
+ });
538
+ }
539
+ /**
540
+ * Owns retry safety and delivery ambiguity for Teams send failures.
541
+ * Only Teams rate-limit rejection proves this unkeyed POST safe to replay.
542
+ */
543
+ function classifyMSTeamsSendError(err) {
544
+ const statusCode = extractStatusCode(err);
545
+ const retryAfterMs = extractRetryAfterMs(err);
546
+ const errorCode = extractErrorCode(err) ?? void 0;
547
+ if (statusCode === 401) return {
548
+ kind: "auth",
549
+ statusCode,
550
+ errorCode
551
+ };
552
+ if (statusCode === 403) {
553
+ if (errorCode === "ContentStreamNotAllowed") return {
554
+ kind: "permanent",
555
+ statusCode,
556
+ errorCode
557
+ };
558
+ return {
559
+ kind: "auth",
560
+ statusCode,
561
+ errorCode
562
+ };
563
+ }
564
+ if (statusCode === 429) return {
565
+ kind: "replay-safe",
566
+ statusCode,
567
+ retryAfterMs: retryAfterMs ?? void 0,
568
+ errorCode
569
+ };
570
+ if (statusCode === 408 || statusCode != null && statusCode >= 500) return {
571
+ kind: "ambiguous",
572
+ source: "http",
573
+ statusCode,
574
+ errorCode
575
+ };
576
+ if (statusCode != null && statusCode >= 400) return {
577
+ kind: "permanent",
578
+ statusCode,
579
+ errorCode
580
+ };
581
+ if (statusCode == null && (0, openclaw_plugin_sdk_retry_runtime.isTransientNetworkError)(err)) return {
582
+ kind: "ambiguous",
583
+ source: "transport",
584
+ errorCode
585
+ };
586
+ return {
587
+ kind: "unknown",
588
+ statusCode: statusCode ?? void 0,
589
+ errorCode
590
+ };
591
+ }
592
+ /**
593
+ * Detect whether an error is caused by a revoked Proxy.
594
+ *
595
+ * The Bot Framework SDK wraps TurnContext in a Proxy that is revoked once the
596
+ * turn handler returns. Any later access (e.g. from a debounced callback)
597
+ * throws a TypeError whose message contains the distinctive "proxy that has
598
+ * been revoked" string.
599
+ */
600
+ function isRevokedProxyError(err) {
601
+ if (!(err instanceof TypeError)) return false;
602
+ return /proxy that has been revoked/i.test(err.message);
603
+ }
604
+ function formatMSTeamsSendErrorHint(classification) {
605
+ if (classification.kind === "auth") return "check msteams appId/appPassword/tenantId (or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID)";
606
+ if (classification.errorCode === "ContentStreamNotAllowed") return "Teams expired the content stream; stop streaming earlier and fall back to normal message delivery";
607
+ if (classification.kind === "replay-safe") return "Teams throttled the bot; backing off may help";
608
+ if (classification.kind === "ambiguous") {
609
+ if (classification.source === "transport") return "transport-level failure sending to Teams Bot Connector (smba.trafficmanager.net); the outcome is unknown, so check egress and conversation history before taking further action";
610
+ return "Teams/Bot Framework delivery outcome is unknown; inspect the conversation history before taking further action";
611
+ }
612
+ }
613
+ function formatMSTeamsDeliveryFailureGuidance(classification) {
614
+ if (classification.kind === "replay-safe") return "The request was rate-limited before delivery; retrying later may succeed.";
615
+ if (classification.kind === "ambiguous") return "Delivery may already have succeeded; do not send the same content again without checking the conversation.";
616
+ }
617
+ //#endregion
618
+ //#region extensions/msteams/src/setup-surface.ts
619
+ const t = (0, openclaw_plugin_sdk_setup.createSetupTranslator)();
620
+ const channel = "msteams";
621
+ function openDelegatedOAuthUrl(url) {
622
+ return Promise.reject(/* @__PURE__ */ new Error(`Automatic browser launch is not available. Open this URL manually: ${url}`));
623
+ }
624
+ function looksLikeGuid(value) {
625
+ return /^[0-9a-fA-F-]{16,}$/.test(value);
626
+ }
627
+ async function promptMSTeamsAllowFrom(params) {
628
+ const accountId = (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(params.accountId ?? require_resolve_allowlist.resolveDefaultMSTeamsAccountId(params.cfg));
629
+ const existing = require_resolve_allowlist.resolveMSTeamsAccountConfig(params.cfg, accountId).allowFrom ?? [];
630
+ await params.prompter.note([
631
+ t("wizard.msteams.allowlistIntro"),
632
+ t("wizard.msteams.allowlistResolve"),
633
+ t("wizard.msteams.examples"),
634
+ "- alex@example.com",
635
+ "- Alex Johnson",
636
+ "- 00000000-0000-0000-0000-000000000000"
637
+ ].join("\n"), t("wizard.msteams.allowlistTitle"));
638
+ while (true) {
639
+ const entry = await params.prompter.text({
640
+ message: t("wizard.msteams.allowFromPrompt"),
641
+ placeholder: "alex@example.com, Alex Johnson",
642
+ initialValue: existing[0] ? existing[0] : void 0,
643
+ validate: (value) => value.trim() ? void 0 : t("common.required")
644
+ });
645
+ const parts = (0, openclaw_plugin_sdk_setup.splitSetupEntries)(entry);
646
+ if (parts.length === 0) {
647
+ await params.prompter.note(t("wizard.msteams.enterAtLeastOneUser"), t("wizard.msteams.allowlistTitle"));
648
+ continue;
649
+ }
650
+ const resolved = await require_resolve_allowlist.resolveMSTeamsUserAllowlist({
651
+ cfg: params.cfg,
652
+ accountId,
653
+ entries: parts
654
+ }).catch(() => null);
655
+ let ids;
656
+ if (!resolved) {
657
+ ids = parts.filter((part) => looksLikeGuid(part));
658
+ if (ids.length !== parts.length) {
659
+ await params.prompter.note(t("wizard.msteams.graphLookupUnavailable"), t("wizard.msteams.allowlistTitle"));
660
+ continue;
661
+ }
662
+ } else {
663
+ const unresolved = resolved.filter((item) => !item.resolved || !item.id);
664
+ if (unresolved.length > 0) {
665
+ await params.prompter.note(t("wizard.msteams.couldNotResolve", { entries: unresolved.map((item) => item.input).join(", ") }), t("wizard.msteams.allowlistTitle"));
666
+ continue;
667
+ }
668
+ ids = resolved.flatMap((item) => item.id ? [item.id] : []);
669
+ }
670
+ const unique = (0, openclaw_plugin_sdk_setup.mergeAllowFromEntries)(existing, ids);
671
+ return patchMSTeamsAccountConfig({
672
+ cfg: params.cfg,
673
+ accountId,
674
+ patch: {
675
+ dmPolicy: "allowlist",
676
+ allowFrom: unique
677
+ },
678
+ scopeDefaultToAccounts: shouldScopeMSTeamsDefaultToAccounts(params.cfg, accountId)
679
+ });
680
+ }
681
+ }
682
+ function shouldScopeMSTeamsDefaultToAccounts(cfg, accountId) {
683
+ if ((0, openclaw_plugin_sdk_account_id.normalizeAccountId)(accountId) !== openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID) return false;
684
+ return Object.keys(cfg.channels?.msteams?.accounts ?? {}).length > 0;
685
+ }
686
+ function setMSTeamsTeamsAllowlist(cfg, accountId, entries) {
687
+ const teams = { ...require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId).teams ?? {} };
688
+ for (const entry of entries) {
689
+ const teamKey = entry.teamKey;
690
+ if (!teamKey) continue;
691
+ const existing = teams[teamKey] ?? {};
692
+ if (entry.channelKey) {
693
+ const channels = { ...existing.channels };
694
+ channels[entry.channelKey] = channels[entry.channelKey] ?? {};
695
+ teams[teamKey] = {
696
+ ...existing,
697
+ channels
698
+ };
699
+ } else teams[teamKey] = existing;
700
+ }
701
+ return patchMSTeamsAccountConfig({
702
+ cfg,
703
+ accountId,
704
+ patch: { teams },
705
+ scopeDefaultToAccounts: shouldScopeMSTeamsDefaultToAccounts(cfg, accountId)
706
+ });
707
+ }
708
+ function listMSTeamsGroupEntries(cfg, accountId) {
709
+ return Object.entries(require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId).teams ?? {}).flatMap(([teamKey, value]) => {
710
+ const channels = value?.channels ?? {};
711
+ const channelKeys = Object.keys(channels);
712
+ if (channelKeys.length === 0) return [teamKey];
713
+ return channelKeys.map((channelKey) => `${teamKey}/${channelKey}`);
714
+ });
715
+ }
716
+ async function resolveMSTeamsGroupAllowlist(params) {
717
+ let resolvedEntries = params.entries.map((entry) => require_resolve_allowlist.parseMSTeamsTeamEntry(entry)).filter((entry) => entry !== null);
718
+ if (params.entries.length === 0 || !require_token_config.resolveMSTeamsCredentials(require_resolve_allowlist.resolveMSTeamsAccountConfig(params.cfg, params.accountId), {
719
+ allowEnvFallback: params.accountId === "default",
720
+ pathPrefix: require_resolve_allowlist.resolveMSTeamsAccountConfigPath(params.cfg, params.accountId)
721
+ })) return resolvedEntries;
722
+ try {
723
+ const lookups = await require_resolve_allowlist.resolveMSTeamsChannelAllowlist({
724
+ cfg: params.cfg,
725
+ accountId: params.accountId,
726
+ entries: params.entries
727
+ });
728
+ const resolvedChannels = lookups.filter((entry) => entry.resolved && entry.teamId && entry.channelId);
729
+ const resolvedTeams = lookups.filter((entry) => entry.resolved && entry.teamId && !entry.channelId);
730
+ const unresolved = lookups.filter((entry) => !entry.resolved).map((entry) => entry.input);
731
+ resolvedEntries = [
732
+ ...resolvedChannels.flatMap((entry) => entry.teamId && entry.channelId ? [{
733
+ teamKey: entry.teamId,
734
+ channelKey: entry.channelId
735
+ }] : []),
736
+ ...resolvedTeams.flatMap((entry) => entry.teamId ? [{ teamKey: entry.teamId }] : []),
737
+ ...unresolved.map((entry) => require_resolve_allowlist.parseMSTeamsTeamEntry(entry)).filter((entry) => entry !== null)
738
+ ];
739
+ const summary = [];
740
+ if (resolvedChannels.length > 0) summary.push(t("wizard.msteams.resolvedChannels", { entries: resolvedChannels.map((entry) => entry.channelId).filter(Boolean).join(", ") }));
741
+ if (resolvedTeams.length > 0) summary.push(t("wizard.msteams.resolvedTeams", { entries: resolvedTeams.map((entry) => entry.teamId).filter(Boolean).join(", ") }));
742
+ if (unresolved.length > 0) summary.push(t("wizard.msteams.unresolvedKept", { entries: unresolved.join(", ") }));
743
+ if (summary.length > 0) await params.prompter.note(summary.join("\n"), t("wizard.msteams.channelsLabel"));
744
+ return resolvedEntries;
745
+ } catch (err) {
746
+ await params.prompter.note(t("wizard.msteams.channelLookupFailed", { error: formatUnknownError(err) }), t("wizard.msteams.channelsLabel"));
747
+ return resolvedEntries;
748
+ }
749
+ }
750
+ const msteamsGroupAccess = {
751
+ ...(0, openclaw_plugin_sdk_setup_runtime.createAccountScopedGroupAccessSection)({
752
+ channel,
753
+ label: t("wizard.msteams.channelsLabel"),
754
+ placeholder: "Team Name/Channel Name, teamId/conversationId",
755
+ currentPolicy: ({ cfg, accountId }) => require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId).groupPolicy ?? "allowlist",
756
+ currentEntries: ({ cfg, accountId }) => listMSTeamsGroupEntries(cfg, accountId),
757
+ updatePrompt: ({ cfg, accountId }) => Boolean(require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, accountId).teams),
758
+ resolveAllowlist: ({ cfg, accountId, entries, prompter }) => resolveMSTeamsGroupAllowlist({
759
+ cfg,
760
+ accountId,
761
+ entries,
762
+ prompter
763
+ }),
764
+ fallbackResolved: (entries) => entries.map((entry) => require_resolve_allowlist.parseMSTeamsTeamEntry(entry)).filter((entry) => entry !== null),
765
+ applyAllowlist: ({ cfg, accountId, resolved }) => setMSTeamsTeamsAllowlist(cfg, accountId, resolved)
766
+ }),
767
+ setPolicy: ({ cfg, accountId, policy }) => patchMSTeamsAccountConfig({
768
+ cfg,
769
+ accountId,
770
+ patch: { groupPolicy: policy },
771
+ scopeDefaultToAccounts: shouldScopeMSTeamsDefaultToAccounts(cfg, accountId)
772
+ })
773
+ };
774
+ const msteamsDmPolicy = (0, openclaw_plugin_sdk_channel_dm_policy.createChannelDmPolicy)({
775
+ label: "MS Teams",
776
+ channel,
777
+ policyKey: "channels.msteams.dmPolicy",
778
+ allowFromKey: "channels.msteams.allowFrom",
779
+ resolveAccount: (cfg, accountId) => {
780
+ const resolvedAccountId = (0, openclaw_plugin_sdk_account_id.normalizeAccountId)(accountId ?? require_resolve_allowlist.resolveDefaultMSTeamsAccountId(cfg));
781
+ return {
782
+ accountId: resolvedAccountId,
783
+ config: require_resolve_allowlist.resolveMSTeamsAccountConfig(cfg, resolvedAccountId)
784
+ };
785
+ },
786
+ resolveConfigKeys: ({ cfg, account }) => {
787
+ const rawAccountKey = require_resolve_allowlist.resolveMSTeamsAccountEntryKey(cfg.channels?.msteams?.accounts, account.accountId);
788
+ const base = account.accountId !== "default" || shouldScopeMSTeamsDefaultToAccounts(cfg, account.accountId) ? `channels.msteams.accounts.${rawAccountKey ?? account.accountId}` : "channels.msteams";
789
+ return {
790
+ policyKey: `${base}.dmPolicy`,
791
+ allowFromKey: `${base}.allowFrom`
792
+ };
793
+ },
794
+ applyPatch: ({ cfg, account, patch }) => patchMSTeamsAccountConfig({
795
+ cfg,
796
+ accountId: account.accountId,
797
+ patch,
798
+ scopeDefaultToAccounts: shouldScopeMSTeamsDefaultToAccounts(cfg, account.accountId)
799
+ }),
800
+ promptAllowFrom: promptMSTeamsAllowFrom
801
+ });
802
+ const msteamsSetupWizardBase = createMSTeamsSetupWizardBase();
803
+ const msteamsSetupWizard = {
804
+ ...msteamsSetupWizardBase,
805
+ finalize: async (params) => {
806
+ const baseFinalize = msteamsSetupWizardBase.finalize;
807
+ const baseResult = baseFinalize ? await baseFinalize(params) : void 0;
808
+ let next = baseResult?.cfg ?? params.cfg;
809
+ const resolvedAccountId = baseResult && "accountId" in baseResult && typeof baseResult.accountId === "string" ? baseResult.accountId : params.accountId;
810
+ const finalCreds = require_token_config.resolveMSTeamsCredentials(require_resolve_allowlist.resolveMSTeamsAccountConfig(next, resolvedAccountId), {
811
+ allowEnvFallback: resolvedAccountId === "default",
812
+ pathPrefix: require_resolve_allowlist.resolveMSTeamsAccountConfigPath(next, resolvedAccountId)
813
+ });
814
+ if (finalCreds?.type === "secret") {
815
+ if (await params.prompter.confirm({
816
+ message: t("wizard.msteams.delegatedAuthPrompt"),
817
+ initialValue: false
818
+ })) {
819
+ next = patchMSTeamsAccountConfig({
820
+ cfg: next,
821
+ accountId: resolvedAccountId,
822
+ patch: { delegatedAuth: { enabled: true } },
823
+ scopeDefaultToAccounts: shouldScopeMSTeamsDefaultToAccounts(next, resolvedAccountId)
824
+ });
825
+ const noteDelegatedAuthFailure = async (err) => {
826
+ await params.prompter.note(`Delegated auth setup failed: ${formatUnknownError(err)}\n` + t("wizard.msteams.delegatedAuthRetry"), t("wizard.msteams.delegatedAuthTitle"));
827
+ };
828
+ let oauthModule;
829
+ try {
830
+ oauthModule = await Promise.resolve().then(() => require("./oauth-D9u8sPCD.cjs"));
831
+ } catch (err) {
832
+ await noteDelegatedAuthFailure(err);
833
+ return {
834
+ ...baseResult,
835
+ cfg: next
836
+ };
837
+ }
838
+ await params.options?.beforePersistentEffect?.();
839
+ const progress = params.prompter.progress(t("wizard.msteams.delegatedOAuthProgress"));
840
+ let tokens;
841
+ try {
842
+ tokens = await oauthModule.loginMSTeamsDelegated({
843
+ log: (msg) => {
844
+ params.prompter.note(msg);
845
+ },
846
+ note: (msg, title) => params.prompter.note(msg, title),
847
+ prompt: (msg) => params.prompter.text({ message: msg }),
848
+ progress
849
+ }, {
850
+ tenantId: finalCreds.tenantId,
851
+ clientId: finalCreds.appId,
852
+ clientSecret: finalCreds.appPassword
853
+ });
854
+ } catch (err) {
855
+ progress.stop();
856
+ await noteDelegatedAuthFailure(err);
857
+ return {
858
+ ...baseResult,
859
+ cfg: next
860
+ };
861
+ }
862
+ try {
863
+ await params.options?.beforePersistentEffect?.();
864
+ } catch (err) {
865
+ progress.stop();
866
+ throw err;
867
+ }
868
+ await require_delegated_state.saveMSTeamsDelegatedTokens(tokens, resolvedAccountId);
869
+ progress.stop(t("wizard.msteams.delegatedAuthConfigured"));
870
+ }
871
+ }
872
+ return {
873
+ ...baseResult,
874
+ cfg: next
875
+ };
876
+ },
877
+ dmPolicy: msteamsDmPolicy,
878
+ groupAccess: msteamsGroupAccess,
879
+ disable: (cfg) => (0, openclaw_plugin_sdk_setup.setSetupChannelEnabled)(cfg, channel, false)
880
+ };
881
+ //#endregion
882
+ //#region extensions/msteams/src/channel.setup.ts
883
+ const msteamsSetupPlugin = {
884
+ id: "msteams",
885
+ meta: {
886
+ ...msteamsMeta,
887
+ aliases: [...msteamsMeta.aliases]
888
+ },
889
+ capabilities: {
890
+ chatTypes: [
891
+ "direct",
892
+ "channel",
893
+ "group",
894
+ "thread"
895
+ ],
896
+ polls: true,
897
+ threads: true,
898
+ media: true,
899
+ reactions: true
900
+ },
901
+ reload: {
902
+ configPrefixes: ["channels.msteams"],
903
+ noopPrefixes: ["messages.inbound"]
904
+ },
905
+ configSchema: require_config_schema.MSTeamsChannelConfigSchema,
906
+ config: {
907
+ ...msteamsConfigAdapter,
908
+ isConfigured: (account) => account.configured,
909
+ describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
910
+ account,
911
+ configured: account.configured,
912
+ extra: { tokenStatus: account.tokenStatus }
913
+ })
914
+ },
915
+ setupWizard: msteamsSetupWizard,
916
+ setupContract: msteamsSetupContract
917
+ };
918
+ //#endregion
919
+ Object.defineProperty(exports, "classifyMSTeamsSendError", {
920
+ enumerable: true,
921
+ get: function() {
922
+ return classifyMSTeamsSendError;
923
+ }
924
+ });
925
+ Object.defineProperty(exports, "collectMSTeamsSecurityWarnings", {
926
+ enumerable: true,
927
+ get: function() {
928
+ return collectMSTeamsSecurityWarnings;
929
+ }
930
+ });
931
+ Object.defineProperty(exports, "createMSTeamsSetupWizardBase", {
932
+ enumerable: true,
933
+ get: function() {
934
+ return createMSTeamsSetupWizardBase;
935
+ }
936
+ });
937
+ Object.defineProperty(exports, "formatMSTeamsDeliveryFailureGuidance", {
938
+ enumerable: true,
939
+ get: function() {
940
+ return formatMSTeamsDeliveryFailureGuidance;
941
+ }
942
+ });
943
+ Object.defineProperty(exports, "formatMSTeamsSendErrorHint", {
944
+ enumerable: true,
945
+ get: function() {
946
+ return formatMSTeamsSendErrorHint;
947
+ }
948
+ });
949
+ Object.defineProperty(exports, "formatUnknownError", {
950
+ enumerable: true,
951
+ get: function() {
952
+ return formatUnknownError;
953
+ }
954
+ });
955
+ Object.defineProperty(exports, "isRevokedProxyError", {
956
+ enumerable: true,
957
+ get: function() {
958
+ return isRevokedProxyError;
959
+ }
960
+ });
961
+ Object.defineProperty(exports, "msteamsConfigAdapter", {
962
+ enumerable: true,
963
+ get: function() {
964
+ return msteamsConfigAdapter;
965
+ }
966
+ });
967
+ Object.defineProperty(exports, "msteamsSetupAdapter", {
968
+ enumerable: true,
969
+ get: function() {
970
+ return msteamsSetupAdapter;
971
+ }
972
+ });
973
+ Object.defineProperty(exports, "msteamsSetupPlugin", {
974
+ enumerable: true,
975
+ get: function() {
976
+ return msteamsSetupPlugin;
977
+ }
978
+ });
979
+ Object.defineProperty(exports, "msteamsSetupWizard", {
980
+ enumerable: true,
981
+ get: function() {
982
+ return msteamsSetupWizard;
983
+ }
984
+ });
985
+ Object.defineProperty(exports, "openDelegatedOAuthUrl", {
986
+ enumerable: true,
987
+ get: function() {
988
+ return openDelegatedOAuthUrl;
989
+ }
990
+ });