@openclaw/msteams 2026.10.1-beta.2 → 2026.10.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/.setup/{adapter.runtime-D0HYByze.cjs → adapter.runtime-JoPydWqP.cjs} +1 -1
  2. package/dist/.setup/{approval-handler.runtime-C-RJ3wXc.cjs → approval-handler.runtime-bUN9icMr.cjs} +3 -3
  3. package/dist/.setup/{bot-framework-service-url-BUhTe8F3.cjs → bot-framework-service-url-CPp4d-Q6.cjs} +1 -5
  4. package/dist/.setup/{channel-BFhXodl2.cjs → channel-Cifn9fsv.cjs} +230 -430
  5. package/dist/.setup/{channel.runtime-D9jrw2SN.cjs → channel.runtime-DWRAolil.cjs} +70 -44
  6. package/dist/.setup/{channel.setup-ss0TO-ap.cjs → channel.setup-BjbHugkL.cjs} +5 -7
  7. package/dist/.setup/{config-schema-0KoBzb0t.cjs → config-schema-Dk0mRIam.cjs} +1 -1
  8. package/dist/.setup/{conversation-store-state-f7V8CVNy.cjs → conversation-store-state-DprmOfl7.cjs} +103 -236
  9. package/dist/.setup/{monitor-DfSPCRkk.cjs → monitor-C9x_CJhY.cjs} +173 -322
  10. package/dist/.setup/oauth-CWJ85AMw.cjs +55 -0
  11. package/dist/.setup/{reaction-types-B-GEv57k.cjs → reaction-types-Ig9sQJuR.cjs} +3 -3
  12. package/dist/.setup/{resolve-allowlist-Ct9yxQUw.cjs → resolve-allowlist-DdDBVCzl.cjs} +77 -174
  13. package/dist/.setup/{send-7VV1iCai.cjs → send-rJpcVtRp.cjs} +8 -9
  14. package/dist/.setup/{setup-plugin-api-B0OFG32J.cjs → setup-plugin-api-DfoVOqMJ.cjs} +1 -1
  15. package/dist/.setup/{thread-session-ClI-lSyG.cjs → thread-session-B74FC1Id.cjs} +1 -1
  16. package/dist/.setup/{token-config-DOt3XwVa.cjs → token-config-CqIh8z7Q.cjs} +6 -7
  17. package/dist/api.cjs +2 -2
  18. package/dist/channel-config-api.cjs +1 -1
  19. package/dist/channel-plugin-api.cjs +1 -1
  20. package/dist/directory-contract-api.cjs +2 -2
  21. package/dist/doctor-contract-api.cjs +10 -3
  22. package/dist/qa-runner-api.cjs +9 -10
  23. package/dist/setup-entry.cjs +1 -1
  24. package/dist/setup-plugin-api.cjs +1 -1
  25. package/package.json +4 -4
  26. package/dist/.setup/oauth-CYxMYIOQ.cjs +0 -102
@@ -0,0 +1,55 @@
1
+ const require_resolve_allowlist = require("./resolve-allowlist-DdDBVCzl.cjs");
2
+ let openclaw_plugin_sdk_provider_auth = require("openclaw/plugin-sdk/provider-auth");
3
+ let openclaw_plugin_sdk_provider_auth_runtime = require("openclaw/plugin-sdk/provider-auth-runtime");
4
+ //#region extensions/msteams/src/oauth.flow.ts
5
+ function buildMSTeamsAuthUrl(params) {
6
+ const scopes = params.scopes ?? require_resolve_allowlist.MSTEAMS_DEFAULT_DELEGATED_SCOPES;
7
+ return `${require_resolve_allowlist.buildMSTeamsAuthEndpoint(params.tenantId)}?${new URLSearchParams({
8
+ client_id: params.clientId,
9
+ response_type: "code",
10
+ redirect_uri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
11
+ scope: scopes.join(" "),
12
+ code_challenge: params.challenge,
13
+ code_challenge_method: "S256",
14
+ state: params.state,
15
+ prompt: "consent"
16
+ }).toString()}`;
17
+ }
18
+ //#endregion
19
+ //#region extensions/msteams/src/oauth.ts
20
+ async function loginMSTeamsDelegated(ctx, params) {
21
+ await ctx.note([
22
+ "You are running in a remote/VPS environment.",
23
+ "A URL will be shown for you to open in your LOCAL browser.",
24
+ "After signing in, copy the redirect URL and paste it back here."
25
+ ].join("\n"), "MSTeams Delegated OAuth");
26
+ const { verifier, challenge } = (0, openclaw_plugin_sdk_provider_auth.generateHexPkceVerifierChallenge)();
27
+ const state = (0, openclaw_plugin_sdk_provider_auth_runtime.generateOAuthState)();
28
+ const authUrl = buildMSTeamsAuthUrl({
29
+ tenantId: params.tenantId,
30
+ clientId: params.clientId,
31
+ challenge,
32
+ state,
33
+ scopes: require_resolve_allowlist.MSTEAMS_DEFAULT_DELEGATED_SCOPES
34
+ });
35
+ ctx.progress.update("OAuth URL ready");
36
+ ctx.log(`\nOpen this URL in your LOCAL browser:\n\n${authUrl}\n`);
37
+ ctx.progress.update("Waiting for you to paste the callback URL...");
38
+ const callbackInput = await ctx.prompt("Paste the redirect URL here: ");
39
+ const parsed = (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(callbackInput, {
40
+ missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
41
+ invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
42
+ });
43
+ if ("error" in parsed) throw new Error(parsed.error);
44
+ if (parsed.state !== state) throw new Error("OAuth state mismatch - please try again");
45
+ ctx.progress.update("Exchanging authorization code for tokens...");
46
+ return require_resolve_allowlist.exchangeMSTeamsCodeForTokens({
47
+ tenantId: params.tenantId,
48
+ clientId: params.clientId,
49
+ clientSecret: params.clientSecret,
50
+ code: parsed.code,
51
+ verifier
52
+ });
53
+ }
54
+ //#endregion
55
+ exports.loginMSTeamsDelegated = loginMSTeamsDelegated;
@@ -1,4 +1,4 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-Ct9yxQUw.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-DdDBVCzl.cjs");
2
2
  //#region extensions/msteams/src/graph-thread.ts
3
3
  /**
4
4
  * Strip HTML tags from Teams message content, preserving @mention display names.
@@ -57,8 +57,8 @@ async function fetchChatMessageText(token, chatId, messageId, deadline) {
57
57
  * Graph API workaround for this; pagination via `@odata.nextLink` can retrieve more
58
58
  * replies but still in ascending order only.
59
59
  */
60
- async function fetchThreadReplies(token, groupId, channelId, messageId, limit = 50, deadline) {
61
- const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top=${Math.min(Math.max(limit, 1), 50)}`;
60
+ async function fetchThreadReplies(token, groupId, channelId, messageId, deadline) {
61
+ const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top=50`;
62
62
  return (await require_resolve_allowlist.fetchGraphJson({
63
63
  token,
64
64
  path,
@@ -1,7 +1,7 @@
1
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
2
2
  require("../runtime-api.cjs");
3
- const require_bot_framework_service_url = require("./bot-framework-service-url-BUhTe8F3.cjs");
4
- const require_token_config = require("./token-config-DOt3XwVa.cjs");
3
+ const require_bot_framework_service_url = require("./bot-framework-service-url-CPp4d-Q6.cjs");
4
+ const require_token_config = require("./token-config-CqIh8z7Q.cjs");
5
5
  let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
6
6
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
7
7
  let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
@@ -131,12 +131,8 @@ const GRAPH_SHARED_LINK_HOST_SUFFIXES = [
131
131
  "onedrive.com"
132
132
  ];
133
133
  function isGraphSharedLinkUrl(url) {
134
- let parsed;
135
- try {
136
- parsed = new URL(url);
137
- } catch {
138
- return false;
139
- }
134
+ const parsed = URL.parse(url);
135
+ if (!parsed) return false;
140
136
  const host = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(parsed.hostname);
141
137
  if (parsed.protocol !== "https:" || !host) return false;
142
138
  return GRAPH_SHARED_LINK_HOST_SUFFIXES.some((suffix) => host === suffix || host.endsWith(suffix.startsWith(".") ? suffix : `.${suffix}`));
@@ -161,9 +157,9 @@ function normalizeContentType(value) {
161
157
  return `${trimmed.slice(0, parameterIndex).trim().toLowerCase()}${trimmed.slice(parameterIndex)}`;
162
158
  }
163
159
  function resolveMSTeamsMediaKind(params) {
164
- const mime = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.contentType ?? "");
165
- const name = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.fileName ?? "");
166
- const fileType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.fileType ?? "");
160
+ const mime = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.contentType);
161
+ const name = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.fileName);
162
+ const fileType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(params.fileType);
167
163
  return mime.startsWith("image/") || IMAGE_EXT_RE.test(name) || IMAGE_EXT_RE.test(`x.${fileType}`) ? "image" : "document";
168
164
  }
169
165
  function isLikelyImageAttachment(att) {
@@ -195,11 +191,7 @@ function extractHtmlFromAttachment(att) {
195
191
  return typeof att.content.text === "string" ? att.content.text : typeof att.content.body === "string" ? att.content.body : typeof att.content.content === "string" ? att.content.content : void 0;
196
192
  }
197
193
  function fileHintFromUrl(src) {
198
- try {
199
- return new URL(src).pathname.split("/").pop() || void 0;
200
- } catch {
201
- return;
202
- }
194
+ return URL.parse(src)?.pathname.split("/").pop() || void 0;
203
195
  }
204
196
  function extractInlineImageReferences(attachments) {
205
197
  const out = [];
@@ -242,19 +234,16 @@ function extractInlineImageReferences(attachments) {
242
234
  return out;
243
235
  }
244
236
  function safeHostForUrl(url) {
245
- try {
246
- return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(new URL(url).hostname);
247
- } catch {
248
- return "invalid-url";
249
- }
237
+ const parsed = URL.parse(url);
238
+ return parsed ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(parsed.hostname) : "invalid-url";
250
239
  }
251
240
  function isMockFetchFn(fetchFn) {
252
241
  const candidate = fetchFn;
253
242
  return Boolean(candidate.mock || Object.hasOwn(candidate, "_isMockFunction"));
254
243
  }
255
- function resolveGuardedFetchImpl(params) {
256
- if (!params.fetchFn) return;
257
- if (params.fetchFnSupportsDispatcher === true || params.fetchFn === fetch || params.fetchFn === globalThis.fetch || isMockFetchFn(params.fetchFn)) return params.fetchFn;
244
+ function resolveGuardedFetchImpl(fetchFn) {
245
+ if (!fetchFn) return;
246
+ if (fetchFn === fetch || fetchFn === globalThis.fetch || isMockFetchFn(fetchFn)) return fetchFn;
258
247
  throw new Error("MSTeams attachment fetchFn must set fetchFnSupportsDispatcher to use guarded DNS pinning");
259
248
  }
260
249
  function resolveRetainedAuthorizationRedirectHostnameAllowlist(input) {
@@ -272,16 +261,6 @@ function applyAuthorizationHeaderForUrl(params) {
272
261
  if (params.bearerToken && (0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(params.url, params.authAllowHosts)) params.headers.set("Authorization", `Bearer ${params.bearerToken}`);
273
262
  else params.headers.delete("Authorization");
274
263
  }
275
- async function resolveAndValidateIP(hostname, resolveFn) {
276
- const resolve = resolveFn ?? node_dns_promises.lookup;
277
- let resolved;
278
- try {
279
- resolved = await resolve(hostname);
280
- } catch {
281
- throw new Error(`DNS resolution failed for "${hostname}"`);
282
- }
283
- if ((0, openclaw_plugin_sdk_ssrf_policy.isPrivateIpAddress)(resolved.address)) throw new Error(`Hostname "${hostname}" resolves to private/reserved IP (${resolved.address})`);
284
- }
285
264
  const MAX_SAFE_REDIRECTS = 5;
286
265
  function isRedirectStatus(status) {
287
266
  return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
@@ -297,62 +276,33 @@ function isRedirectStatus(status) {
297
276
  async function safeFetchWithPolicy(params) {
298
277
  const { allowHosts, authAllowHosts } = params.policy;
299
278
  const resolveFn = params.resolveFn ?? node_dns_promises.lookup;
300
- const hasDispatcher = params.requestInit && "dispatcher" in params.requestInit;
301
279
  const currentHeaders = new Headers(params.requestInit?.headers);
302
280
  const currentUrl = params.url;
303
281
  if (!(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(currentUrl, allowHosts)) throw new Error(`Initial download URL blocked: ${currentUrl}`);
304
282
  if (currentHeaders.has("authorization") && !(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(currentUrl, authAllowHosts)) currentHeaders.delete("authorization");
305
- if (!hasDispatcher) {
306
- const lookupFn = async (hostname) => {
307
- const resolved = await resolveFn(hostname);
308
- return [{
309
- ...resolved,
310
- family: resolved.address.includes(":") ? 6 : 4
311
- }];
312
- };
313
- const guarded = await (0, openclaw_plugin_sdk_ssrf_runtime.fetchWithSsrFGuard)({
314
- url: currentUrl,
315
- fetchImpl: resolveGuardedFetchImpl({
316
- fetchFn: params.fetchFn,
317
- fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher
318
- }),
319
- init: {
320
- ...params.requestInit,
321
- headers: currentHeaders
322
- },
323
- maxRedirects: MAX_SAFE_REDIRECTS,
324
- requireHttps: true,
325
- policy: (0, openclaw_plugin_sdk_ssrf_policy.buildHostnameAllowlistPolicyFromSuffixAllowlist)(allowHosts),
326
- lookupFn,
327
- retainAuthorizationRedirectHostnameAllowlist: resolveRetainedAuthorizationRedirectHostnameAllowlist(authAllowHosts),
328
- auditContext: "msteams.attachment",
329
- timeoutMs: params.timeoutMs ?? 3e4
330
- });
331
- return (0, openclaw_plugin_sdk_fetch_runtime.responseWithRelease)(guarded.response, guarded.release);
332
- }
333
- try {
334
- const initialHost = new URL(currentUrl).hostname;
335
- await resolveAndValidateIP(initialHost, resolveFn);
336
- } catch {
337
- throw new Error(`Initial download URL blocked: ${currentUrl}`);
338
- }
339
- const res = await (params.fetchFn ?? fetch)(currentUrl, {
340
- ...params.requestInit,
341
- headers: currentHeaders,
342
- redirect: "manual"
283
+ const lookupFn = async (hostname) => {
284
+ const resolved = await resolveFn(hostname);
285
+ return [{
286
+ ...resolved,
287
+ family: resolved.address.includes(":") ? 6 : 4
288
+ }];
289
+ };
290
+ const guarded = await (0, openclaw_plugin_sdk_ssrf_runtime.fetchWithSsrFGuard)({
291
+ url: currentUrl,
292
+ fetchImpl: resolveGuardedFetchImpl(params.fetchFn),
293
+ init: {
294
+ ...params.requestInit,
295
+ headers: currentHeaders
296
+ },
297
+ maxRedirects: MAX_SAFE_REDIRECTS,
298
+ requireHttps: true,
299
+ policy: (0, openclaw_plugin_sdk_ssrf_policy.buildHostnameAllowlistPolicyFromSuffixAllowlist)(allowHosts),
300
+ lookupFn,
301
+ retainAuthorizationRedirectHostnameAllowlist: resolveRetainedAuthorizationRedirectHostnameAllowlist(authAllowHosts),
302
+ auditContext: "msteams.attachment",
303
+ timeoutMs: params.timeoutMs ?? 3e4
343
304
  });
344
- if (!isRedirectStatus(res.status)) return res;
345
- const location = res.headers.get("location");
346
- if (!location) return res;
347
- let redirectUrl;
348
- try {
349
- redirectUrl = new URL(location, currentUrl).toString();
350
- } catch {
351
- throw new Error(`Invalid redirect URL: ${location}`);
352
- }
353
- if (!(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(redirectUrl, allowHosts)) throw new Error(`Media redirect target blocked by allowlist: ${redirectUrl}`);
354
- if (currentHeaders.has("authorization") && !(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(redirectUrl, authAllowHosts)) currentHeaders.delete("authorization");
355
- return res;
305
+ return (0, openclaw_plugin_sdk_fetch_runtime.responseWithRelease)(guarded.response, guarded.release);
356
306
  }
357
307
  //#endregion
358
308
  //#region extensions/msteams/src/cloud.ts
@@ -361,19 +311,15 @@ const PUBLIC_MSTEAMS_SERVICE_HOST = "smba.trafficmanager.net";
361
311
  const CHINA_BOT_FRAMEWORK_SERVICE_HOST = "botframework.azure.cn";
362
312
  function normalizeOptionalServiceUrl(value) {
363
313
  const trimmed = value?.trim();
364
- if (!trimmed) return null;
365
- try {
366
- const parsed = new URL(trimmed);
367
- parsed.hash = "";
368
- parsed.search = "";
369
- parsed.pathname = parsed.pathname.replace(/\/+$/, "");
370
- return {
371
- value: parsed.toString().replace(/\/+$/, ""),
372
- host: parsed.hostname.toLowerCase()
373
- };
374
- } catch {
375
- return null;
376
- }
314
+ const parsed = trimmed ? URL.parse(trimmed) : null;
315
+ if (!parsed) return null;
316
+ parsed.hash = "";
317
+ parsed.search = "";
318
+ parsed.pathname = parsed.pathname.replace(/\/+$/, "");
319
+ return {
320
+ value: parsed.toString().replace(/\/+$/, ""),
321
+ host: parsed.hostname.toLowerCase()
322
+ };
377
323
  }
378
324
  function resolveMSTeamsSdkCloudOptions(cfg) {
379
325
  const cloud = cfg?.cloud ?? DEFAULT_MSTEAMS_CLOUD;
@@ -438,6 +384,7 @@ async function prepareMSTeamsConnectorRequest() {
438
384
  }
439
385
  return assertCurrent;
440
386
  }
387
+ const msteamsConnectorEffectMiddleware = { invoke: (_context, next) => (0, openclaw_plugin_sdk_fetch_runtime.captureEffectAuthority)().initiate(next) };
441
388
  const msteamsConnectorHandoffInterceptor = { request: async ({ config }) => {
442
389
  const assertCurrent = await prepareMSTeamsConnectorRequest();
443
390
  if (!assertCurrent) return config;
@@ -576,7 +523,7 @@ async function createMSTeamsExpressAdapter(serverOrApp) {
576
523
  const { ExpressAdapter } = await loadSdkModules();
577
524
  return new ExpressAdapter(serverOrApp);
578
525
  }
579
- async function createMSTeamsApp(creds, options) {
526
+ async function loadMSTeamsSdkWithAuth(creds, options) {
580
527
  const { App, cloudFromName } = await loadSdkModules();
581
528
  const privateQaRuntime = resolveMSTeamsPrivateQaRuntime();
582
529
  const cloud = options?.cloud ?? "Public";
@@ -585,7 +532,8 @@ async function createMSTeamsApp(creds, options) {
585
532
  client: privateQaRuntime?.client ?? options?.httpClient ?? {
586
533
  headers: { "User-Agent": buildOpenClawUserAgentFragment() },
587
534
  timeout: 3e4,
588
- interceptors: [msteamsConnectorHandoffInterceptor]
535
+ interceptors: [msteamsConnectorHandoffInterceptor],
536
+ middlewares: [msteamsConnectorEffectMiddleware]
589
537
  },
590
538
  ...privateQaRuntime ? {
591
539
  clientSecret: "",
@@ -598,24 +546,15 @@ async function createMSTeamsApp(creds, options) {
598
546
  ...serviceUrl ? { serviceUrl } : {},
599
547
  ...options?.oauthDefaultConnectionName ? { oauth: { defaultConnectionName: options.oauthDefaultConnectionName } } : {}
600
548
  };
601
- if (creds.type === "federated") return await createFederatedApp(creds, App, {
602
- clientSecret: "",
603
- ...appOptions
604
- });
605
- return new App({
549
+ const createApp = (auth) => ({ app: new App({
606
550
  clientId: creds.appId,
607
- clientSecret: creds.appPassword,
608
551
  tenantId: creds.tenantId,
552
+ ...auth,
609
553
  ...appOptions
610
- });
611
- }
612
- async function createFederatedApp(creds, App, appOptions) {
613
- if (creds.useManagedIdentity) return new App({
614
- clientId: creds.appId,
615
- tenantId: creds.tenantId,
616
- managedIdentityClientId: creds.managedIdentityClientId ?? "system",
617
- ...appOptions
618
- });
554
+ }) });
555
+ if (creds.type !== "federated") return createApp({ clientSecret: creds.appPassword });
556
+ appOptions.clientSecret = "";
557
+ if (creds.useManagedIdentity) return createApp({ managedIdentityClientId: creds.managedIdentityClientId ?? "system" });
619
558
  if (!creds.certificatePath) throw new Error("Federated credentials require either a certificate path or managed identity.");
620
559
  let privateKey;
621
560
  try {
@@ -623,21 +562,13 @@ async function createFederatedApp(creds, App, appOptions) {
623
562
  } catch {
624
563
  throw new Error("Failed to read certificate file: the configured credential is unavailable.");
625
564
  }
626
- return createCertificateApp(creds, privateKey, App, appOptions);
627
- }
628
- function createCertificateApp(creds, privateKey, App, appOptions) {
629
565
  let credentialPromise = null;
630
566
  const tokenProvider = async (scope) => {
631
567
  const token = await (await (credentialPromise ??= loadAzureIdentity().then((az) => new az.ClientCertificateCredential(creds.tenantId, creds.appId, { certificate: privateKey })))).getToken(scope);
632
568
  if (!token?.token) throw new Error("Failed to acquire token via certificate credential.");
633
569
  return token.token;
634
570
  };
635
- return new App({
636
- clientId: creds.appId,
637
- tenantId: creds.tenantId,
638
- token: tokenProvider,
639
- ...appOptions
640
- });
571
+ return createApp({ token: tokenProvider });
641
572
  }
642
573
  function createMSTeamsTokenProvider(app) {
643
574
  return { async getAccessToken(scope) {
@@ -648,14 +579,9 @@ function createMSTeamsTokenProvider(app) {
648
579
  return (await app.tokenProvider.getAppToken(app.cloud?.botScope ?? "https://api.botframework.com/.default"))?.toString() ?? "";
649
580
  } };
650
581
  }
651
- async function loadMSTeamsSdkWithAuth(creds, options) {
652
- return { app: await createMSTeamsApp(creds, options) };
653
- }
654
582
  //#endregion
655
583
  //#region extensions/msteams/src/oauth.shared.ts
656
584
  const MSTEAMS_OAUTH_REDIRECT_URI = "http://localhost:8086/oauth2callback";
657
- const MSTEAMS_OAUTH_CALLBACK_PORT = 8086;
658
- const MSTEAMS_OAUTH_CALLBACK_PATH = "/oauth2callback";
659
585
  const MSTEAMS_DEFAULT_TOKEN_FETCH_TIMEOUT_MS = 1e4;
660
586
  const MSTEAMS_DEFAULT_DELEGATED_SCOPES = [
661
587
  "ChatMessage.Send",
@@ -874,8 +800,7 @@ async function fetchGraphAbsoluteUrl(params) {
874
800
  url: params.url,
875
801
  init: { headers: {
876
802
  "User-Agent": buildUserAgent(),
877
- Authorization: `Bearer ${params.token}`,
878
- ...params.headers
803
+ Authorization: `Bearer ${params.token}`
879
804
  } },
880
805
  auditContext: "msteams.graph.absolute",
881
806
  timeoutMs: MSTEAMS_REQUEST_TIMEOUT_MS,
@@ -893,10 +818,6 @@ async function fetchGraphAbsoluteUrl(params) {
893
818
  }
894
819
  }
895
820
  }
896
- /**
897
- * Fetch all pages of a Graph API collection, following @odata.nextLink.
898
- * Optionally stop early when `findOne` matches an item.
899
- */
900
821
  async function fetchAllGraphPages(params) {
901
822
  const maxPages = params.maxPages ?? 50;
902
823
  const items = [];
@@ -1016,9 +937,6 @@ async function findGraphUsersByExactIdentity(params) {
1016
937
  }
1017
938
  //#endregion
1018
939
  //#region extensions/msteams/src/inbound.ts
1019
- /**
1020
- * Strip HTML tags, preserving text content.
1021
- */
1022
940
  function htmlToPlainText(html) {
1023
941
  return (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(html.replace(/<[^>]*>/g, " ")).replaceAll("\xA0", " ").replace(/\s+/g, " ").trim();
1024
942
  }
@@ -1081,17 +999,9 @@ function uniqueItemsById(items) {
1081
999
  }
1082
1000
  return [...byId.values()];
1083
1001
  }
1084
- function findExactNames(items, query) {
1002
+ function findExactMatches(items, query, fields = ["displayName"]) {
1085
1003
  const normalized = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(query);
1086
- return uniqueItemsById(items.filter((item) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(item.displayName) === normalized));
1087
- }
1088
- function findExactUsers(items, query) {
1089
- const normalized = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(query);
1090
- return uniqueItemsById(items.filter((item) => [
1091
- item.displayName,
1092
- item.mail,
1093
- item.userPrincipalName
1094
- ].some((value) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(value) === normalized)));
1004
+ return uniqueItemsById(items.filter((item) => fields.some((field) => (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(item[field]) === normalized)));
1095
1005
  }
1096
1006
  function isStableMSTeamsUserId(raw) {
1097
1007
  return /^[0-9a-fA-F-]{16,}$/.test(normalizeMSTeamsUserInput(raw));
@@ -1103,20 +1013,21 @@ function normalizeStaticMSTeamsAllowEntry(raw) {
1103
1013
  const id = normalizeMSTeamsUserInput(trimmed);
1104
1014
  return isStableMSTeamsUserId(id) ? id : void 0;
1105
1015
  }
1106
- function projectStableMSTeamsUserAllowlist(entries) {
1107
- if (!entries) return;
1108
- const projected = entries.map((entry) => normalizeStaticMSTeamsAllowEntry(entry)).filter((entry) => Boolean(entry));
1109
- return [...new Map(projected.map((entry) => [(0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(entry), entry])).values()];
1110
- }
1111
- function projectStableMSTeamsGroupAllowlist(entries) {
1016
+ function projectStableMSTeamsAllowlist(entries, allowConversations) {
1112
1017
  if (!entries) return;
1113
1018
  const projected = entries.map((entry) => {
1114
- const stableUserEntry = normalizeStaticMSTeamsAllowEntry(entry);
1115
- if (stableUserEntry) return stableUserEntry;
1019
+ const stable = normalizeStaticMSTeamsAllowEntry(entry);
1020
+ if (stable || !allowConversations) return stable;
1116
1021
  const conversationId = normalizeMSTeamsConversationId(normalizeMSTeamsUserInput(entry));
1117
1022
  return MSTEAMS_GROUP_CONVERSATION_ID.test(conversationId) ? conversationId : void 0;
1118
1023
  }).filter((entry) => Boolean(entry));
1119
- return [...new Map(projected.map((entry) => [MSTEAMS_GROUP_CONVERSATION_ID.test(entry) ? `conversation:${entry}` : (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(entry), entry])).values()];
1024
+ return [...new Map(projected.map((entry) => [allowConversations && MSTEAMS_GROUP_CONVERSATION_ID.test(entry) ? `conversation:${entry}` : (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(entry), entry])).values()];
1025
+ }
1026
+ function projectStableMSTeamsUserAllowlist(entries) {
1027
+ return projectStableMSTeamsAllowlist(entries, false);
1028
+ }
1029
+ function projectStableMSTeamsGroupAllowlist(entries) {
1030
+ return projectStableMSTeamsAllowlist(entries, true);
1120
1031
  }
1121
1032
  function stripProviderPrefix(raw) {
1122
1033
  return raw.replace(/^(msteams|teams):/i, "");
@@ -1283,7 +1194,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1283
1194
  resolved: false,
1284
1195
  note: "team lookup incomplete"
1285
1196
  };
1286
- const exactTeams = findExactNames(result.items, team);
1197
+ const exactTeams = findExactMatches(result.items, team);
1287
1198
  const [exactTeam] = exactTeams;
1288
1199
  if (!exactTeam) return {
1289
1200
  input,
@@ -1327,7 +1238,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1327
1238
  note: "channel lookup failed"
1328
1239
  };
1329
1240
  }
1330
- const generalChannels = findExactNames(teamChannels, "general");
1241
+ const generalChannels = findExactMatches(teamChannels, "general");
1331
1242
  if (params.teamIdMode !== "graph" && generalChannels.length !== 1) return {
1332
1243
  input,
1333
1244
  resolved: false,
@@ -1344,7 +1255,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1344
1255
  teamName
1345
1256
  };
1346
1257
  const channelById = teamChannels.find((item) => item.id === channel);
1347
- const exactChannels = channelById ? [channelById] : findExactNames(teamChannels, channel);
1258
+ const exactChannels = channelById ? [channelById] : findExactMatches(teamChannels, channel);
1348
1259
  if (exactChannels.length === 0) return {
1349
1260
  input,
1350
1261
  resolved: false,
@@ -1458,7 +1369,7 @@ async function resolveMSTeamsUserAllowlist(params) {
1458
1369
  return await (0, openclaw_plugin_sdk_allow_from.mapAllowlistResolutionInputs)({
1459
1370
  inputs: params.entries,
1460
1371
  mapInput: async (input) => {
1461
- const query = normalizeQuery(normalizeMSTeamsUserInput(input));
1372
+ const query = normalizeMSTeamsUserInput(input);
1462
1373
  if (!query) return {
1463
1374
  input,
1464
1375
  resolved: false
@@ -1477,7 +1388,11 @@ async function resolveMSTeamsUserAllowlist(params) {
1477
1388
  resolved: false,
1478
1389
  note: "user lookup incomplete"
1479
1390
  };
1480
- const users = findExactUsers(result.items, query);
1391
+ const users = findExactMatches(result.items, query, [
1392
+ "displayName",
1393
+ "mail",
1394
+ "userPrincipalName"
1395
+ ]);
1481
1396
  const [match] = users;
1482
1397
  if (!match) return {
1483
1398
  input,
@@ -1523,18 +1438,6 @@ Object.defineProperty(exports, "MSTEAMS_DEFAULT_DELEGATED_SCOPES", {
1523
1438
  return MSTEAMS_DEFAULT_DELEGATED_SCOPES;
1524
1439
  }
1525
1440
  });
1526
- Object.defineProperty(exports, "MSTEAMS_OAUTH_CALLBACK_PATH", {
1527
- enumerable: true,
1528
- get: function() {
1529
- return MSTEAMS_OAUTH_CALLBACK_PATH;
1530
- }
1531
- });
1532
- Object.defineProperty(exports, "MSTEAMS_OAUTH_CALLBACK_PORT", {
1533
- enumerable: true,
1534
- get: function() {
1535
- return MSTEAMS_OAUTH_CALLBACK_PORT;
1536
- }
1537
- });
1538
1441
  Object.defineProperty(exports, "MSTEAMS_OAUTH_REDIRECT_URI", {
1539
1442
  enumerable: true,
1540
1443
  get: function() {
@@ -1,11 +1,11 @@
1
1
  const require_runtime = require("./runtime-gZTAuFux.cjs");
2
2
  require("../runtime-api.cjs");
3
- const require_resolve_allowlist = require("./resolve-allowlist-Ct9yxQUw.cjs");
4
- const require_bot_framework_service_url = require("./bot-framework-service-url-BUhTe8F3.cjs");
5
- const require_token_config = require("./token-config-DOt3XwVa.cjs");
6
- const require_channel = require("./channel-BFhXodl2.cjs");
7
- const require_channel_setup = require("./channel.setup-ss0TO-ap.cjs");
8
- const require_conversation_store_state = require("./conversation-store-state-f7V8CVNy.cjs");
3
+ const require_resolve_allowlist = require("./resolve-allowlist-DdDBVCzl.cjs");
4
+ const require_bot_framework_service_url = require("./bot-framework-service-url-CPp4d-Q6.cjs");
5
+ const require_token_config = require("./token-config-CqIh8z7Q.cjs");
6
+ const require_channel = require("./channel-Cifn9fsv.cjs");
7
+ const require_channel_setup = require("./channel.setup-BjbHugkL.cjs");
8
+ const require_conversation_store_state = require("./conversation-store-state-DprmOfl7.cjs");
9
9
  let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
10
10
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
11
11
  let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
@@ -196,13 +196,13 @@ function createMSTeamsSendReceipt(params) {
196
196
  return receipt;
197
197
  }
198
198
  function createMSTeamsSendResult(params) {
199
- const platformMessageIds = (params.platformMessageIds?.length ? [...params.platformMessageIds] : [params.messageId]).map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown");
199
+ const platformMessageId = params.messageId.trim();
200
200
  return {
201
201
  messageId: params.messageId,
202
202
  conversationId: params.conversationId,
203
203
  receipt: createMSTeamsSendReceipt({
204
204
  conversationId: params.conversationId,
205
- platformMessageIds,
205
+ platformMessageIds: platformMessageId && platformMessageId !== "unknown" ? [platformMessageId] : [],
206
206
  kind: params.kind
207
207
  }),
208
208
  ...params.pendingUploadId ? { pendingUploadId: params.pendingUploadId } : {}
@@ -386,7 +386,6 @@ async function sendTextWithMedia(ctx, text, mediaUrl, options) {
386
386
  app,
387
387
  conversationRef: ref,
388
388
  messages,
389
- retry: {},
390
389
  onRetry: (event) => {
391
390
  log.debug?.("retrying send", {
392
391
  conversationId,
@@ -1,3 +1,3 @@
1
- const require_channel_setup = require("./channel.setup-ss0TO-ap.cjs");
1
+ const require_channel_setup = require("./channel.setup-BjbHugkL.cjs");
2
2
  require("../setup-plugin-api.cjs");
3
3
  exports.msteamsSetupPlugin = require_channel_setup.msteamsSetupPlugin;
@@ -1,4 +1,4 @@
1
- const require_resolve_allowlist = require("./resolve-allowlist-Ct9yxQUw.cjs");
1
+ const require_resolve_allowlist = require("./resolve-allowlist-DdDBVCzl.cjs");
2
2
  let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
3
3
  let openclaw_plugin_sdk_approval_auth_runtime = require("openclaw/plugin-sdk/approval-auth-runtime");
4
4
  let openclaw_plugin_sdk_routing = require("openclaw/plugin-sdk/routing");
@@ -5,12 +5,11 @@ let openclaw_plugin_sdk_secret_input = require("openclaw/plugin-sdk/secret-input
5
5
  const MSTEAMS_DELEGATED_TOKEN_LEGACY_FILENAME = "msteams-delegated.json";
6
6
  const MSTEAMS_DELEGATED_TOKEN_NAMESPACE = "delegated-token";
7
7
  const MSTEAMS_DELEGATED_TOKEN_KEY = "current";
8
- function openDelegatedTokenStore(env) {
8
+ function openDelegatedTokenStore() {
9
9
  return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
10
10
  namespace: MSTEAMS_DELEGATED_TOKEN_NAMESPACE,
11
11
  maxEntries: 1,
12
- overflowPolicy: "reject-new",
13
- ...env ? { env } : {}
12
+ overflowPolicy: "reject-new"
14
13
  });
15
14
  }
16
15
  function normalizeMSTeamsDelegatedTokens(value) {
@@ -25,13 +24,13 @@ function normalizeMSTeamsDelegatedTokens(value) {
25
24
  ...typeof token.userPrincipalName === "string" ? { userPrincipalName: token.userPrincipalName } : {}
26
25
  };
27
26
  }
28
- async function loadMSTeamsDelegatedTokens(env) {
29
- return normalizeMSTeamsDelegatedTokens(await openDelegatedTokenStore(env).lookup("current")) ?? void 0;
27
+ async function loadMSTeamsDelegatedTokens() {
28
+ return normalizeMSTeamsDelegatedTokens(await openDelegatedTokenStore().lookup("current")) ?? void 0;
30
29
  }
31
- async function saveMSTeamsDelegatedTokens(tokens, env) {
30
+ async function saveMSTeamsDelegatedTokens(tokens) {
32
31
  const normalized = normalizeMSTeamsDelegatedTokens(tokens);
33
32
  if (!normalized) throw new Error("Invalid Microsoft Teams delegated token payload");
34
- await openDelegatedTokenStore(env).register(MSTEAMS_DELEGATED_TOKEN_KEY, normalized);
33
+ await openDelegatedTokenStore().register(MSTEAMS_DELEGATED_TOKEN_KEY, normalized);
35
34
  }
36
35
  //#endregion
37
36
  //#region extensions/msteams/src/token-config.ts
package/dist/api.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./.setup/channel-BFhXodl2.cjs");
3
- const require_channel_setup = require("./.setup/channel.setup-ss0TO-ap.cjs");
2
+ const require_channel = require("./.setup/channel-Cifn9fsv.cjs");
3
+ const require_channel_setup = require("./.setup/channel.setup-BjbHugkL.cjs");
4
4
  exports.createMSTeamsSetupWizardBase = require_channel_setup.createMSTeamsSetupWizardBase;
5
5
  exports.msteamsPlugin = require_channel.msteamsPlugin;
6
6
  exports.msteamsSetupAdapter = require_channel_setup.msteamsSetupAdapter;
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_config_schema = require("./.setup/config-schema-0KoBzb0t.cjs");
2
+ const require_config_schema = require("./.setup/config-schema-Dk0mRIam.cjs");
3
3
  exports.MSTeamsChannelConfigSchema = require_config_schema.MSTeamsChannelConfigSchema;
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_channel = require("./.setup/channel-BFhXodl2.cjs");
2
+ const require_channel = require("./.setup/channel-Cifn9fsv.cjs");
3
3
  exports.msteamsPlugin = require_channel.msteamsPlugin;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_resolve_allowlist = require("./.setup/resolve-allowlist-Ct9yxQUw.cjs");
3
- const require_token_config = require("./.setup/token-config-DOt3XwVa.cjs");
2
+ const require_resolve_allowlist = require("./.setup/resolve-allowlist-DdDBVCzl.cjs");
3
+ const require_token_config = require("./.setup/token-config-CqIh8z7Q.cjs");
4
4
  let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
5
5
  const msteamsDirectoryContractPlugin = {
6
6
  id: "msteams",