@openclaw/msteams 2026.9.6 → 2026.9.7

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 (33) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{adapter.runtime-CQWZeqB5.cjs → adapter.runtime-BiWeMKXE.cjs} +21 -29
  3. package/dist/.setup/{approval-card-CPNH_q3P.cjs → approval-card-DWPDItvq.cjs} +6 -3
  4. package/dist/.setup/{approval-handler.runtime-CUnanUdR.cjs → approval-handler.runtime-D1s7UR3U.cjs} +4 -4
  5. package/dist/.setup/bot-framework-service-url-BUhTe8F3.cjs +55 -0
  6. package/dist/.setup/{channel-BDp16XRR.cjs → channel-ByzS7QJ0.cjs} +286 -180
  7. package/dist/.setup/{channel.runtime-Cv5F8JCa.cjs → channel.runtime-Baz8XDFs.cjs} +43 -142
  8. package/dist/.setup/{channel.setup-BVDfgdCc.cjs → channel.setup-DL8lcWT_.cjs} +6 -6
  9. package/dist/.setup/{config-schema-D22Lr1Qk.cjs → config-schema-0KoBzb0t.cjs} +24 -38
  10. package/dist/.setup/{messenger-8RA1FUJa.cjs → conversation-store-state-B7JuyZTm.cjs} +693 -287
  11. package/dist/.setup/{src-BfOCwlHp.cjs → monitor-BJ7IyH4y.cjs} +422 -592
  12. package/dist/.setup/{oauth-C6m7dvHj.cjs → oauth-DQjOnJ4l.cjs} +1 -1
  13. package/dist/.setup/{reaction-types-C7RA7Wxt.cjs → reaction-types-CQ4oSUe7.cjs} +2 -6
  14. package/dist/.setup/{resolve-allowlist-CHzaaWiC.cjs → resolve-allowlist-Pl_NQFYH.cjs} +55 -312
  15. package/dist/.setup/{rolldown-runtime-VH7oDXx4.cjs → rolldown-runtime-BloeesfJ.cjs} +22 -0
  16. package/dist/.setup/{send-CYN_N7O1.cjs → send-VUM7Sryb.cjs} +43 -96
  17. package/dist/.setup/{setup-plugin-api-DpiaA8z1.cjs → setup-plugin-api-Dyf8kF-l.cjs} +1 -1
  18. package/dist/.setup/{thread-session-CXgHK-yi.cjs → thread-session--rw3BTal.cjs} +2 -5
  19. package/dist/api.cjs +2 -2
  20. package/dist/channel-config-api.cjs +1 -1
  21. package/dist/channel-plugin-api.cjs +1 -1
  22. package/dist/configured-state.cjs +0 -1
  23. package/dist/directory-contract-api.cjs +1 -1
  24. package/dist/doctor-contract-api.cjs +201 -371
  25. package/dist/qa-runner-api.cjs +1 -1
  26. package/dist/runtime-api.cjs +0 -6
  27. package/dist/setup-entry.cjs +1 -1
  28. package/dist/setup-plugin-api.cjs +1 -1
  29. package/openclaw.plugin.json +46 -5
  30. package/package.json +9 -9
  31. package/dist/.setup/polls-BJ4-4uZm.cjs +0 -668
  32. package/dist/.setup/secret-input-C65t6kjM.cjs +0 -1
  33. package/dist/.setup/sso-token-store-YYLHXgFH.cjs +0 -111
@@ -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");
3
4
  const require_delegated_state = require("./delegated-state-u-ywZyZT.cjs");
4
- require("./secret-input-C65t6kjM.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");
@@ -17,8 +17,8 @@ let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text
17
17
  let openclaw_plugin_sdk_secret_file = require("openclaw/plugin-sdk/secret-file");
18
18
  let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
19
19
  let node_module = require("node:module");
20
- let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
21
20
  let openclaw_plugin_sdk_secret_input = require("openclaw/plugin-sdk/secret-input");
21
+ let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
22
22
  //#region extensions/msteams/src/request-timeout.ts
23
23
  const MSTEAMS_REQUEST_TIMEOUT_MS = 3e4;
24
24
  const MSTEAMS_SHAREPOINT_UPLOAD_BASE_TIMEOUT_MS = 3e5;
@@ -131,11 +131,6 @@ const GRAPH_SHARED_LINK_HOST_SUFFIXES = [
131
131
  "onedrive.live.com",
132
132
  "onedrive.com"
133
133
  ];
134
- /**
135
- * Returns true when the URL points at a SharePoint or OneDrive host whose
136
- * shared-link content must be fetched through the Graph shares API rather
137
- * than directly.
138
- */
139
134
  function isGraphSharedLinkUrl(url) {
140
135
  let parsed;
141
136
  try {
@@ -155,12 +150,6 @@ function isGraphSharedLinkUrl(url) {
155
150
  function encodeGraphShareId(url) {
156
151
  return `u!${node_buffer.Buffer.from(url, "utf8").toString("base64url")}`;
157
152
  }
158
- /**
159
- * When `url` is a SharePoint/OneDrive shared link, return the matching
160
- * `GET /shares/{shareId}/driveItem/content` URL that actually yields the file
161
- * bytes. Returns `undefined` for non-shared-link URLs so callers can fall
162
- * through to the existing fetch path.
163
- */
164
153
  function tryBuildGraphSharesUrlForSharedLink(url) {
165
154
  if (!isGraphSharedLinkUrl(url)) return;
166
155
  return `${GRAPH_ROOT}/shares/${encodeGraphShareId(url)}/driveItem/content`;
@@ -201,25 +190,17 @@ function isLikelyImageAttachment(att) {
201
190
  }
202
191
  return false;
203
192
  }
204
- /**
205
- * Returns true if the attachment can be downloaded (any file type).
206
- * Used when downloading all files, not just images.
207
- */
208
193
  function isDownloadableAttachment(att) {
209
194
  if ((normalizeContentType(att.contentType) ?? "") === "application/vnd.microsoft.teams.file.download.info" && (0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(att.content) && typeof att.content.downloadUrl === "string") return true;
210
- if (typeof att.contentUrl === "string" && att.contentUrl.trim()) return true;
211
- return false;
195
+ return typeof att.contentUrl === "string" && Boolean(att.contentUrl.trim());
212
196
  }
213
197
  function isAdvertisedFileAttachment(attachment) {
214
198
  const contentType = normalizeContentType(attachment.contentType) ?? "";
215
199
  if (contentType.startsWith("text/html") || contentType.startsWith("application/vnd.microsoft.card.") || contentType.startsWith("application/vnd.microsoft.teams.card.")) return false;
216
200
  return Boolean(isDownloadableAttachment(attachment) || isLikelyImageAttachment(attachment) || attachment.name?.trim() || contentType);
217
201
  }
218
- function isHtmlAttachment(att) {
219
- return (normalizeContentType(att.contentType) ?? "").startsWith("text/html");
220
- }
221
202
  function extractHtmlFromAttachment(att) {
222
- if (!isHtmlAttachment(att)) return;
203
+ if (!normalizeContentType(att.contentType)?.startsWith("text/html")) return;
223
204
  if (typeof att.content === "string") return att.content;
224
205
  if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(att.content)) return;
225
206
  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;
@@ -242,8 +223,7 @@ function extractInlineImageReferences(attachments) {
242
223
  const html = extractHtmlFromAttachment(att);
243
224
  if (!html) continue;
244
225
  IMG_SRC_RE.lastIndex = 0;
245
- let match = IMG_SRC_RE.exec(html);
246
- while (match) {
226
+ for (const match of html.matchAll(IMG_SRC_RE)) {
247
227
  const src = match[1]?.trim();
248
228
  if (src) {
249
229
  if (src.startsWith("data:")) out.push({
@@ -258,7 +238,6 @@ function extractInlineImageReferences(attachments) {
258
238
  kind: "unavailable",
259
239
  sourceId
260
240
  });
261
- match = IMG_SRC_RE.exec(html);
262
241
  continue;
263
242
  }
264
243
  out.push({
@@ -269,7 +248,6 @@ function extractInlineImageReferences(attachments) {
269
248
  });
270
249
  }
271
250
  }
272
- match = IMG_SRC_RE.exec(html);
273
251
  }
274
252
  }
275
253
  return out;
@@ -281,12 +259,6 @@ function safeHostForUrl(url) {
281
259
  return "invalid-url";
282
260
  }
283
261
  }
284
- function resolveAllowedHosts(input) {
285
- return (0, openclaw_plugin_sdk_ssrf_policy.normalizeHostnameSuffixAllowlist)(input, DEFAULT_MEDIA_HOST_ALLOWLIST);
286
- }
287
- function resolveAuthAllowedHosts(input) {
288
- return (0, openclaw_plugin_sdk_ssrf_policy.normalizeHostnameSuffixAllowlist)(input, DEFAULT_MEDIA_AUTH_HOST_ALLOWLIST);
289
- }
290
262
  function isMockFetchFn(fetchFn) {
291
263
  const candidate = fetchFn;
292
264
  return Boolean(candidate.mock || Object.hasOwn(candidate, "_isMockFunction"));
@@ -299,44 +271,25 @@ function resolveGuardedFetchImpl(params) {
299
271
  function resolveRetainedAuthorizationRedirectHostnameAllowlist(input) {
300
272
  if (!input) return;
301
273
  if (input.includes("*")) return ["*"];
302
- return resolveMediaSsrfPolicy(input)?.hostnameAllowlist;
274
+ return (0, openclaw_plugin_sdk_ssrf_policy.buildHostnameAllowlistPolicyFromSuffixAllowlist)(input)?.hostnameAllowlist;
303
275
  }
304
276
  function resolveAttachmentFetchPolicy(params) {
305
277
  return {
306
- allowHosts: resolveAllowedHosts(params?.allowHosts),
307
- authAllowHosts: resolveAuthAllowedHosts(params?.authAllowHosts)
278
+ allowHosts: (0, openclaw_plugin_sdk_ssrf_policy.normalizeHostnameSuffixAllowlist)(params?.allowHosts, DEFAULT_MEDIA_HOST_ALLOWLIST),
279
+ authAllowHosts: (0, openclaw_plugin_sdk_ssrf_policy.normalizeHostnameSuffixAllowlist)(params?.authAllowHosts, DEFAULT_MEDIA_AUTH_HOST_ALLOWLIST)
308
280
  };
309
281
  }
310
- function isUrlAllowed(url, allowlist) {
311
- return (0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(url, allowlist);
312
- }
313
282
  function applyAuthorizationHeaderForUrl(params) {
314
283
  if (!params.bearerToken) {
315
284
  params.headers.delete("Authorization");
316
285
  return;
317
286
  }
318
- if (isUrlAllowed(params.url, params.authAllowHosts)) {
287
+ if ((0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(params.url, params.authAllowHosts)) {
319
288
  params.headers.set("Authorization", `Bearer ${params.bearerToken}`);
320
289
  return;
321
290
  }
322
291
  params.headers.delete("Authorization");
323
292
  }
324
- function resolveMediaSsrfPolicy(allowHosts) {
325
- return (0, openclaw_plugin_sdk_ssrf_policy.buildHostnameAllowlistPolicyFromSuffixAllowlist)(allowHosts);
326
- }
327
- /**
328
- * Returns true if the given IPv4 or IPv6 address is in a private, loopback,
329
- * or link-local range that must never be reached from media downloads.
330
- *
331
- * Delegates to the SDK's `isPrivateIpAddress` which handles IPv4-mapped IPv6,
332
- * expanded notation, NAT64, 6to4, Teredo, octal IPv4, and fails closed on
333
- * parse errors.
334
- */
335
- const isPrivateOrReservedIP = openclaw_plugin_sdk_ssrf_policy.isPrivateIpAddress;
336
- /**
337
- * Resolve a hostname via DNS and reject private/reserved IPs.
338
- * Throws if the resolved IP is private or resolution fails.
339
- */
340
293
  async function resolveAndValidateIP(hostname, resolveFn) {
341
294
  const resolve = resolveFn ?? node_dns_promises.lookup;
342
295
  let resolved;
@@ -345,10 +298,9 @@ async function resolveAndValidateIP(hostname, resolveFn) {
345
298
  } catch {
346
299
  throw new Error(`DNS resolution failed for "${hostname}"`);
347
300
  }
348
- if (isPrivateOrReservedIP(resolved.address)) throw new Error(`Hostname "${hostname}" resolves to private/reserved IP (${resolved.address})`);
301
+ if ((0, openclaw_plugin_sdk_ssrf_policy.isPrivateIpAddress)(resolved.address)) throw new Error(`Hostname "${hostname}" resolves to private/reserved IP (${resolved.address})`);
349
302
  return resolved.address;
350
303
  }
351
- /** Maximum number of redirects to follow in safeFetch. */
352
304
  const MAX_SAFE_REDIRECTS = 5;
353
305
  function isRedirectStatus(status) {
354
306
  return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
@@ -361,13 +313,14 @@ function isRedirectStatus(status) {
361
313
  * - Auto-following redirects to non-allowlisted hosts
362
314
  * - DNS rebinding attacks when a lookup function is provided
363
315
  */
364
- async function safeFetch(params) {
316
+ async function safeFetchWithPolicy(params) {
317
+ const { allowHosts, authAllowHosts } = params.policy;
365
318
  const resolveFn = params.resolveFn ?? node_dns_promises.lookup;
366
319
  const hasDispatcher = Boolean(params.requestInit && typeof params.requestInit === "object" && "dispatcher" in params.requestInit);
367
320
  const currentHeaders = new Headers(params.requestInit?.headers);
368
321
  const currentUrl = params.url;
369
- if (!isUrlAllowed(currentUrl, params.allowHosts)) throw new Error(`Initial download URL blocked: ${currentUrl}`);
370
- if (currentHeaders.has("authorization") && params.authorizationAllowHosts && !isUrlAllowed(currentUrl, params.authorizationAllowHosts)) currentHeaders.delete("authorization");
322
+ if (!(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(currentUrl, allowHosts)) throw new Error(`Initial download URL blocked: ${currentUrl}`);
323
+ if (currentHeaders.has("authorization") && !(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(currentUrl, authAllowHosts)) currentHeaders.delete("authorization");
371
324
  if (!hasDispatcher) {
372
325
  const lookupFn = async (hostname) => {
373
326
  const resolved = await resolveFn(hostname);
@@ -388,9 +341,9 @@ async function safeFetch(params) {
388
341
  },
389
342
  maxRedirects: MAX_SAFE_REDIRECTS,
390
343
  requireHttps: true,
391
- policy: resolveMediaSsrfPolicy(params.allowHosts),
344
+ policy: (0, openclaw_plugin_sdk_ssrf_policy.buildHostnameAllowlistPolicyFromSuffixAllowlist)(allowHosts),
392
345
  lookupFn,
393
- retainAuthorizationRedirectHostnameAllowlist: resolveRetainedAuthorizationRedirectHostnameAllowlist(params.authorizationAllowHosts),
346
+ retainAuthorizationRedirectHostnameAllowlist: resolveRetainedAuthorizationRedirectHostnameAllowlist(authAllowHosts),
394
347
  auditContext: "msteams.attachment",
395
348
  timeoutMs: params.timeoutMs ?? 3e4
396
349
  });
@@ -416,22 +369,10 @@ async function safeFetch(params) {
416
369
  } catch {
417
370
  throw new Error(`Invalid redirect URL: ${location}`);
418
371
  }
419
- if (!isUrlAllowed(redirectUrl, params.allowHosts)) throw new Error(`Media redirect target blocked by allowlist: ${redirectUrl}`);
420
- if (currentHeaders.has("authorization") && params.authorizationAllowHosts && !isUrlAllowed(redirectUrl, params.authorizationAllowHosts)) currentHeaders.delete("authorization");
372
+ if (!(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(redirectUrl, allowHosts)) throw new Error(`Media redirect target blocked by allowlist: ${redirectUrl}`);
373
+ if (currentHeaders.has("authorization") && !(0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(redirectUrl, authAllowHosts)) currentHeaders.delete("authorization");
421
374
  return res;
422
375
  }
423
- async function safeFetchWithPolicy(params) {
424
- return await safeFetch({
425
- url: params.url,
426
- allowHosts: params.policy.allowHosts,
427
- authorizationAllowHosts: params.policy.authAllowHosts,
428
- fetchFn: params.fetchFn,
429
- fetchFnSupportsDispatcher: params.fetchFnSupportsDispatcher,
430
- requestInit: params.requestInit,
431
- resolveFn: params.resolveFn,
432
- timeoutMs: params.timeoutMs
433
- });
434
- }
435
376
  //#endregion
436
377
  //#region extensions/msteams/src/cloud.ts
437
378
  const DEFAULT_MSTEAMS_CLOUD = "Public";
@@ -465,66 +406,25 @@ function resolveMSTeamsSdkCloudOptions(cfg) {
465
406
  function isChinaBotFrameworkServiceHost(host) {
466
407
  return host === CHINA_BOT_FRAMEWORK_SERVICE_HOST || host.endsWith(`.${CHINA_BOT_FRAMEWORK_SERVICE_HOST}`);
467
408
  }
468
- function isChinaBotFrameworkServiceUrl(value) {
469
- const parsed = normalizeOptionalServiceUrl(value);
470
- return Boolean(parsed && isChinaBotFrameworkServiceHost(parsed.host));
471
- }
472
409
  function validateMSTeamsProactiveServiceUrlBoundary(params) {
473
410
  const configured = normalizeOptionalServiceUrl(params.configuredServiceUrl);
474
411
  if (params.cloud !== "Public" && params.cloud !== "China" && !configured) throw new Error(`msteams proactive send blocked for ${params.conversationId}: channels.msteams.cloud=${params.cloud} requires channels.msteams.serviceUrl so SDK proactive operations use the matching Teams Bot Connector endpoint.`);
475
412
  if (params.cloud === "China" && configured && !isChinaBotFrameworkServiceHost(configured.host)) throw new Error(`msteams proactive send blocked for ${params.conversationId}: configured Teams serviceUrl (${configured.value}) is not a Microsoft Teams China Bot Framework channel endpoint.`);
476
413
  if (params.cloud !== "China" && configured && isChinaBotFrameworkServiceHost(configured.host)) throw new Error(`msteams proactive send blocked for ${params.conversationId}: configured Teams serviceUrl (${configured.value}) requires channels.msteams.cloud=China.`);
414
+ const stored = normalizeOptionalServiceUrl(params.storedServiceUrl);
415
+ if (!stored) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation reference is missing a valid serviceUrl. Ask the bot to receive a new Teams message in this conversation, then retry.`);
477
416
  if (configured) {
478
- const stored = normalizeOptionalServiceUrl(params.storedServiceUrl);
479
- if (!stored) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation reference is missing a valid serviceUrl. Ask the bot to receive a new Teams message in this conversation, then retry.`);
480
417
  if (stored.host !== configured.host) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation serviceUrl (${stored.value}) does not match configured Teams SDK serviceUrl host (${configured.host}). Set channels.msteams.cloud/channels.msteams.serviceUrl for the Teams cloud that owns this conversation, or refresh the stored conversation by receiving a new message.`);
481
418
  return;
482
419
  }
483
- const stored = normalizeOptionalServiceUrl(params.storedServiceUrl);
484
- if (!stored) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation reference is missing a valid serviceUrl. Ask the bot to receive a new Teams message in this conversation, then retry.`);
485
420
  if (params.cloud === "China") {
486
421
  if (!isChinaBotFrameworkServiceHost(stored.host)) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation serviceUrl (${stored.value}) is not a Microsoft Teams China Bot Framework channel endpoint. Use a conversation reference received from the China/21Vianet Teams cloud.`);
487
422
  return;
488
423
  }
489
- if (isChinaBotFrameworkServiceUrl(stored.value)) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation serviceUrl (${stored.value}) requires channels.msteams.cloud=China.`);
424
+ if (isChinaBotFrameworkServiceHost(stored.host)) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation serviceUrl (${stored.value}) requires channels.msteams.cloud=China.`);
490
425
  if (stored.host !== PUBLIC_MSTEAMS_SERVICE_HOST) throw new Error(`msteams proactive send blocked for ${params.conversationId}: stored conversation serviceUrl (${stored.value}) is not a Microsoft Teams public-cloud Bot Connector endpoint. Set channels.msteams.cloud and channels.msteams.serviceUrl for the supported Teams cloud that owns this conversation.`);
491
426
  }
492
427
  //#endregion
493
- //#region extensions/msteams/src/http-error.ts
494
- async function createMSTeamsHttpError(response, label, options) {
495
- return await (0, openclaw_plugin_sdk_provider_http.createProviderHttpError)(response, label, options);
496
- }
497
- //#endregion
498
- //#region extensions/msteams/src/bot-framework-service-url.ts
499
- const BOT_FRAMEWORK_SERVICE_URL_HOST_ALLOWLIST = (0, openclaw_plugin_sdk_ssrf_policy.normalizeHostnameSuffixAllowlist)([
500
- "smba.trafficmanager.net",
501
- "smba.infra.gcc.teams.microsoft.com",
502
- "smba.infra.gov.teams.microsoft.us",
503
- "smba.infra.dod.teams.microsoft.us",
504
- "botframework.azure.cn"
505
- ]);
506
- function describeBotFrameworkServiceUrlHost(serviceUrl) {
507
- try {
508
- return new URL(serviceUrl.trim()).hostname || "invalid-url";
509
- } catch {
510
- return "invalid-url";
511
- }
512
- }
513
- function isAllowedBotFrameworkServiceUrl(serviceUrl) {
514
- if (typeof serviceUrl !== "string") return false;
515
- const trimmed = serviceUrl.trim();
516
- return Boolean(trimmed && (0, openclaw_plugin_sdk_ssrf_policy.isHttpsUrlAllowedByHostnameSuffixAllowlist)(trimmed, BOT_FRAMEWORK_SERVICE_URL_HOST_ALLOWLIST));
517
- }
518
- function tryNormalizeBotFrameworkServiceUrl(serviceUrl) {
519
- if (!isAllowedBotFrameworkServiceUrl(serviceUrl)) return;
520
- return serviceUrl.trim().replace(/\/+$/, "");
521
- }
522
- function normalizeBotFrameworkServiceUrl(serviceUrl) {
523
- const normalized = tryNormalizeBotFrameworkServiceUrl(serviceUrl);
524
- if (normalized) return normalized;
525
- throw new Error(`Blocked Microsoft Teams serviceUrl host: ${describeBotFrameworkServiceUrlHost(serviceUrl)}`);
526
- }
527
- //#endregion
528
428
  //#region extensions/msteams/src/send-handoff.ts
529
429
  const connectorHandoff = new node_async_hooks.AsyncLocalStorage();
530
430
  function notDispatched(error) {
@@ -577,30 +477,13 @@ const msteamsConnectorHandoffInterceptor = { request: async ({ config }) => {
577
477
  const PRIVATE_QA_BUILD_ENV = "OPENCLAW_BUILD_PRIVATE_QA";
578
478
  const PRIVATE_QA_NONCE_HEADER = "x-openclaw-msteams-qa-nonce";
579
479
  const PRIVATE_QA_RUNTIME_SYMBOL = Symbol.for("openclaw.msteams.privateQaRuntime");
580
- var PrivateQaHttpClient = class PrivateQaHttpClient {
581
- constructor(connectorUrl, nonce, options = {}) {
582
- this.connectorUrl = connectorUrl;
583
- this.nonce = nonce;
584
- this.options = options;
585
- }
586
- clone(options = {}) {
587
- return new PrivateQaHttpClient(this.connectorUrl, this.nonce, {
588
- ...this.options,
589
- ...options,
590
- headers: {
591
- ...this.options.headers,
592
- ...options.headers
593
- }
594
- });
595
- }
596
- async request(config) {
480
+ function createPrivateQaClientOptions(connectorUrl, nonce) {
481
+ const request = async (config) => {
597
482
  const sourceUrl = new URL(config.url ?? "", "https://smba.trafficmanager.net");
598
- const targetUrl = new URL(`${sourceUrl.pathname}${sourceUrl.search}`, this.connectorUrl);
599
- const headers = new Headers(this.options.headers);
483
+ const targetUrl = new URL(`${sourceUrl.pathname}${sourceUrl.search}`, connectorUrl);
484
+ const headers = new Headers();
600
485
  for (const [key, value] of Object.entries(config.headers ?? {})) if (value != null) headers.set(key, String(value));
601
- headers.set(PRIVATE_QA_NONCE_HEADER, this.nonce);
602
- const token = typeof this.options.token === "function" ? await this.options.token() : this.options.token;
603
- if (token) headers.set("authorization", `Bearer ${token}`);
486
+ headers.set(PRIVATE_QA_NONCE_HEADER, nonce);
604
487
  const method = String(config.method ?? "GET").toUpperCase();
605
488
  const assertCurrent = await prepareMSTeamsConnectorRequest();
606
489
  const { response, release } = await (0, openclaw_plugin_sdk_ssrf_runtime.fetchWithSsrFGuard)({
@@ -629,46 +512,12 @@ var PrivateQaHttpClient = class PrivateQaHttpClient {
629
512
  } finally {
630
513
  await release();
631
514
  }
632
- }
633
- get(url, config = {}) {
634
- return this.request({
635
- ...config,
636
- method: "GET",
637
- url
638
- });
639
- }
640
- post(url, data, config = {}) {
641
- return this.request({
642
- ...config,
643
- data,
644
- method: "POST",
645
- url
646
- });
647
- }
648
- put(url, data, config = {}) {
649
- return this.request({
650
- ...config,
651
- data,
652
- method: "PUT",
653
- url
654
- });
655
- }
656
- patch(url, data, config = {}) {
657
- return this.request({
658
- ...config,
659
- data,
660
- method: "PATCH",
661
- url
662
- });
663
- }
664
- delete(url, config = {}) {
665
- return this.request({
666
- ...config,
667
- method: "DELETE",
668
- url
669
- });
670
- }
671
- };
515
+ };
516
+ return { interceptors: [{ request: ({ config }) => {
517
+ config.adapter = request;
518
+ return config;
519
+ } }] };
520
+ }
672
521
  function resolveMSTeamsPrivateQaRuntime(env = process.env, bootstrap = globalThis[PRIVATE_QA_RUNTIME_SYMBOL]) {
673
522
  if (!bootstrap) return;
674
523
  if (env[PRIVATE_QA_BUILD_ENV] !== "1") throw new Error("Microsoft Teams private QA runtime requires OPENCLAW_BUILD_PRIVATE_QA=1");
@@ -679,8 +528,7 @@ function resolveMSTeamsPrivateQaRuntime(env = process.env, bootstrap = globalThi
679
528
  const parsedConnectorUrl = new URL(connectorUrl);
680
529
  if (parsedConnectorUrl.protocol !== "http:" || parsedConnectorUrl.hostname !== "127.0.0.1" && parsedConnectorUrl.hostname !== "localhost") throw new Error("Microsoft Teams private QA connector must use loopback HTTP");
681
530
  return {
682
- client: new PrivateQaHttpClient(parsedConnectorUrl.toString(), nonce),
683
- listenHost: "127.0.0.1",
531
+ client: createPrivateQaClientOptions(parsedConnectorUrl.toString(), nonce),
684
532
  skipAuth: true,
685
533
  token: async () => botToken
686
534
  };
@@ -765,7 +613,7 @@ async function createMSTeamsApp(creds, options) {
765
613
  const { App, cloudFromName } = await loadSdkModules();
766
614
  const privateQaRuntime = resolveMSTeamsPrivateQaRuntime();
767
615
  const cloud = options?.cloud ?? "Public";
768
- const serviceUrl = options?.serviceUrl ? normalizeBotFrameworkServiceUrl(options.serviceUrl) : void 0;
616
+ const serviceUrl = options?.serviceUrl ? require_bot_framework_service_url.normalizeBotFrameworkServiceUrl(options.serviceUrl) : void 0;
769
617
  const appOptions = {
770
618
  client: privateQaRuntime?.client ?? options?.httpClient ?? {
771
619
  headers: { "User-Agent": buildOpenClawUserAgentFragment() },
@@ -828,37 +676,19 @@ function createCertificateApp(creds, privateKey, App, appOptions) {
828
676
  ...appOptions
829
677
  });
830
678
  }
831
- /**
832
- * Build a token provider that uses the Teams SDK App's public tokenManager
833
- * for token acquisition.
834
- */
835
679
  function createMSTeamsTokenProvider(app) {
836
- const tokenToString = (token) => {
837
- if (token == null) return "";
838
- return token.toString();
839
- };
840
680
  return { async getAccessToken(scope) {
841
681
  if (scope.includes("graph.microsoft.com") || scope.includes("graph.microsoft.us") || scope.includes("microsoftgraph.chinacloudapi.cn")) {
842
682
  if (app.cloud?.graphScope?.includes("microsoftgraph.chinacloudapi.cn")) throw new Error("Microsoft Teams Graph operations are not supported for channels.msteams.cloud=China until Graph requests are routed through the Azure China Graph endpoint.");
843
- return tokenToString(await app.tokenManager.getGraphToken());
683
+ return (await app.tokenProvider.getAppToken(app.cloud?.graphScope ?? "https://graph.microsoft.com/.default", app.credentials?.tenantId || "common"))?.toString() ?? "";
844
684
  }
845
- return tokenToString(await app.tokenManager.getBotToken());
685
+ return (await app.tokenProvider.getAppToken(app.cloud?.botScope ?? "https://api.botframework.com/.default"))?.toString() ?? "";
846
686
  } };
847
687
  }
848
688
  async function loadMSTeamsSdkWithAuth(creds, options) {
849
689
  return { app: await createMSTeamsApp(creds, options) };
850
690
  }
851
691
  //#endregion
852
- //#region extensions/msteams/src/token-response.ts
853
- function readAccessToken(value) {
854
- if (typeof value === "string") return value;
855
- if (value && typeof value === "object") {
856
- const token = value.accessToken ?? value.token;
857
- return typeof token === "string" ? token : null;
858
- }
859
- return null;
860
- }
861
- //#endregion
862
692
  //#region extensions/msteams/src/oauth.shared.ts
863
693
  const MSTEAMS_OAUTH_REDIRECT_URI = "http://localhost:8086/oauth2callback";
864
694
  const MSTEAMS_OAUTH_CALLBACK_PORT = 8086;
@@ -880,25 +710,9 @@ function buildMSTeamsTokenEndpoint(tenantId) {
880
710
  //#region extensions/msteams/src/oauth.token.ts
881
711
  /** Five-minute buffer subtracted from token expiry to avoid edge-case clock drift. */
882
712
  const EXPIRY_BUFFER_MS = 3e5;
883
- function createMSTeamsTokenBody(params) {
884
- const body = new URLSearchParams({
885
- client_id: params.clientId,
886
- client_secret: params.clientSecret,
887
- grant_type: params.grantType,
888
- scope: [...params.scopes].join(" ")
889
- });
890
- for (const [key, value] of Object.entries(params.values ?? {})) body.set(key, value);
891
- return body;
892
- }
893
- function resolveMSTeamsTokenExpiresAt(value) {
894
- return (0, openclaw_plugin_sdk_number_runtime.resolveExpiresAtMsFromDurationSeconds)(value, { bufferMs: EXPIRY_BUFFER_MS });
895
- }
896
- function assertMSTeamsTokenResponseObject(data, failureLabel) {
897
- if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(data)) throw new Error(`MSTeams ${failureLabel} failed: invalid token response fields`);
898
- return data;
899
- }
900
713
  function parseMSTeamsTokenResponse(data, failureLabel) {
901
- const expiresAt = resolveMSTeamsTokenExpiresAt(data.expires_in);
714
+ if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(data)) throw new Error(`MSTeams ${failureLabel} failed: invalid token response fields`);
715
+ const expiresAt = (0, openclaw_plugin_sdk_number_runtime.resolveExpiresAtMsFromDurationSeconds)(data.expires_in, { bufferMs: EXPIRY_BUFFER_MS });
902
716
  if (typeof data.access_token !== "string" || !data.access_token || expiresAt === void 0 || data.refresh_token !== void 0 && typeof data.refresh_token !== "string" || data.scope !== void 0 && typeof data.scope !== "string") throw new Error(`MSTeams ${failureLabel} failed: invalid token response fields`);
903
717
  return {
904
718
  access_token: data.access_token,
@@ -922,20 +736,20 @@ async function fetchMSTeamsTokens(params) {
922
736
  auditContext: params.auditContext
923
737
  });
924
738
  try {
925
- if (!response.ok) throw await createMSTeamsHttpError(response, `MSTeams ${params.failureLabel} failed`);
926
- return parseMSTeamsTokenResponse(assertMSTeamsTokenResponseObject(await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(response, `MSTeams ${params.failureLabel} failed`), params.failureLabel), params.failureLabel);
739
+ if (!response.ok) throw await (0, openclaw_plugin_sdk_provider_http.createProviderHttpError)(response, `MSTeams ${params.failureLabel} failed`);
740
+ return parseMSTeamsTokenResponse(await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(response, `MSTeams ${params.failureLabel} failed`), params.failureLabel);
927
741
  } finally {
928
742
  await release();
929
743
  }
930
744
  }
931
745
  async function requestMSTeamsDelegatedTokens(params) {
932
746
  const scopes = params.scopes ?? MSTEAMS_DEFAULT_DELEGATED_SCOPES;
933
- const body = createMSTeamsTokenBody({
934
- clientId: params.clientId,
935
- clientSecret: params.clientSecret,
936
- grantType: params.grantType,
937
- scopes,
938
- values: params.values
747
+ const body = new URLSearchParams({
748
+ client_id: params.clientId,
749
+ client_secret: params.clientSecret,
750
+ grant_type: params.grantType,
751
+ scope: scopes.join(" "),
752
+ ...params.values
939
753
  });
940
754
  const data = await fetchMSTeamsTokens({
941
755
  tokenUrl: buildMSTeamsTokenEndpoint(params.tenantId),
@@ -1039,14 +853,8 @@ function resolveMSTeamsCredentials(cfg) {
1039
853
  tenantId
1040
854
  };
1041
855
  }
1042
- function loadDelegatedTokens() {
1043
- return require_delegated_state.loadMSTeamsDelegatedTokens();
1044
- }
1045
- function saveDelegatedTokens(tokens) {
1046
- return require_delegated_state.saveMSTeamsDelegatedTokens(tokens);
1047
- }
1048
856
  async function resolveDelegatedAccessToken(params) {
1049
- const tokens = await loadDelegatedTokens();
857
+ const tokens = await require_delegated_state.loadMSTeamsDelegatedTokens();
1050
858
  if (!tokens) return;
1051
859
  if ((0, openclaw_plugin_sdk_number_runtime.isFutureDateTimestampMs)(tokens.expiresAt)) return tokens.accessToken;
1052
860
  try {
@@ -1057,7 +865,7 @@ async function resolveDelegatedAccessToken(params) {
1057
865
  refreshToken: tokens.refreshToken,
1058
866
  scopes: tokens.scopes
1059
867
  });
1060
- await saveDelegatedTokens(refreshed);
868
+ await require_delegated_state.saveMSTeamsDelegatedTokens(refreshed);
1061
869
  return refreshed.accessToken;
1062
870
  } catch {
1063
871
  return;
@@ -1110,7 +918,7 @@ async function requestGraph(params) {
1110
918
  let releaseInFinally = true;
1111
919
  try {
1112
920
  assertReadAuthority?.();
1113
- if (!response.ok) throw await createMSTeamsHttpError(response, `${params.errorPrefix ?? "Graph"} ${params.path} failed`);
921
+ if (!response.ok) throw await (0, openclaw_plugin_sdk_provider_http.createProviderHttpError)(response, `${params.errorPrefix ?? "Graph"} ${params.path} failed`);
1114
922
  releaseInFinally = false;
1115
923
  return (0, openclaw_plugin_sdk_fetch_runtime.responseWithRelease)(response, release);
1116
924
  } finally {
@@ -1166,7 +974,7 @@ async function fetchGraphAbsoluteUrl(params) {
1166
974
  });
1167
975
  try {
1168
976
  assertReadAuthority?.();
1169
- if (!response.ok) throw await createMSTeamsHttpError(response, `Graph ${params.url} failed`);
977
+ if (!response.ok) throw await (0, openclaw_plugin_sdk_provider_http.createProviderHttpError)(response, `Graph ${params.url} failed`);
1170
978
  return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(response, `Graph ${params.url} failed`);
1171
979
  } finally {
1172
980
  try {
@@ -1226,12 +1034,11 @@ async function resolveGraphToken(cfg, options) {
1226
1034
  const { app } = await loadMSTeamsSdkWithAuth(creds, resolveMSTeamsSdkCloudOptions(msteamsCfg));
1227
1035
  assertRequestCurrent?.();
1228
1036
  const tokenProvider = createMSTeamsTokenProvider(app);
1229
- const graphTokenValue = await withMSTeamsRequestDeadline({
1037
+ const accessToken = await withMSTeamsRequestDeadline({
1230
1038
  label: "MS Teams Graph token",
1231
1039
  work: () => tokenProvider.getAccessToken("https://graph.microsoft.com")
1232
1040
  });
1233
1041
  assertRequestCurrent?.();
1234
- const accessToken = readAccessToken(graphTokenValue);
1235
1042
  if (!accessToken) throw new Error("MS Teams graph token unavailable");
1236
1043
  return accessToken;
1237
1044
  }
@@ -1368,11 +1175,7 @@ function uniqueItemsById(items) {
1368
1175
  }
1369
1176
  return [...byId.values()];
1370
1177
  }
1371
- function findExactTeams(items, query) {
1372
- const normalized = normalizeExactMatch(query);
1373
- return uniqueItemsById(items.filter((item) => normalizeExactMatch(item.displayName) === normalized));
1374
- }
1375
- function findExactChannels(items, query) {
1178
+ function findExactNames(items, query) {
1376
1179
  const normalized = normalizeExactMatch(query);
1377
1180
  return uniqueItemsById(items.filter((item) => normalizeExactMatch(item.displayName) === normalized));
1378
1181
  }
@@ -1580,7 +1383,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1580
1383
  resolved: false,
1581
1384
  note: "team lookup incomplete"
1582
1385
  };
1583
- const exactTeams = findExactTeams(result.items, team);
1386
+ const exactTeams = findExactNames(result.items, team);
1584
1387
  const [exactTeam] = exactTeams;
1585
1388
  if (!exactTeam) return {
1586
1389
  input,
@@ -1624,7 +1427,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1624
1427
  note: "channel lookup failed"
1625
1428
  };
1626
1429
  }
1627
- const generalChannels = findExactChannels(teamChannels, "general");
1430
+ const generalChannels = findExactNames(teamChannels, "general");
1628
1431
  if (params.teamIdMode !== "graph" && generalChannels.length !== 1) return {
1629
1432
  input,
1630
1433
  resolved: false,
@@ -1641,7 +1444,7 @@ async function resolveMSTeamsChannelAllowlist(params) {
1641
1444
  teamName
1642
1445
  };
1643
1446
  const channelById = teamChannels.find((item) => item.id === channel);
1644
- const exactChannels = channelById ? [channelById] : findExactChannels(teamChannels, channel);
1447
+ const exactChannels = channelById ? [channelById] : findExactNames(teamChannels, channel);
1645
1448
  if (exactChannels.length === 0) return {
1646
1449
  input,
1647
1450
  resolved: false,
@@ -1874,12 +1677,6 @@ Object.defineProperty(exports, "createMSTeamsExpressAdapter", {
1874
1677
  return createMSTeamsExpressAdapter;
1875
1678
  }
1876
1679
  });
1877
- Object.defineProperty(exports, "createMSTeamsHttpError", {
1878
- enumerable: true,
1879
- get: function() {
1880
- return createMSTeamsHttpError;
1881
- }
1882
- });
1883
1680
  Object.defineProperty(exports, "createMSTeamsInboundDeadline", {
1884
1681
  enumerable: true,
1885
1682
  get: function() {
@@ -1898,12 +1695,6 @@ Object.defineProperty(exports, "deleteGraphRequest", {
1898
1695
  return deleteGraphRequest;
1899
1696
  }
1900
1697
  });
1901
- Object.defineProperty(exports, "describeBotFrameworkServiceUrlHost", {
1902
- enumerable: true,
1903
- get: function() {
1904
- return describeBotFrameworkServiceUrlHost;
1905
- }
1906
- });
1907
1698
  Object.defineProperty(exports, "encodeGraphShareId", {
1908
1699
  enumerable: true,
1909
1700
  get: function() {
@@ -1988,12 +1779,6 @@ Object.defineProperty(exports, "isAdvertisedFileAttachment", {
1988
1779
  return isAdvertisedFileAttachment;
1989
1780
  }
1990
1781
  });
1991
- Object.defineProperty(exports, "isAllowedBotFrameworkServiceUrl", {
1992
- enumerable: true,
1993
- get: function() {
1994
- return isAllowedBotFrameworkServiceUrl;
1995
- }
1996
- });
1997
1782
  Object.defineProperty(exports, "isDownloadableAttachment", {
1998
1783
  enumerable: true,
1999
1784
  get: function() {
@@ -2012,12 +1797,6 @@ Object.defineProperty(exports, "isRedirectStatus", {
2012
1797
  return isRedirectStatus;
2013
1798
  }
2014
1799
  });
2015
- Object.defineProperty(exports, "isUrlAllowed", {
2016
- enumerable: true,
2017
- get: function() {
2018
- return isUrlAllowed;
2019
- }
2020
- });
2021
1800
  Object.defineProperty(exports, "listChannelsForTeam", {
2022
1801
  enumerable: true,
2023
1802
  get: function() {
@@ -2036,12 +1815,6 @@ Object.defineProperty(exports, "listTeamsByName", {
2036
1815
  return listTeamsByName;
2037
1816
  }
2038
1817
  });
2039
- Object.defineProperty(exports, "loadDelegatedTokens", {
2040
- enumerable: true,
2041
- get: function() {
2042
- return loadDelegatedTokens;
2043
- }
2044
- });
2045
1818
  Object.defineProperty(exports, "loadMSTeamsSdkWithAuth", {
2046
1819
  enumerable: true,
2047
1820
  get: function() {
@@ -2066,12 +1839,6 @@ Object.defineProperty(exports, "mutateGraphJson", {
2066
1839
  return mutateGraphJson;
2067
1840
  }
2068
1841
  });
2069
- Object.defineProperty(exports, "normalizeBotFrameworkServiceUrl", {
2070
- enumerable: true,
2071
- get: function() {
2072
- return normalizeBotFrameworkServiceUrl;
2073
- }
2074
- });
2075
1842
  Object.defineProperty(exports, "normalizeContentType", {
2076
1843
  enumerable: true,
2077
1844
  get: function() {
@@ -2144,12 +1911,6 @@ Object.defineProperty(exports, "projectStableMSTeamsUserAllowlist", {
2144
1911
  return projectStableMSTeamsUserAllowlist;
2145
1912
  }
2146
1913
  });
2147
- Object.defineProperty(exports, "readAccessToken", {
2148
- enumerable: true,
2149
- get: function() {
2150
- return readAccessToken;
2151
- }
2152
- });
2153
1914
  Object.defineProperty(exports, "resolveAttachmentFetchPolicy", {
2154
1915
  enumerable: true,
2155
1916
  get: function() {
@@ -2216,12 +1977,6 @@ Object.defineProperty(exports, "resolveMSTeamsUserAllowlist", {
2216
1977
  return resolveMSTeamsUserAllowlist;
2217
1978
  }
2218
1979
  });
2219
- Object.defineProperty(exports, "resolveMediaSsrfPolicy", {
2220
- enumerable: true,
2221
- get: function() {
2222
- return resolveMediaSsrfPolicy;
2223
- }
2224
- });
2225
1980
  Object.defineProperty(exports, "resolveRequestUrl", {
2226
1981
  enumerable: true,
2227
1982
  get: function() {
@@ -2246,12 +2001,6 @@ Object.defineProperty(exports, "safeHostForUrl", {
2246
2001
  return safeHostForUrl;
2247
2002
  }
2248
2003
  });
2249
- Object.defineProperty(exports, "saveDelegatedTokens", {
2250
- enumerable: true,
2251
- get: function() {
2252
- return saveDelegatedTokens;
2253
- }
2254
- });
2255
2004
  Object.defineProperty(exports, "searchGraphUsers", {
2256
2005
  enumerable: true,
2257
2006
  get: function() {
@@ -2270,12 +2019,6 @@ Object.defineProperty(exports, "tryBuildGraphSharesUrlForSharedLink", {
2270
2019
  return tryBuildGraphSharesUrlForSharedLink;
2271
2020
  }
2272
2021
  });
2273
- Object.defineProperty(exports, "tryNormalizeBotFrameworkServiceUrl", {
2274
- enumerable: true,
2275
- get: function() {
2276
- return tryNormalizeBotFrameworkServiceUrl;
2277
- }
2278
- });
2279
2022
  Object.defineProperty(exports, "validateMSTeamsProactiveServiceUrlBoundary", {
2280
2023
  enumerable: true,
2281
2024
  get: function() {