@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.
- package/dist/.setup/{adapter.runtime-D0HYByze.cjs → adapter.runtime-JoPydWqP.cjs} +1 -1
- package/dist/.setup/{approval-handler.runtime-C-RJ3wXc.cjs → approval-handler.runtime-bUN9icMr.cjs} +3 -3
- package/dist/.setup/{bot-framework-service-url-BUhTe8F3.cjs → bot-framework-service-url-CPp4d-Q6.cjs} +1 -5
- package/dist/.setup/{channel-BFhXodl2.cjs → channel-Cifn9fsv.cjs} +230 -430
- package/dist/.setup/{channel.runtime-D9jrw2SN.cjs → channel.runtime-DWRAolil.cjs} +70 -44
- package/dist/.setup/{channel.setup-ss0TO-ap.cjs → channel.setup-BjbHugkL.cjs} +5 -7
- package/dist/.setup/{config-schema-0KoBzb0t.cjs → config-schema-Dk0mRIam.cjs} +1 -1
- package/dist/.setup/{conversation-store-state-f7V8CVNy.cjs → conversation-store-state-DprmOfl7.cjs} +103 -236
- package/dist/.setup/{monitor-DfSPCRkk.cjs → monitor-C9x_CJhY.cjs} +173 -322
- package/dist/.setup/oauth-CWJ85AMw.cjs +55 -0
- package/dist/.setup/{reaction-types-B-GEv57k.cjs → reaction-types-Ig9sQJuR.cjs} +3 -3
- package/dist/.setup/{resolve-allowlist-Ct9yxQUw.cjs → resolve-allowlist-DdDBVCzl.cjs} +77 -174
- package/dist/.setup/{send-7VV1iCai.cjs → send-rJpcVtRp.cjs} +8 -9
- package/dist/.setup/{setup-plugin-api-B0OFG32J.cjs → setup-plugin-api-DfoVOqMJ.cjs} +1 -1
- package/dist/.setup/{thread-session-ClI-lSyG.cjs → thread-session-B74FC1Id.cjs} +1 -1
- package/dist/.setup/{token-config-DOt3XwVa.cjs → token-config-CqIh8z7Q.cjs} +6 -7
- package/dist/api.cjs +2 -2
- package/dist/channel-config-api.cjs +1 -1
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/directory-contract-api.cjs +2 -2
- package/dist/doctor-contract-api.cjs +10 -3
- package/dist/qa-runner-api.cjs +9 -10
- package/dist/setup-entry.cjs +1 -1
- package/dist/setup-plugin-api.cjs +1 -1
- package/package.json +4 -4
- 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-
|
|
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,
|
|
61
|
-
const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top
|
|
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-
|
|
4
|
-
const require_token_config = require("./token-config-
|
|
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
|
-
|
|
135
|
-
|
|
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
|
-
|
|
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
|
-
|
|
246
|
-
|
|
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(
|
|
256
|
-
if (!
|
|
257
|
-
if (
|
|
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
|
-
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
-
|
|
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
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
613
|
-
if (creds.useManagedIdentity) return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1115
|
-
if (
|
|
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 =
|
|
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 =
|
|
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] :
|
|
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 =
|
|
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 =
|
|
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-
|
|
4
|
-
const require_bot_framework_service_url = require("./bot-framework-service-url-
|
|
5
|
-
const require_token_config = require("./token-config-
|
|
6
|
-
const require_channel = require("./channel-
|
|
7
|
-
const require_channel_setup = require("./channel.setup-
|
|
8
|
-
const require_conversation_store_state = require("./conversation-store-state-
|
|
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
|
|
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,4 +1,4 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
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(
|
|
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(
|
|
29
|
-
return normalizeMSTeamsDelegatedTokens(await openDelegatedTokenStore(
|
|
27
|
+
async function loadMSTeamsDelegatedTokens() {
|
|
28
|
+
return normalizeMSTeamsDelegatedTokens(await openDelegatedTokenStore().lookup("current")) ?? void 0;
|
|
30
29
|
}
|
|
31
|
-
async function saveMSTeamsDelegatedTokens(tokens
|
|
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(
|
|
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-
|
|
3
|
-
const require_channel_setup = require("./.setup/channel.setup-
|
|
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-
|
|
2
|
+
const require_config_schema = require("./.setup/config-schema-Dk0mRIam.cjs");
|
|
3
3
|
exports.MSTeamsChannelConfigSchema = require_config_schema.MSTeamsChannelConfigSchema;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_resolve_allowlist = require("./.setup/resolve-allowlist-
|
|
3
|
-
const require_token_config = require("./.setup/token-config-
|
|
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",
|