@openclaw/msteams 2026.5.7 → 2026.5.10-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/api.js +2 -2
- package/dist/{channel-BOwKBAvY.js → channel-kz4Rzh2w.js} +45 -20
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-BC1ruIfN.js → channel.runtime-C1IGCVBT.js} +3 -3
- package/dist/{graph-users-9uQJepqr.js → graph-users-CCU0WVMZ.js} +44 -24
- package/dist/{policy-DTnU2GR7.js → policy-bM71GXRd.js} +2 -10
- package/dist/{probe-D_H8yFps.js → probe-CQKmxtlj.js} +83 -61
- package/dist/{resolve-allowlist-D41JSziq.js → resolve-allowlist-7CHP2hEA.js} +1 -1
- package/dist/{runtime-api-DV1iVMn1.js → runtime-api-C3EIaIpt.js} +3 -3
- package/dist/runtime-api.js +2 -2
- package/dist/setup-plugin-api.js +2 -2
- package/dist/{setup-surface-BLkFQYIQ.js → setup-surface-C7d0jGM5.js} +2 -2
- package/dist/{src-CP7V_TeZ.js → src-DQ7ARgDd.js} +238 -221
- package/dist/test-api.js +1 -1
- package/package.json +7 -7
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as msteamsPlugin } from "./channel-
|
|
2
|
-
import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-
|
|
1
|
+
import { t as msteamsPlugin } from "./channel-kz4Rzh2w.js";
|
|
2
|
+
import { i as msteamsSetupAdapter, n as openDelegatedOAuthUrl, r as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-C7d0jGM5.js";
|
|
3
3
|
export { createMSTeamsSetupWizardBase, msteamsPlugin, msteamsSetupAdapter, msteamsSetupWizard, openDelegatedOAuthUrl };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { o as buildProbeChannelStatusSummary, r as PAIRING_APPROVED_MESSAGE, s as chunkTextForOutbound, t as DEFAULT_ACCOUNT_ID, u as createDefaultChannelRuntimeState } from "./runtime-api-
|
|
2
|
-
import { h as resolveMSTeamsCredentials } from "./graph-users-
|
|
3
|
-
import { a as parseMSTeamsTeamChannelInput, c as resolveMSTeamsUserAllowlist, i as parseMSTeamsConversationId, n as normalizeMSTeamsMessagingTarget, r as normalizeMSTeamsUserInput, s as resolveMSTeamsChannelAllowlist, t as looksLikeMSTeamsTargetId } from "./resolve-allowlist-
|
|
1
|
+
import { o as buildProbeChannelStatusSummary, r as PAIRING_APPROVED_MESSAGE, s as chunkTextForOutbound, t as DEFAULT_ACCOUNT_ID, u as createDefaultChannelRuntimeState } from "./runtime-api-C3EIaIpt.js";
|
|
2
|
+
import { h as resolveMSTeamsCredentials } from "./graph-users-CCU0WVMZ.js";
|
|
3
|
+
import { a as parseMSTeamsTeamChannelInput, c as resolveMSTeamsUserAllowlist, i as parseMSTeamsConversationId, n as normalizeMSTeamsMessagingTarget, r as normalizeMSTeamsUserInput, s as resolveMSTeamsChannelAllowlist, t as looksLikeMSTeamsTargetId } from "./resolve-allowlist-7CHP2hEA.js";
|
|
4
4
|
import { t as MSTeamsChannelConfigSchema } from "./config-schema-DwOEthCC.js";
|
|
5
|
-
import {
|
|
6
|
-
import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-
|
|
5
|
+
import { n as resolveMSTeamsGroupToolPolicy } from "./policy-bM71GXRd.js";
|
|
6
|
+
import { i as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-C7d0jGM5.js";
|
|
7
7
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
8
8
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
9
9
|
import { createTopLevelChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
10
10
|
import { buildChannelOutboundSessionRoute, createChatChannelPlugin, stripChannelTargetPrefix, stripTargetKindPrefix } from "openclaw/plugin-sdk/channel-core";
|
|
11
|
+
import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-message";
|
|
11
12
|
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
|
12
13
|
import { createAllowlistProviderGroupPolicyWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, projectConfigWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
|
13
14
|
import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, listDirectoryEntriesFromSources } from "openclaw/plugin-sdk/directory-runtime";
|
|
@@ -182,7 +183,7 @@ const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarning
|
|
|
182
183
|
resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
|
|
183
184
|
collect: ({ groupPolicy }) => groupPolicy === "open" ? ["- MS Teams groups: groupPolicy=\"open\" allows any member to trigger (mention-gated). Set channels.msteams.groupPolicy=\"allowlist\" + channels.msteams.groupAllowFrom to restrict senders."] : []
|
|
184
185
|
});
|
|
185
|
-
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
186
|
+
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-C1IGCVBT.js"), "msTeamsChannelRuntime");
|
|
186
187
|
const resolveMSTeamsChannelConfig = (cfg) => ({
|
|
187
188
|
allowFrom: cfg.channels?.msteams?.allowFrom,
|
|
188
189
|
defaultTo: cfg.channels?.msteams?.defaultTo
|
|
@@ -376,6 +377,41 @@ function describeMSTeamsMessageTool({ cfg }) {
|
|
|
376
377
|
} : null
|
|
377
378
|
};
|
|
378
379
|
}
|
|
380
|
+
const msteamsChannelOutbound = {
|
|
381
|
+
deliveryMode: "direct",
|
|
382
|
+
chunker: chunkTextForOutbound,
|
|
383
|
+
chunkerMode: "markdown",
|
|
384
|
+
textChunkLimit: 4e3,
|
|
385
|
+
pollMaxOptions: 12,
|
|
386
|
+
deliveryCapabilities: { durableFinal: {
|
|
387
|
+
text: true,
|
|
388
|
+
media: true,
|
|
389
|
+
messageSendingHooks: true
|
|
390
|
+
} },
|
|
391
|
+
...createRuntimeOutboundDelegates({
|
|
392
|
+
getRuntime: loadMSTeamsChannelRuntime,
|
|
393
|
+
sendText: { resolve: (runtime) => runtime.msteamsOutbound.sendText },
|
|
394
|
+
sendMedia: { resolve: (runtime) => runtime.msteamsOutbound.sendMedia },
|
|
395
|
+
sendPoll: { resolve: (runtime) => runtime.msteamsOutbound.sendPoll }
|
|
396
|
+
})
|
|
397
|
+
};
|
|
398
|
+
const msteamsMessageAdapter = createChannelMessageAdapterFromOutbound({
|
|
399
|
+
id: "msteams",
|
|
400
|
+
outbound: msteamsChannelOutbound,
|
|
401
|
+
live: {
|
|
402
|
+
capabilities: {
|
|
403
|
+
draftPreview: true,
|
|
404
|
+
previewFinalization: true,
|
|
405
|
+
progressUpdates: true,
|
|
406
|
+
nativeStreaming: true
|
|
407
|
+
},
|
|
408
|
+
finalizer: { capabilities: {
|
|
409
|
+
finalEdit: true,
|
|
410
|
+
normalFallback: true,
|
|
411
|
+
previewReceipt: true
|
|
412
|
+
} }
|
|
413
|
+
}
|
|
414
|
+
});
|
|
379
415
|
const msteamsPlugin = createChatChannelPlugin({
|
|
380
416
|
base: {
|
|
381
417
|
id: "msteams",
|
|
@@ -428,6 +464,7 @@ const msteamsPlugin = createChatChannelPlugin({
|
|
|
428
464
|
hint: "<conversationId|user:ID|conversation:ID>"
|
|
429
465
|
}
|
|
430
466
|
},
|
|
467
|
+
message: msteamsMessageAdapter,
|
|
431
468
|
directory: createChannelDirectoryAdapter({
|
|
432
469
|
self: async ({ cfg }) => {
|
|
433
470
|
const creds = resolveMSTeamsCredentials(cfg.channels?.msteams);
|
|
@@ -928,7 +965,7 @@ const msteamsPlugin = createChatChannelPlugin({
|
|
|
928
965
|
})
|
|
929
966
|
}),
|
|
930
967
|
gateway: { startAccount: async (ctx) => {
|
|
931
|
-
const { monitorMSTeamsProvider } = await import("./src-
|
|
968
|
+
const { monitorMSTeamsProvider } = await import("./src-DQ7ARgDd.js");
|
|
932
969
|
const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
|
|
933
970
|
ctx.setStatus({
|
|
934
971
|
accountId: ctx.accountId,
|
|
@@ -966,19 +1003,7 @@ const msteamsPlugin = createChatChannelPlugin({
|
|
|
966
1003
|
hasRepliedRef
|
|
967
1004
|
};
|
|
968
1005
|
} },
|
|
969
|
-
outbound:
|
|
970
|
-
deliveryMode: "direct",
|
|
971
|
-
chunker: chunkTextForOutbound,
|
|
972
|
-
chunkerMode: "markdown",
|
|
973
|
-
textChunkLimit: 4e3,
|
|
974
|
-
pollMaxOptions: 12,
|
|
975
|
-
...createRuntimeOutboundDelegates({
|
|
976
|
-
getRuntime: loadMSTeamsChannelRuntime,
|
|
977
|
-
sendText: { resolve: (runtime) => runtime.msteamsOutbound.sendText },
|
|
978
|
-
sendMedia: { resolve: (runtime) => runtime.msteamsOutbound.sendMedia },
|
|
979
|
-
sendPoll: { resolve: (runtime) => runtime.msteamsOutbound.sendPoll }
|
|
980
|
-
})
|
|
981
|
-
}
|
|
1006
|
+
outbound: msteamsChannelOutbound
|
|
982
1007
|
});
|
|
983
1008
|
//#endregion
|
|
984
1009
|
export { msteamsPlugin as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as msteamsPlugin } from "./channel-
|
|
1
|
+
import { t as msteamsPlugin } from "./channel-kz4Rzh2w.js";
|
|
2
2
|
export { msteamsPlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { s as chunkTextForOutbound } from "./runtime-api-
|
|
2
|
-
import { a as fetchGraphJson, c as normalizeQuery, d as postGraphJson, f as resolveGraphToken, i as fetchGraphAbsoluteUrl, l as patchGraphJson, n as deleteGraphRequest, o as listChannelsForTeam, r as escapeOData, s as listTeamsByName, t as searchGraphUsers, u as postGraphBetaJson } from "./graph-users-
|
|
3
|
-
import { S as createMSTeamsConversationStoreFs, a as sendMessageMSTeams, b as createMSTeamsPollStoreFs, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-
|
|
1
|
+
import { s as chunkTextForOutbound } from "./runtime-api-C3EIaIpt.js";
|
|
2
|
+
import { a as fetchGraphJson, c as normalizeQuery, d as postGraphJson, f as resolveGraphToken, i as fetchGraphAbsoluteUrl, l as patchGraphJson, n as deleteGraphRequest, o as listChannelsForTeam, r as escapeOData, s as listTeamsByName, t as searchGraphUsers, u as postGraphBetaJson } from "./graph-users-CCU0WVMZ.js";
|
|
3
|
+
import { S as createMSTeamsConversationStoreFs, a as sendMessageMSTeams, b as createMSTeamsPollStoreFs, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-CQKmxtlj.js";
|
|
4
4
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
|
5
5
|
import { createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
6
6
|
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps";
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as getMSTeamsRuntime, h as fetchWithSsrFGuard$1 } from "./runtime-api-C3EIaIpt.js";
|
|
2
2
|
import { n as refreshMSTeamsDelegatedTokens } from "./oauth.token-xxpoLWy5.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import { isRecord as isRecord$
|
|
4
|
+
import { isRecord as isRecord$2, normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
5
5
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
6
6
|
import { Buffer } from "node:buffer";
|
|
7
7
|
import { lookup } from "node:dns/promises";
|
|
8
8
|
import { buildHostnameAllowlistPolicyFromSuffixAllowlist, isHttpsUrlAllowedByHostnameSuffixAllowlist, isPrivateIpAddress, normalizeHostnameSuffixAllowlist } from "openclaw/plugin-sdk/ssrf-policy";
|
|
9
|
-
import * as fs
|
|
10
|
-
import {
|
|
11
|
-
import path, { dirname } from "node:path";
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import path, { basename, dirname } from "node:path";
|
|
12
|
+
import { privateFileStoreSync } from "openclaw/plugin-sdk/security-runtime";
|
|
12
13
|
import { hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
13
14
|
//#region extensions/msteams/src/attachments/shared.ts
|
|
14
15
|
const IMAGE_EXT_RE = /\.(avif|bmp|gif|heic|heif|jpe?g|png|tiff?|webp)$/i;
|
|
@@ -122,7 +123,7 @@ function tryBuildGraphSharesUrlForSharedLink(url) {
|
|
|
122
123
|
function readNestedString(value, keys) {
|
|
123
124
|
let current = value;
|
|
124
125
|
for (const key of keys) {
|
|
125
|
-
if (!isRecord$
|
|
126
|
+
if (!isRecord$2(current)) return;
|
|
126
127
|
current = current[key];
|
|
127
128
|
}
|
|
128
129
|
return normalizeOptionalString(current);
|
|
@@ -153,7 +154,7 @@ function isLikelyImageAttachment(att) {
|
|
|
153
154
|
const name = typeof att.name === "string" ? att.name : "";
|
|
154
155
|
if (contentType.startsWith("image/")) return true;
|
|
155
156
|
if (IMAGE_EXT_RE.test(name)) return true;
|
|
156
|
-
if (contentType === "application/vnd.microsoft.teams.file.download.info" && isRecord$
|
|
157
|
+
if (contentType === "application/vnd.microsoft.teams.file.download.info" && isRecord$2(att.content)) {
|
|
157
158
|
const fileType = typeof att.content.fileType === "string" ? att.content.fileType : "";
|
|
158
159
|
if (fileType && IMAGE_EXT_RE.test(`x.${fileType}`)) return true;
|
|
159
160
|
const fileName = typeof att.content.fileName === "string" ? att.content.fileName : "";
|
|
@@ -166,7 +167,7 @@ function isLikelyImageAttachment(att) {
|
|
|
166
167
|
* Used when downloading all files, not just images.
|
|
167
168
|
*/
|
|
168
169
|
function isDownloadableAttachment(att) {
|
|
169
|
-
if ((normalizeContentType(att.contentType) ?? "") === "application/vnd.microsoft.teams.file.download.info" && isRecord$
|
|
170
|
+
if ((normalizeContentType(att.contentType) ?? "") === "application/vnd.microsoft.teams.file.download.info" && isRecord$2(att.content) && typeof att.content.downloadUrl === "string") return true;
|
|
170
171
|
if (typeof att.contentUrl === "string" && att.contentUrl.trim()) return true;
|
|
171
172
|
return false;
|
|
172
173
|
}
|
|
@@ -176,7 +177,7 @@ function isHtmlAttachment(att) {
|
|
|
176
177
|
function extractHtmlFromAttachment(att) {
|
|
177
178
|
if (!isHtmlAttachment(att)) return;
|
|
178
179
|
if (typeof att.content === "string") return att.content;
|
|
179
|
-
if (!isRecord$
|
|
180
|
+
if (!isRecord$2(att.content)) return;
|
|
180
181
|
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;
|
|
181
182
|
}
|
|
182
183
|
function isLikelyBase64Payload(value) {
|
|
@@ -387,7 +388,7 @@ async function safeFetchWithPolicy(params) {
|
|
|
387
388
|
}
|
|
388
389
|
//#endregion
|
|
389
390
|
//#region extensions/msteams/src/errors.ts
|
|
390
|
-
function isRecord(value) {
|
|
391
|
+
function isRecord$1(value) {
|
|
391
392
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
392
393
|
}
|
|
393
394
|
function formatUnknownError(err) {
|
|
@@ -405,7 +406,7 @@ function formatUnknownError(err) {
|
|
|
405
406
|
}
|
|
406
407
|
}
|
|
407
408
|
function extractStatusCode(err) {
|
|
408
|
-
if (!isRecord(err)) return null;
|
|
409
|
+
if (!isRecord$1(err)) return null;
|
|
409
410
|
const direct = err.statusCode ?? err.status;
|
|
410
411
|
if (typeof direct === "number" && Number.isFinite(direct)) return direct;
|
|
411
412
|
if (typeof direct === "string") {
|
|
@@ -413,7 +414,7 @@ function extractStatusCode(err) {
|
|
|
413
414
|
if (Number.isFinite(parsed)) return parsed;
|
|
414
415
|
}
|
|
415
416
|
const response = err.response;
|
|
416
|
-
if (isRecord(response)) {
|
|
417
|
+
if (isRecord$1(response)) {
|
|
417
418
|
const status = response.status;
|
|
418
419
|
if (typeof status === "number" && Number.isFinite(status)) return status;
|
|
419
420
|
if (typeof status === "string") {
|
|
@@ -424,20 +425,20 @@ function extractStatusCode(err) {
|
|
|
424
425
|
return null;
|
|
425
426
|
}
|
|
426
427
|
function extractErrorCode(err) {
|
|
427
|
-
if (!isRecord(err)) return null;
|
|
428
|
+
if (!isRecord$1(err)) return null;
|
|
428
429
|
const direct = err.code;
|
|
429
430
|
if (typeof direct === "string" && direct.trim()) return direct;
|
|
430
431
|
const response = err.response;
|
|
431
|
-
if (!isRecord(response)) return null;
|
|
432
|
+
if (!isRecord$1(response)) return null;
|
|
432
433
|
const body = response.body;
|
|
433
|
-
if (isRecord(body)) {
|
|
434
|
+
if (isRecord$1(body)) {
|
|
434
435
|
const error = body.error;
|
|
435
|
-
if (isRecord(error) && typeof error.code === "string" && error.code.trim()) return error.code;
|
|
436
|
+
if (isRecord$1(error) && typeof error.code === "string" && error.code.trim()) return error.code;
|
|
436
437
|
}
|
|
437
438
|
return null;
|
|
438
439
|
}
|
|
439
440
|
function extractRetryAfterMs(err) {
|
|
440
|
-
if (!isRecord(err)) return null;
|
|
441
|
+
if (!isRecord$1(err)) return null;
|
|
441
442
|
const direct = err.retryAfterMs ?? err.retry_after_ms;
|
|
442
443
|
if (typeof direct === "number" && Number.isFinite(direct) && direct >= 0) return direct;
|
|
443
444
|
const retryAfter = err.retryAfter ?? err.retry_after;
|
|
@@ -447,10 +448,10 @@ function extractRetryAfterMs(err) {
|
|
|
447
448
|
if (Number.isFinite(parsed) && parsed >= 0) return parsed * 1e3;
|
|
448
449
|
}
|
|
449
450
|
const response = err.response;
|
|
450
|
-
if (!isRecord(response)) return null;
|
|
451
|
+
if (!isRecord$1(response)) return null;
|
|
451
452
|
const headers = response.headers;
|
|
452
453
|
if (!headers) return null;
|
|
453
|
-
if (isRecord(headers)) {
|
|
454
|
+
if (isRecord$1(headers)) {
|
|
454
455
|
const raw = headers["retry-after"] ?? headers["Retry-After"];
|
|
455
456
|
if (typeof raw === "string") {
|
|
456
457
|
const parsed = Number.parseFloat(raw);
|
|
@@ -512,6 +513,13 @@ function classifyMSTeamsSendError(err) {
|
|
|
512
513
|
statusCode,
|
|
513
514
|
errorCode
|
|
514
515
|
};
|
|
516
|
+
if (statusCode == null) {
|
|
517
|
+
const networkCode = isRecord$1(err) && typeof err.code === "string" ? err.code : null;
|
|
518
|
+
if (networkCode === "ECONNREFUSED" || networkCode === "ENOTFOUND" || networkCode === "EHOSTUNREACH" || networkCode === "ETIMEDOUT" || networkCode === "ECONNRESET") return {
|
|
519
|
+
kind: "network",
|
|
520
|
+
errorCode: networkCode
|
|
521
|
+
};
|
|
522
|
+
}
|
|
515
523
|
return {
|
|
516
524
|
kind: "unknown",
|
|
517
525
|
statusCode: statusCode ?? void 0,
|
|
@@ -536,6 +544,7 @@ function formatMSTeamsSendErrorHint(classification) {
|
|
|
536
544
|
if (classification.errorCode === "ContentStreamNotAllowed") return "Teams expired the content stream; stop streaming earlier and fall back to normal message delivery";
|
|
537
545
|
if (classification.kind === "throttled") return "Teams throttled the bot; backing off may help";
|
|
538
546
|
if (classification.kind === "transient") return "transient Teams/Bot Framework error; retry may succeed";
|
|
547
|
+
if (classification.kind === "network") return "transport-level failure sending reply to Teams Bot Connector (smba.trafficmanager.net) — check egress firewall rules allow outbound HTTPS to smba.trafficmanager.net";
|
|
539
548
|
}
|
|
540
549
|
//#endregion
|
|
541
550
|
//#region extensions/msteams/src/user-agent.ts
|
|
@@ -617,7 +626,7 @@ function createFederatedApp(creds, sdk) {
|
|
|
617
626
|
if (!creds.certificatePath) throw new Error("Federated credentials require either a certificate path or managed identity.");
|
|
618
627
|
let privateKey;
|
|
619
628
|
try {
|
|
620
|
-
privateKey = fs
|
|
629
|
+
privateKey = fs.readFileSync(creds.certificatePath, "utf-8");
|
|
621
630
|
} catch (err) {
|
|
622
631
|
const msg = err instanceof Error ? err.message : String(err);
|
|
623
632
|
throw new Error(`Failed to read certificate file at '${creds.certificatePath}': ${msg}`, { cause: err });
|
|
@@ -1045,11 +1054,23 @@ async function createBotFrameworkJwtValidator(creds) {
|
|
|
1045
1054
|
if (!isJwtPayloadObject(verifiedPayload)) return false;
|
|
1046
1055
|
if (getAudienceClaims(verifiedPayload).includes(BOT_FRAMEWORK_GLOBAL_AUDIENCE) && !hasExpectedBotIdentity(verifiedPayload, creds.appId)) return false;
|
|
1047
1056
|
return true;
|
|
1048
|
-
} catch {
|
|
1057
|
+
} catch (err) {
|
|
1058
|
+
if (isJwksNetworkError(err)) throw err;
|
|
1049
1059
|
return false;
|
|
1050
1060
|
}
|
|
1051
1061
|
} };
|
|
1052
1062
|
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Return true when the error originated from a network-level failure fetching
|
|
1065
|
+
* the JWKS endpoint (DNS resolution, connection refused, TLS handshake, etc.)
|
|
1066
|
+
* rather than from token verification logic.
|
|
1067
|
+
*/
|
|
1068
|
+
function isJwksNetworkError(err) {
|
|
1069
|
+
if (!(err instanceof Error)) return false;
|
|
1070
|
+
const code = err.code;
|
|
1071
|
+
if (code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "EHOSTUNREACH" || code === "ETIMEDOUT" || code === "ECONNRESET") return true;
|
|
1072
|
+
return /jwks|key fetch|getSigningKey/i.test(err.message) && /network|fetch|connect/i.test(err.message);
|
|
1073
|
+
}
|
|
1053
1074
|
//#endregion
|
|
1054
1075
|
//#region extensions/msteams/src/token-response.ts
|
|
1055
1076
|
function readAccessToken(value) {
|
|
@@ -1135,8 +1156,7 @@ function loadDelegatedTokens() {
|
|
|
1135
1156
|
}
|
|
1136
1157
|
function saveDelegatedTokens(tokens) {
|
|
1137
1158
|
const tokenPath = resolveDelegatedTokenPath();
|
|
1138
|
-
|
|
1139
|
-
writeFileSync(tokenPath, JSON.stringify(tokens, null, 2), "utf8");
|
|
1159
|
+
privateFileStoreSync(dirname(tokenPath)).writeJson(basename(tokenPath), tokens);
|
|
1140
1160
|
}
|
|
1141
1161
|
async function resolveDelegatedAccessToken(params) {
|
|
1142
1162
|
const tokens = loadDelegatedTokens();
|
|
@@ -1351,4 +1371,4 @@ async function searchGraphUsers(params) {
|
|
|
1351
1371
|
})).value ?? [];
|
|
1352
1372
|
}
|
|
1353
1373
|
//#endregion
|
|
1354
|
-
export { ATTACHMENT_TAG_RE as A, isLikelyImageAttachment as B, loadMSTeamsSdkWithAuth as C, formatMSTeamsSendErrorHint as D, classifyMSTeamsSendError as E, estimateBase64DecodedBytes as F, resolveAttachmentFetchPolicy as G, isUrlAllowed as H, extractHtmlFromAttachment as I, safeFetchWithPolicy as J, resolveMediaSsrfPolicy as K, extractInlineImageCandidates as L, IMG_SRC_RE as M, applyAuthorizationHeaderForUrl as N, formatUnknownError as O, encodeGraphShareId as P, inferPlaceholder as R, createMSTeamsTokenProvider as S, ensureUserAgentHeader as T, normalizeContentType as U, isRecord$
|
|
1374
|
+
export { ATTACHMENT_TAG_RE as A, isLikelyImageAttachment as B, loadMSTeamsSdkWithAuth as C, formatMSTeamsSendErrorHint as D, classifyMSTeamsSendError as E, estimateBase64DecodedBytes as F, resolveAttachmentFetchPolicy as G, isUrlAllowed as H, extractHtmlFromAttachment as I, safeFetchWithPolicy as J, resolveMediaSsrfPolicy as K, extractInlineImageCandidates as L, IMG_SRC_RE as M, applyAuthorizationHeaderForUrl as N, formatUnknownError as O, encodeGraphShareId as P, inferPlaceholder as R, createMSTeamsTokenProvider as S, ensureUserAgentHeader as T, normalizeContentType as U, isRecord$2 as V, readNestedString as W, tryBuildGraphSharesUrlForSharedLink as X, safeHostForUrl as Y, resolveMSTeamsStorePath as _, fetchGraphJson as a, createBotFrameworkJwtValidator as b, normalizeQuery as c, postGraphJson as d, resolveGraphToken as f, saveDelegatedTokens as g, resolveMSTeamsCredentials as h, fetchGraphAbsoluteUrl as i, GRAPH_ROOT as j, isRevokedProxyError as k, patchGraphJson as l, loadDelegatedTokens as m, deleteGraphRequest as n, listChannelsForTeam as o, hasConfiguredMSTeamsCredentials as p, resolveRequestUrl as q, escapeOData as r, listTeamsByName as s, searchGraphUsers as t, postGraphBetaJson as u, normalizeSecretInputString as v, buildUserAgent as w, createMSTeamsAdapter as x, readAccessToken as y, isDownloadableAttachment as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { O as resolveNestedAllowlistDecision, S as normalizeChannelSlug, T as resolveChannelEntryMatchWithFallback, _ as isDangerousNameMatchingEnabled, i as buildChannelKeyCandidates, k as resolveToolsBySender, w as resolveAllowlistMatchSimple } from "./runtime-api-C3EIaIpt.js";
|
|
2
2
|
//#region extensions/msteams/src/policy.ts
|
|
3
3
|
function resolveMSTeamsRouteConfig(params) {
|
|
4
4
|
const teamId = params.teamId?.trim();
|
|
@@ -130,13 +130,5 @@ function resolveMSTeamsReplyPolicy(params) {
|
|
|
130
130
|
replyStyle: params.channelConfig?.replyStyle ?? params.teamConfig?.replyStyle ?? params.globalConfig?.replyStyle ?? (requireMention ? "thread" : "top-level")
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
-
function isMSTeamsGroupAllowed(params) {
|
|
134
|
-
return evaluateSenderGroupAccessForPolicy({
|
|
135
|
-
groupPolicy: params.groupPolicy,
|
|
136
|
-
groupAllowFrom: params.allowFrom.map((entry) => String(entry)),
|
|
137
|
-
senderId: params.senderId,
|
|
138
|
-
isSenderAllowed: () => resolveMSTeamsAllowlistMatch(params).allowed
|
|
139
|
-
}).allowed;
|
|
140
|
-
}
|
|
141
133
|
//#endregion
|
|
142
|
-
export { resolveMSTeamsRouteConfig as
|
|
134
|
+
export { resolveMSTeamsRouteConfig as i, resolveMSTeamsGroupToolPolicy as n, resolveMSTeamsReplyPolicy as r, resolveMSTeamsAllowlistMatch as t };
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { C as loadMSTeamsSdkWithAuth, D as formatMSTeamsSendErrorHint, E as classifyMSTeamsSendError, O as formatUnknownError, S as createMSTeamsTokenProvider, _ as resolveMSTeamsStorePath, h as resolveMSTeamsCredentials, k as isRevokedProxyError, m as loadDelegatedTokens, w as buildUserAgent, x as createMSTeamsAdapter, y as readAccessToken } from "./graph-users-
|
|
3
|
-
import {
|
|
1
|
+
import { C as normalizeStringEntries, E as resolveChannelMediaMaxBytes, M as getMSTeamsRuntime, d as detectMime, g as getFileExtension, m as extractOriginalFilename, p as extensionForMime, y as loadOutboundMediaFromUrl } from "./runtime-api-C3EIaIpt.js";
|
|
2
|
+
import { C as loadMSTeamsSdkWithAuth, D as formatMSTeamsSendErrorHint, E as classifyMSTeamsSendError, O as formatUnknownError, S as createMSTeamsTokenProvider, _ as resolveMSTeamsStorePath, h as resolveMSTeamsCredentials, k as isRevokedProxyError, m as loadDelegatedTokens, w as buildUserAgent, x as createMSTeamsAdapter, y as readAccessToken } from "./graph-users-CCU0WVMZ.js";
|
|
3
|
+
import { i as resolveMSTeamsRouteConfig, r as resolveMSTeamsReplyPolicy } from "./policy-bM71GXRd.js";
|
|
4
|
+
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-message";
|
|
5
|
+
import { convertMarkdownTables, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, sleep } from "openclaw/plugin-sdk/text-runtime";
|
|
4
6
|
import { withFileLock } from "openclaw/plugin-sdk/file-lock";
|
|
5
7
|
import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
6
8
|
import { lookup } from "node:dns/promises";
|
|
7
|
-
import
|
|
9
|
+
import { isPrivateIpAddress } from "openclaw/plugin-sdk/ssrf-policy";
|
|
8
10
|
import path from "node:path";
|
|
11
|
+
import { pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
9
12
|
import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
|
10
13
|
import crypto from "node:crypto";
|
|
11
14
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
@@ -72,11 +75,7 @@ async function writeJsonFile(filePath, value) {
|
|
|
72
75
|
await writeJsonFileAtomically(filePath, value);
|
|
73
76
|
}
|
|
74
77
|
async function ensureJsonFile(filePath, fallback) {
|
|
75
|
-
|
|
76
|
-
await fs.promises.access(filePath);
|
|
77
|
-
} catch {
|
|
78
|
-
await writeJsonFile(filePath, fallback);
|
|
79
|
-
}
|
|
78
|
+
if (!await pathExists(filePath)) await writeJsonFile(filePath, fallback);
|
|
80
79
|
}
|
|
81
80
|
async function withFileLock$1(filePath, fallback, fn) {
|
|
82
81
|
await ensureJsonFile(filePath, fallback);
|
|
@@ -182,14 +181,6 @@ function createMSTeamsConversationStoreFs(params) {
|
|
|
182
181
|
const STORE_FILENAME$1 = "msteams-polls.json";
|
|
183
182
|
const MAX_POLLS = 1e3;
|
|
184
183
|
const POLL_TTL_MS = 720 * 60 * 60 * 1e3;
|
|
185
|
-
function isRecord(value) {
|
|
186
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
187
|
-
}
|
|
188
|
-
function normalizeOptionalString$1(value) {
|
|
189
|
-
if (typeof value !== "string") return;
|
|
190
|
-
const trimmed = value.trim();
|
|
191
|
-
return trimmed ? trimmed : void 0;
|
|
192
|
-
}
|
|
193
184
|
function normalizeChoiceValue(value) {
|
|
194
185
|
if (typeof value === "string") {
|
|
195
186
|
const trimmed = value.trim();
|
|
@@ -214,7 +205,7 @@ function readNestedValue(value, keys) {
|
|
|
214
205
|
return current;
|
|
215
206
|
}
|
|
216
207
|
function readNestedString(value, keys) {
|
|
217
|
-
return normalizeOptionalString
|
|
208
|
+
return normalizeOptionalString(readNestedValue(value, keys));
|
|
218
209
|
}
|
|
219
210
|
function extractMSTeamsPollVote(activity) {
|
|
220
211
|
const value = activity?.value;
|
|
@@ -395,9 +386,6 @@ function createMSTeamsPollStoreFs(params) {
|
|
|
395
386
|
* - Building FileInfoCard attachments (to confirm upload completion)
|
|
396
387
|
* - Parsing fileConsent/invoke activities
|
|
397
388
|
*/
|
|
398
|
-
function normalizeLowercaseStringOrEmpty$1(value) {
|
|
399
|
-
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
400
|
-
}
|
|
401
389
|
/**
|
|
402
390
|
* Allowlist of domains that are valid targets for file consent uploads.
|
|
403
391
|
* These are the Microsoft/SharePoint domains that Teams legitimately provides
|
|
@@ -418,31 +406,10 @@ const CONSENT_UPLOAD_HOST_ALLOWLIST = [
|
|
|
418
406
|
"graph.microsoft.cn"
|
|
419
407
|
];
|
|
420
408
|
/**
|
|
421
|
-
* Returns true if the given IPv4 or IPv6 address is
|
|
422
|
-
*
|
|
409
|
+
* Returns true if the given IPv4 or IPv6 address is private, internal, or
|
|
410
|
+
* special-use and must never be reached via consent uploads.
|
|
423
411
|
*/
|
|
424
|
-
|
|
425
|
-
const ipv4MappedMatch = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(ip);
|
|
426
|
-
if (ipv4MappedMatch) return isPrivateOrReservedIP(ipv4MappedMatch[1]);
|
|
427
|
-
const v4Parts = ip.split(".");
|
|
428
|
-
if (v4Parts.length === 4) {
|
|
429
|
-
const octets = v4Parts.map(Number);
|
|
430
|
-
if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return false;
|
|
431
|
-
const [a, b] = octets;
|
|
432
|
-
if (a === 10) return true;
|
|
433
|
-
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
434
|
-
if (a === 192 && b === 168) return true;
|
|
435
|
-
if (a === 127) return true;
|
|
436
|
-
if (a === 169 && b === 254) return true;
|
|
437
|
-
if (a === 0) return true;
|
|
438
|
-
}
|
|
439
|
-
const normalized = normalizeLowercaseStringOrEmpty$1(ip);
|
|
440
|
-
if (normalized === "::1") return true;
|
|
441
|
-
if (normalized.startsWith("fe80:") || normalized.startsWith("fe80")) return true;
|
|
442
|
-
if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
|
|
443
|
-
if (normalized === "::") return true;
|
|
444
|
-
return false;
|
|
445
|
-
}
|
|
412
|
+
const isPrivateOrReservedIP = isPrivateIpAddress;
|
|
446
413
|
/**
|
|
447
414
|
* Validate that a consent upload URL is safe to PUT to.
|
|
448
415
|
* Checks:
|
|
@@ -460,7 +427,7 @@ async function validateConsentUploadUrl(url, opts) {
|
|
|
460
427
|
throw new Error("Consent upload URL is not a valid URL");
|
|
461
428
|
}
|
|
462
429
|
if (parsed.protocol !== "https:") throw new Error(`Consent upload URL must use HTTPS, got ${parsed.protocol}`);
|
|
463
|
-
const hostname = normalizeLowercaseStringOrEmpty
|
|
430
|
+
const hostname = normalizeLowercaseStringOrEmpty(parsed.hostname);
|
|
464
431
|
if (!(opts?.allowlist ?? CONSENT_UPLOAD_HOST_ALLOWLIST).some((entry) => hostname === entry || hostname.endsWith(`.${entry}`))) throw new Error(`Consent upload URL hostname "${hostname}" is not in the allowed domains`);
|
|
465
432
|
const resolveFn = opts?.resolveFn ?? ((name) => lookup(name, { all: true }));
|
|
466
433
|
let resolved;
|
|
@@ -1554,7 +1521,7 @@ async function sendMSTeamsMessages(params) {
|
|
|
1554
1521
|
const resolvedThreadId = params.conversationRef.threadId ?? params.conversationRef.activityId;
|
|
1555
1522
|
if (params.replyStyle === "thread") {
|
|
1556
1523
|
const ctx = params.context;
|
|
1557
|
-
if (!ctx)
|
|
1524
|
+
if (!ctx) return await sendProactively(messages, 0, resolvedThreadId);
|
|
1558
1525
|
const messageIds = [];
|
|
1559
1526
|
for (const [idx, message] of messages.entries()) {
|
|
1560
1527
|
const result = await withRevokedProxyFallback({
|
|
@@ -1579,6 +1546,23 @@ async function sendMSTeamsMessages(params) {
|
|
|
1579
1546
|
}
|
|
1580
1547
|
//#endregion
|
|
1581
1548
|
//#region extensions/msteams/src/send-context.ts
|
|
1549
|
+
function resolveMSTeamsProactiveReplyStyle(params) {
|
|
1550
|
+
const threadRootId = params.ref.threadId ?? params.ref.activityId;
|
|
1551
|
+
if (params.conversationType !== "channel" || !threadRootId) return "top-level";
|
|
1552
|
+
const routeConfig = resolveMSTeamsRouteConfig({
|
|
1553
|
+
cfg: params.cfg,
|
|
1554
|
+
teamId: params.ref.teamId,
|
|
1555
|
+
conversationId: params.conversationId,
|
|
1556
|
+
allowNameMatching: false
|
|
1557
|
+
});
|
|
1558
|
+
const { replyStyle } = resolveMSTeamsReplyPolicy({
|
|
1559
|
+
isDirectMessage: false,
|
|
1560
|
+
globalConfig: params.cfg,
|
|
1561
|
+
teamConfig: routeConfig.teamConfig,
|
|
1562
|
+
channelConfig: routeConfig.channelConfig
|
|
1563
|
+
});
|
|
1564
|
+
return replyStyle;
|
|
1565
|
+
}
|
|
1582
1566
|
/**
|
|
1583
1567
|
* Parse the target value into a conversation reference lookup key.
|
|
1584
1568
|
* Supported formats:
|
|
@@ -1646,6 +1630,12 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
1646
1630
|
if (storedConversationType === "personal") conversationType = "personal";
|
|
1647
1631
|
else if (storedConversationType === "channel") conversationType = "channel";
|
|
1648
1632
|
else conversationType = "groupChat";
|
|
1633
|
+
const replyStyle = resolveMSTeamsProactiveReplyStyle({
|
|
1634
|
+
cfg: msteamsCfg,
|
|
1635
|
+
conversationId,
|
|
1636
|
+
ref,
|
|
1637
|
+
conversationType
|
|
1638
|
+
});
|
|
1649
1639
|
const sharePointSiteId = msteamsCfg.sharePointSiteId;
|
|
1650
1640
|
const mediaMaxBytes = resolveChannelMediaMaxBytes({
|
|
1651
1641
|
cfg: params.cfg,
|
|
@@ -1678,6 +1668,7 @@ async function resolveMSTeamsSendContext(params) {
|
|
|
1678
1668
|
adapter,
|
|
1679
1669
|
log,
|
|
1680
1670
|
conversationType,
|
|
1671
|
+
replyStyle,
|
|
1681
1672
|
tokenProvider,
|
|
1682
1673
|
sharePointSiteId,
|
|
1683
1674
|
mediaMaxBytes,
|
|
@@ -1693,6 +1684,29 @@ const FILE_CONSENT_THRESHOLD_BYTES = 4 * 1024 * 1024;
|
|
|
1693
1684
|
* Higher than the default because OneDrive upload handles large files well.
|
|
1694
1685
|
*/
|
|
1695
1686
|
const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
1687
|
+
function createMSTeamsSendReceipt(params) {
|
|
1688
|
+
return createMessageReceiptFromOutboundResults({
|
|
1689
|
+
kind: params.kind,
|
|
1690
|
+
results: params.platformMessageIds.map((messageId) => ({
|
|
1691
|
+
channel: "msteams",
|
|
1692
|
+
messageId,
|
|
1693
|
+
conversationId: params.conversationId
|
|
1694
|
+
}))
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
function createMSTeamsSendResult(params) {
|
|
1698
|
+
const platformMessageIds = (params.platformMessageIds?.length ? [...params.platformMessageIds] : [params.messageId]).map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown");
|
|
1699
|
+
return {
|
|
1700
|
+
messageId: params.messageId,
|
|
1701
|
+
conversationId: params.conversationId,
|
|
1702
|
+
receipt: createMSTeamsSendReceipt({
|
|
1703
|
+
conversationId: params.conversationId,
|
|
1704
|
+
platformMessageIds,
|
|
1705
|
+
kind: params.kind
|
|
1706
|
+
}),
|
|
1707
|
+
...params.pendingUploadId ? { pendingUploadId: params.pendingUploadId } : {}
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1696
1710
|
/**
|
|
1697
1711
|
* Send a message to a Teams conversation or user.
|
|
1698
1712
|
*
|
|
@@ -1774,11 +1788,12 @@ async function sendMessageMSTeams(params) {
|
|
|
1774
1788
|
messageId,
|
|
1775
1789
|
uploadId
|
|
1776
1790
|
});
|
|
1777
|
-
return {
|
|
1791
|
+
return createMSTeamsSendResult({
|
|
1778
1792
|
messageId,
|
|
1779
1793
|
conversationId,
|
|
1794
|
+
kind: "card",
|
|
1780
1795
|
pendingUploadId: uploadId
|
|
1781
|
-
};
|
|
1796
|
+
});
|
|
1782
1797
|
}
|
|
1783
1798
|
if (conversationType === "personal") {
|
|
1784
1799
|
const base64 = media.buffer.toString("base64");
|
|
@@ -1833,10 +1848,11 @@ async function sendMessageMSTeams(params) {
|
|
|
1833
1848
|
messageId,
|
|
1834
1849
|
fileName: driveItem.name
|
|
1835
1850
|
});
|
|
1836
|
-
return {
|
|
1851
|
+
return createMSTeamsSendResult({
|
|
1837
1852
|
messageId,
|
|
1838
|
-
conversationId
|
|
1839
|
-
|
|
1853
|
+
conversationId,
|
|
1854
|
+
kind: "media"
|
|
1855
|
+
});
|
|
1840
1856
|
}
|
|
1841
1857
|
log.debug?.("uploading to OneDrive (no SharePoint site configured)", {
|
|
1842
1858
|
fileName,
|
|
@@ -1867,10 +1883,11 @@ async function sendMessageMSTeams(params) {
|
|
|
1867
1883
|
messageId,
|
|
1868
1884
|
shareUrl: uploaded.shareUrl
|
|
1869
1885
|
});
|
|
1870
|
-
return {
|
|
1886
|
+
return createMSTeamsSendResult({
|
|
1871
1887
|
messageId,
|
|
1872
|
-
conversationId
|
|
1873
|
-
|
|
1888
|
+
conversationId,
|
|
1889
|
+
kind: "media"
|
|
1890
|
+
});
|
|
1874
1891
|
} catch (err) {
|
|
1875
1892
|
const classification = classifyMSTeamsSendError(err);
|
|
1876
1893
|
const hint = formatMSTeamsSendErrorHint(classification);
|
|
@@ -1884,11 +1901,11 @@ async function sendMessageMSTeams(params) {
|
|
|
1884
1901
|
* Send a text message with optional base64 media URL.
|
|
1885
1902
|
*/
|
|
1886
1903
|
async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
1887
|
-
const { adapter, appId, conversationId, ref, log, tokenProvider, sharePointSiteId, mediaMaxBytes } = ctx;
|
|
1888
|
-
let
|
|
1904
|
+
const { adapter, appId, conversationId, ref, log, tokenProvider, sharePointSiteId, mediaMaxBytes, replyStyle } = ctx;
|
|
1905
|
+
let platformMessageIds;
|
|
1889
1906
|
try {
|
|
1890
|
-
|
|
1891
|
-
replyStyle
|
|
1907
|
+
platformMessageIds = await sendMSTeamsMessages({
|
|
1908
|
+
replyStyle,
|
|
1892
1909
|
adapter,
|
|
1893
1910
|
appId,
|
|
1894
1911
|
conversationRef: ref,
|
|
@@ -1913,14 +1930,19 @@ async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
|
1913
1930
|
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1914
1931
|
throw new Error(`msteams send failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1915
1932
|
}
|
|
1916
|
-
const messageId =
|
|
1933
|
+
const messageId = platformMessageIds[0] ?? "unknown";
|
|
1917
1934
|
log.info("sent proactive message", {
|
|
1918
1935
|
conversationId,
|
|
1919
1936
|
messageId
|
|
1920
1937
|
});
|
|
1921
1938
|
return {
|
|
1922
1939
|
messageId,
|
|
1923
|
-
conversationId
|
|
1940
|
+
conversationId,
|
|
1941
|
+
receipt: createMSTeamsSendReceipt({
|
|
1942
|
+
conversationId,
|
|
1943
|
+
platformMessageIds,
|
|
1944
|
+
kind: mediaUrl ? "media" : "text"
|
|
1945
|
+
})
|
|
1924
1946
|
};
|
|
1925
1947
|
}
|
|
1926
1948
|
async function sendProactiveActivityRaw({ adapter, appId, ref, activity }) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as normalizeQuery, f as resolveGraphToken, o as listChannelsForTeam, s as listTeamsByName, t as searchGraphUsers } from "./graph-users-
|
|
1
|
+
import { c as normalizeQuery, f as resolveGraphToken, o as listChannelsForTeam, s as listTeamsByName, t as searchGraphUsers } from "./graph-users-CCU0WVMZ.js";
|
|
2
2
|
import { mapAllowlistResolutionInputs } from "openclaw/plugin-sdk/allow-from";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
|
4
4
|
//#region extensions/msteams/src/resolve-allowlist.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { mergeAllowlist, resolveAllowlistMatchSimple, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
|
|
2
|
+
import { createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-message";
|
|
2
3
|
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
3
|
-
import {
|
|
4
|
+
import { resolveToolsBySender } from "openclaw/plugin-sdk/channel-policy";
|
|
4
5
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
5
6
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-logging";
|
|
6
|
-
import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
|
7
7
|
import { PAIRING_APPROVED_MESSAGE, buildProbeChannelStatusSummary, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/channel-status";
|
|
8
8
|
import { buildChannelKeyCandidates, normalizeChannelSlug, resolveChannelEntryMatchWithFallback, resolveNestedAllowlistDecision } from "openclaw/plugin-sdk/channel-targets";
|
|
9
9
|
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
@@ -25,4 +25,4 @@ const { setRuntime: setMSTeamsRuntime, getRuntime: getMSTeamsRuntime, tryGetRunt
|
|
|
25
25
|
errorMessage: "MSTeams runtime not initialized"
|
|
26
26
|
});
|
|
27
27
|
//#endregion
|
|
28
|
-
export {
|
|
28
|
+
export { summarizeMapping as A, normalizeStringEntries as C, resolveDefaultGroupPolicy as D, resolveChannelMediaMaxBytes as E, getMSTeamsRuntime as M, getOptionalMSTeamsRuntime as N, resolveNestedAllowlistDecision as O, setMSTeamsRuntime as P, normalizeChannelSlug as S, resolveChannelEntryMatchWithFallback as T, isDangerousNameMatchingEnabled as _, buildMediaPayload as a, logTypingFailure as b, createChannelMessageReplyPipeline as c, detectMime as d, dispatchReplyFromConfigWithSettledDispatcher$1 as f, getFileExtension as g, fetchWithSsrFGuard$1 as h, buildChannelKeyCandidates as i, withFileLock$1 as j, resolveToolsBySender as k, createChannelPairingController as l, extractOriginalFilename as m, DEFAULT_WEBHOOK_MAX_BODY_BYTES as n, buildProbeChannelStatusSummary as o, extensionForMime as p, PAIRING_APPROVED_MESSAGE as r, chunkTextForOutbound as s, DEFAULT_ACCOUNT_ID as t, createDefaultChannelRuntimeState as u, keepHttpServerTaskAlive as v, resolveAllowlistMatchSimple as w, mergeAllowlist as x, loadOutboundMediaFromUrl as y };
|