@openclaw/msteams 2026.9.3 → 2026.9.5
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/assets/activity.svg +40 -0
- package/assets/icon.png +0 -0
- package/dist/{adapter.runtime-DDuc7sKJ.cjs → .setup/adapter.runtime-ChuVK6k_.cjs} +3 -3
- package/dist/{approval-handler.runtime-CoTQG4FS.cjs → .setup/approval-handler.runtime-DDxGPJDz.cjs} +3 -3
- package/dist/{channel-Cdm6-HsU.cjs → .setup/channel-Dzpbbht8.cjs} +63 -35
- package/dist/{channel.runtime-__5ZQlfG.cjs → .setup/channel.runtime-TE49QvFv.cjs} +57 -32
- package/dist/{channel.setup-ChwkwdLk.cjs → .setup/channel.setup-BVDfgdCc.cjs} +17 -25
- package/dist/{delegated-state-DiEz9JIa.cjs → .setup/delegated-state-u-ywZyZT.cjs} +5 -5
- package/dist/{messenger-DbWgzI01.cjs → .setup/messenger-BR1l4zw-.cjs} +108 -178
- package/dist/{oauth-BeROaYf0.cjs → .setup/oauth-C6m7dvHj.cjs} +1 -1
- package/dist/{polls-BBdZPx_R.cjs → .setup/polls-BJ4-4uZm.cjs} +14 -7
- package/dist/{reaction-types-zP91Ncwk.cjs → .setup/reaction-types-C7RA7Wxt.cjs} +1 -1
- package/dist/{resolve-allowlist-CoKmLXYe.cjs → .setup/resolve-allowlist-CHzaaWiC.cjs} +141 -93
- package/dist/.setup/secret-contract-api-ChQdBeU1.cjs +4 -0
- package/dist/.setup/secret-contract-api-ipiUsANg.cjs +28 -0
- package/dist/{send-Bw4W8RO7.cjs → .setup/send-D8ATH4QI.cjs} +95 -33
- package/dist/.setup/setup-plugin-api-DpiaA8z1.cjs +3 -0
- package/dist/{src-B--Qc6lj.cjs → .setup/src-CpKfpP1m.cjs} +134 -58
- package/dist/{sso-token-store-DTeYxubp.cjs → .setup/sso-token-store-YYLHXgFH.cjs} +1 -1
- package/dist/{thread-session-p8FNgohv.cjs → .setup/thread-session-CXgHK-yi.cjs} +1 -1
- package/dist/api.cjs +2 -2
- package/dist/channel-config-api.cjs +1 -1
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/configured-state.cjs +1 -1
- package/dist/directory-contract-api.cjs +1 -1
- package/dist/doctor-contract-api.cjs +64 -62
- package/dist/qa-runner-api.cjs +1 -1
- package/dist/runtime-api.cjs +1 -1
- package/dist/secret-contract-api.cjs +4 -13
- package/dist/setup-entry.cjs +5 -3
- package/dist/setup-plugin-api.cjs +1 -1
- package/openclaw.plugin.json +4 -1
- package/package.json +14 -11
- /package/dist/{approval-card-CPNH_q3P.cjs → .setup/approval-card-CPNH_q3P.cjs} +0 -0
- /package/dist/{config-schema-D22Lr1Qk.cjs → .setup/config-schema-D22Lr1Qk.cjs} +0 -0
- /package/dist/{rolldown-runtime-VH7oDXx4.cjs → .setup/rolldown-runtime-VH7oDXx4.cjs} +0 -0
- /package/dist/{runtime-gZTAuFux.cjs → .setup/runtime-gZTAuFux.cjs} +0 -0
- /package/dist/{secret-input-C65t6kjM.cjs → .setup/secret-input-C65t6kjM.cjs} +0 -0
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
2
2
|
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
3
|
-
require("
|
|
4
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
5
|
-
const require_channel_setup = require("./channel.setup-
|
|
6
|
-
const require_polls = require("./polls-
|
|
3
|
+
require("../runtime-api.cjs");
|
|
4
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CHzaaWiC.cjs");
|
|
5
|
+
const require_channel_setup = require("./channel.setup-BVDfgdCc.cjs");
|
|
6
|
+
const require_polls = require("./polls-BJ4-4uZm.cjs");
|
|
7
7
|
let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
|
|
8
8
|
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
9
|
+
let openclaw_plugin_sdk_fetch_runtime = require("openclaw/plugin-sdk/fetch-runtime");
|
|
9
10
|
let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
|
|
10
11
|
let openclaw_plugin_sdk_reply_payload = require("openclaw/plugin-sdk/reply-payload");
|
|
12
|
+
let openclaw_plugin_sdk_ssrf_runtime = require("openclaw/plugin-sdk/ssrf-runtime");
|
|
11
13
|
let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunking");
|
|
12
14
|
let node_dns_promises = require("node:dns/promises");
|
|
13
15
|
let openclaw_plugin_sdk_ssrf_policy = require("openclaw/plugin-sdk/ssrf-policy");
|
|
14
16
|
let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text-utility-runtime");
|
|
17
|
+
let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
|
|
15
18
|
let openclaw_plugin_sdk_retry_runtime = require("openclaw/plugin-sdk/retry-runtime");
|
|
16
19
|
let node_crypto = require("node:crypto");
|
|
17
20
|
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
18
21
|
let node_path = require("node:path");
|
|
19
22
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
20
23
|
let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
|
|
24
|
+
let openclaw_plugin_sdk_markdown_table_runtime = require("openclaw/plugin-sdk/markdown-table-runtime");
|
|
21
25
|
let openclaw_plugin_sdk_blob_runtime = require("openclaw/plugin-sdk/blob-runtime");
|
|
22
26
|
let openclaw_plugin_sdk_global_singleton = require("openclaw/plugin-sdk/global-singleton");
|
|
23
|
-
let
|
|
27
|
+
let openclaw_plugin_sdk_expect_runtime = require("openclaw/plugin-sdk/expect-runtime");
|
|
24
28
|
let openclaw_plugin_sdk_reply_chunking = require("openclaw/plugin-sdk/reply-chunking");
|
|
25
29
|
let openclaw_plugin_sdk_web_media = require("openclaw/plugin-sdk/web-media");
|
|
26
30
|
let openclaw_plugin_sdk_media_runtime = require("openclaw/plugin-sdk/media-runtime");
|
|
@@ -635,6 +639,7 @@ function serializeMarkdownDestination(href) {
|
|
|
635
639
|
return `<${href.replace(/([\\<>])/gu, "\\$1")}>`;
|
|
636
640
|
}
|
|
637
641
|
function blankBlockEnd(text, index) {
|
|
642
|
+
if (text[index] !== "\n" && text[index] !== "\r") return;
|
|
638
643
|
const match = /^(?:\r?\n)[ \t]*(?:\r?\n)/u.exec(text.slice(index));
|
|
639
644
|
return match ? index + match[0].length : void 0;
|
|
640
645
|
}
|
|
@@ -692,136 +697,25 @@ function protectDelimitedMarkdown(text, opener, tokenPrefix, values) {
|
|
|
692
697
|
}
|
|
693
698
|
return protectedText + text.slice(cursor);
|
|
694
699
|
}
|
|
695
|
-
function
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
cursor += 1;
|
|
703
|
-
spaces += 1;
|
|
704
|
-
}
|
|
705
|
-
if (line[cursor] !== ">") {
|
|
706
|
-
cursor = checkpoint;
|
|
707
|
-
break;
|
|
708
|
-
}
|
|
709
|
-
cursor += 1;
|
|
710
|
-
depth += 1;
|
|
711
|
-
if (line[cursor] === " " || line[cursor] === " ") cursor += 1;
|
|
712
|
-
}
|
|
713
|
-
return {
|
|
714
|
-
content: line.slice(cursor).replace(/\r$/u, ""),
|
|
715
|
-
depth,
|
|
716
|
-
prefix: line.slice(0, cursor)
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
function isTableDelimiterLine(content) {
|
|
720
|
-
const cells = content.trim().replace(/^\|/u, "").replace(/\|$/u, "").split("|").map((cell) => cell.trim());
|
|
721
|
-
return cells.length > 0 && cells.every((cell) => /^:?-+:?$/u.test(cell));
|
|
722
|
-
}
|
|
723
|
-
function protectRawTablesInSegment(text, tokenPrefix, rawTables) {
|
|
724
|
-
const lines = text.split("\n");
|
|
725
|
-
const output = [];
|
|
726
|
-
for (let index = 0; index < lines.length;) {
|
|
727
|
-
const line = lines[index] ?? "";
|
|
728
|
-
const header = parseQuotePrefix(line);
|
|
729
|
-
const delimiter = parseQuotePrefix(lines[index + 1] ?? "");
|
|
730
|
-
if (header.content.includes("|") && delimiter.depth === header.depth && isTableDelimiterLine(delimiter.content)) {
|
|
731
|
-
let end = index + 2;
|
|
732
|
-
while (end < lines.length) {
|
|
733
|
-
const row = parseQuotePrefix(lines[end] ?? "");
|
|
734
|
-
if (row.depth !== header.depth || !row.content.trim() || isInterruptingBlock(lines[end] ?? "")) break;
|
|
735
|
-
end += 1;
|
|
736
|
-
}
|
|
737
|
-
const table = lines.slice(index, end).join("\n");
|
|
738
|
-
if ((0, openclaw_plugin_sdk_text_chunking.convertMarkdownTables)(table, "code") !== table) {
|
|
739
|
-
const tableIndex = rawTables.push(table.slice(header.prefix.length)) - 1;
|
|
740
|
-
output.push(`${header.prefix}${tokenPrefix}t${tableIndex}${TOKEN_END}`);
|
|
741
|
-
index = end;
|
|
742
|
-
continue;
|
|
743
|
-
}
|
|
744
|
-
for (let lineIndex = index; lineIndex < end; lineIndex += 1) output.push(lines[lineIndex] ?? "");
|
|
745
|
-
index = end;
|
|
746
|
-
continue;
|
|
747
|
-
}
|
|
748
|
-
output.push(line);
|
|
749
|
-
index += 1;
|
|
750
|
-
}
|
|
751
|
-
return output.join("\n");
|
|
752
|
-
}
|
|
753
|
-
function isInterruptingBlock(line) {
|
|
754
|
-
const content = parseQuotePrefix(line).content;
|
|
755
|
-
return /^[ \t]{0,3}(?:#{1,6}(?:[ \t]|$)|`{3,}|~{3,}|(?:[-+*]|\d+[.)])[ \t]+)/u.test(content);
|
|
756
|
-
}
|
|
757
|
-
function leadingQuoteDepth(line) {
|
|
758
|
-
return parseQuotePrefix(line).depth;
|
|
759
|
-
}
|
|
760
|
-
function parseFenceLine(line) {
|
|
761
|
-
const match = /^((?: {0,3}>[ \t]?)*)(?:((?:[-+*]|\d+[.)])[ \t]+))?( {0,3})(`{3,}|~{3,})(.*)$/u.exec(line);
|
|
762
|
-
const marker = match?.[4];
|
|
763
|
-
const trailing = match?.[5] ?? "";
|
|
764
|
-
if (!marker || marker.startsWith("`") && trailing.includes("`")) return;
|
|
765
|
-
return {
|
|
766
|
-
marker,
|
|
767
|
-
quoteDepth: match?.[1]?.match(/>/gu)?.length ?? 0,
|
|
768
|
-
trailing,
|
|
769
|
-
listIndent: match?.[2]?.length ?? 0,
|
|
770
|
-
indent: match?.[3]?.length ?? 0
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
function protectRawTablesOutsideFences(text, tokenPrefix, rawTables) {
|
|
700
|
+
function protectRawTables(text, tokenPrefix, rawTables) {
|
|
701
|
+
if (!text.includes("|")) return text;
|
|
702
|
+
const { tables } = (0, openclaw_plugin_sdk_text_chunking.markdownToIRWithMeta)(text, {
|
|
703
|
+
autolink: false,
|
|
704
|
+
linkify: false,
|
|
705
|
+
tableMode: "block"
|
|
706
|
+
});
|
|
774
707
|
let result = "";
|
|
775
|
-
let
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
let fence = parseFenceLine(line);
|
|
785
|
-
const lineQuoteDepth = leadingQuoteDepth(line);
|
|
786
|
-
const lineWithoutQuotes = line.replace(/^(?:[ \t]*>[ \t]?)+/u, "");
|
|
787
|
-
const lineIndent = /^[ \t]*/u.exec(lineWithoutQuotes)?.[0].length ?? 0;
|
|
788
|
-
const listMarkerIndent = /^((?:[-+*]|\d+[.)])[ \t]+)/u.exec(lineWithoutQuotes)?.[1]?.length;
|
|
789
|
-
if (listMarkerIndent) listContextIndent = listMarkerIndent;
|
|
790
|
-
else if (line.trim() && lineIndent < listContextIndent && !fence) listContextIndent = 0;
|
|
791
|
-
if (fence && fence.listIndent === 0 && listContextIndent > 0 && fence.indent >= listContextIndent) fence = {
|
|
792
|
-
...fence,
|
|
793
|
-
listIndent: listContextIndent
|
|
794
|
-
};
|
|
795
|
-
const listOutdented = Boolean(active?.listIndent && line.trim() && lineIndent < active.listIndent && !fence);
|
|
796
|
-
if (active && (active.quoteDepth > lineQuoteDepth || listOutdented)) {
|
|
797
|
-
result += text.slice(fenceStart, offset);
|
|
798
|
-
outsideStart = offset;
|
|
799
|
-
active = void 0;
|
|
800
|
-
fenceStart = void 0;
|
|
801
|
-
}
|
|
802
|
-
if (!active && fence) {
|
|
803
|
-
result += protectRawTablesInSegment(text.slice(outsideStart, offset), tokenPrefix, rawTables);
|
|
804
|
-
fenceStart = offset;
|
|
805
|
-
active = {
|
|
806
|
-
marker: fence.marker,
|
|
807
|
-
quoteDepth: fence.quoteDepth,
|
|
808
|
-
listIndent: fence.listIndent
|
|
809
|
-
};
|
|
810
|
-
} else if (active && fence && fence.marker[0] === active.marker[0] && fence.marker.length >= active.marker.length && fence.quoteDepth === active.quoteDepth && /^[ \t]*$/u.test(fence.trailing)) {
|
|
811
|
-
const fenceEnd = nextNewline < 0 ? lineEnd : nextNewline + 1;
|
|
812
|
-
result += text.slice(fenceStart, fenceEnd);
|
|
813
|
-
outsideStart = fenceEnd;
|
|
814
|
-
active = void 0;
|
|
815
|
-
fenceStart = void 0;
|
|
816
|
-
}
|
|
817
|
-
if (nextNewline < 0) break;
|
|
818
|
-
offset = nextNewline + 1;
|
|
819
|
-
}
|
|
820
|
-
if (active && fenceStart !== void 0) {
|
|
821
|
-
result += text.slice(fenceStart);
|
|
822
|
-
return result;
|
|
708
|
+
let cursor = 0;
|
|
709
|
+
for (const table of tables) {
|
|
710
|
+
const source = (0, openclaw_plugin_sdk_expect_runtime.expectDefined)((0, openclaw_plugin_sdk_markdown_table_runtime.getMarkdownTableSource)(table), "Markdown table source");
|
|
711
|
+
const lineStart = Math.max(text.lastIndexOf("\n", source.start - 1), text.lastIndexOf("\r", source.start - 1)) + 1;
|
|
712
|
+
const start = lineStart + (/^(?: {0,3}>[ \t]?)*/u.exec(text.slice(lineStart, source.start))?.[0] ?? "").length;
|
|
713
|
+
const end = source.end + (text.slice(source.end, source.end + 2) === "\r\n" ? 1 : 0);
|
|
714
|
+
const index = rawTables.push(text.slice(start, end)) - 1;
|
|
715
|
+
result += text.slice(cursor, start) + `${tokenPrefix}t${index}${TOKEN_END}`;
|
|
716
|
+
cursor = end;
|
|
823
717
|
}
|
|
824
|
-
return result +
|
|
718
|
+
return result + text.slice(cursor);
|
|
825
719
|
}
|
|
826
720
|
function protectMSTeamsCode(ir, tokenPrefix, code, protectedValues) {
|
|
827
721
|
const codeSpans = ir.styles.filter((span) => span.style === "code" || span.style === "code_block");
|
|
@@ -877,7 +771,7 @@ function formatMSTeamsMarkdown(markdown, tableMode) {
|
|
|
877
771
|
return `${tokenPrefix}h${index}${TOKEN_END}`;
|
|
878
772
|
}), "![", `${tokenPrefix}i`, images), "@[", `${tokenPrefix}m`, mentions);
|
|
879
773
|
const tableInput = (0, openclaw_plugin_sdk_text_chunking.convertMarkdownTables)(mentionsProtected, tableMode);
|
|
880
|
-
const protectedMarkdown = (tableMode === "off" ?
|
|
774
|
+
const protectedMarkdown = (tableMode === "off" ? protectRawTables(tableInput, tokenPrefix, rawTables) : tableInput).replace(ESCAPED_MARKDOWN_RE, (escaped) => {
|
|
881
775
|
const index = escapedMarkdown.push(escaped) - 1;
|
|
882
776
|
return `${tokenPrefix}e${index}${TOKEN_END}`;
|
|
883
777
|
});
|
|
@@ -957,6 +851,19 @@ function buildTeamsFileInfoCard(file) {
|
|
|
957
851
|
const GRAPH_ROOT = "https://graph.microsoft.com/v1.0";
|
|
958
852
|
const GRAPH_BETA = "https://graph.microsoft.com/beta";
|
|
959
853
|
const GRAPH_SCOPE = "https://graph.microsoft.com";
|
|
854
|
+
async function requestSharePoint(url, init, params) {
|
|
855
|
+
const { response, release } = await (0, openclaw_plugin_sdk_ssrf_runtime.fetchWithSsrFGuard)({
|
|
856
|
+
url,
|
|
857
|
+
init,
|
|
858
|
+
fetchImpl: params.fetchFn,
|
|
859
|
+
mode: "trusted_env_proxy",
|
|
860
|
+
beforeRequest: () => require_resolve_allowlist.assertMSTeamsSendHandoff(params),
|
|
861
|
+
maxRedirects: 20,
|
|
862
|
+
allowCrossOriginUnsafeRedirectReplay: true,
|
|
863
|
+
auditContext: "msteams.graph-upload"
|
|
864
|
+
});
|
|
865
|
+
return (0, openclaw_plugin_sdk_fetch_runtime.responseWithRelease)(response, release);
|
|
866
|
+
}
|
|
960
867
|
function requireMSTeamsSharePointSiteId(siteId) {
|
|
961
868
|
const normalized = siteId?.trim();
|
|
962
869
|
if (!normalized) throw new Error("channels.msteams.sharePointSiteId is required to send files to group chats or channels");
|
|
@@ -978,7 +885,6 @@ async function getGraphAccessToken(tokenProvider) {
|
|
|
978
885
|
* @param params.siteId - SharePoint site ID (e.g., "contoso.sharepoint.com,guid1,guid2")
|
|
979
886
|
*/
|
|
980
887
|
async function uploadToSharePoint(params) {
|
|
981
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
982
888
|
const uploadPath = `/OpenClawShared/${encodeURIComponent(params.filename)}`;
|
|
983
889
|
const uploadUrl = `${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content?@microsoft.graph.conflictBehavior=rename`;
|
|
984
890
|
const timeoutMs = require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length);
|
|
@@ -986,8 +892,10 @@ async function uploadToSharePoint(params) {
|
|
|
986
892
|
label: SHAREPOINT_UPLOAD_TIMEOUT_LABEL,
|
|
987
893
|
timeoutMs,
|
|
988
894
|
work: async (signal) => {
|
|
895
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
989
896
|
const token = await getGraphAccessToken(params.tokenProvider);
|
|
990
|
-
|
|
897
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
898
|
+
const res = await requestSharePoint(uploadUrl, {
|
|
991
899
|
method: "PUT",
|
|
992
900
|
headers: {
|
|
993
901
|
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
@@ -996,7 +904,7 @@ async function uploadToSharePoint(params) {
|
|
|
996
904
|
},
|
|
997
905
|
body: new Blob([(0, openclaw_plugin_sdk_blob_runtime.bufferToBlobPart)(params.buffer)]),
|
|
998
906
|
signal
|
|
999
|
-
});
|
|
907
|
+
}, params);
|
|
1000
908
|
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "SharePoint upload failed");
|
|
1001
909
|
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.uploadSharePointFile", { chunkTimeoutMs: timeoutMs });
|
|
1002
910
|
}
|
|
@@ -1016,18 +924,19 @@ async function uploadToSharePoint(params) {
|
|
|
1016
924
|
* @param params.itemId - The driveItem ID (returned from upload)
|
|
1017
925
|
*/
|
|
1018
926
|
async function getDriveItemProperties(params) {
|
|
1019
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
1020
927
|
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
1021
928
|
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
1022
929
|
work: async (signal) => {
|
|
930
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
1023
931
|
const token = await getGraphAccessToken(params.tokenProvider);
|
|
1024
|
-
|
|
932
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
933
|
+
const res = await requestSharePoint(`${GRAPH_ROOT}/sites/${params.siteId}/drive/items/${params.itemId}?$select=eTag,webDavUrl,name`, {
|
|
1025
934
|
headers: {
|
|
1026
935
|
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
1027
936
|
Authorization: `Bearer ${token}`
|
|
1028
937
|
},
|
|
1029
938
|
signal
|
|
1030
|
-
});
|
|
939
|
+
}, params);
|
|
1031
940
|
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Get driveItem properties failed");
|
|
1032
941
|
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getDriveItemProperties");
|
|
1033
942
|
}
|
|
@@ -1044,18 +953,19 @@ async function getDriveItemProperties(params) {
|
|
|
1044
953
|
* Used to create sharing links scoped to only the chat participants.
|
|
1045
954
|
*/
|
|
1046
955
|
async function getChatMembers(params) {
|
|
1047
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
1048
956
|
return await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
1049
957
|
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
1050
958
|
work: async (signal) => {
|
|
959
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
1051
960
|
const token = await getGraphAccessToken(params.tokenProvider);
|
|
1052
|
-
|
|
961
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
962
|
+
const res = await requestSharePoint(`${GRAPH_ROOT}/chats/${params.chatId}/members`, {
|
|
1053
963
|
headers: {
|
|
1054
964
|
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
1055
965
|
Authorization: `Bearer ${token}`
|
|
1056
966
|
},
|
|
1057
967
|
signal
|
|
1058
|
-
});
|
|
968
|
+
}, params);
|
|
1059
969
|
if (!res.ok) {
|
|
1060
970
|
const message = res.status === 403 ? "Get chat members failed; verify Graph chat-member permissions and tenant access policies" : "Get chat members failed";
|
|
1061
971
|
throw await require_resolve_allowlist.createMSTeamsHttpError(res, message);
|
|
@@ -1070,7 +980,6 @@ async function getChatMembers(params) {
|
|
|
1070
980
|
* For per-user scope, uses beta API with recipients.
|
|
1071
981
|
*/
|
|
1072
982
|
async function createSharePointSharingLink(params) {
|
|
1073
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
1074
983
|
const scope = params.scope ?? "organization";
|
|
1075
984
|
const apiRoot = scope === "users" ? GRAPH_BETA : GRAPH_ROOT;
|
|
1076
985
|
const body = {
|
|
@@ -1081,8 +990,10 @@ async function createSharePointSharingLink(params) {
|
|
|
1081
990
|
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
1082
991
|
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
1083
992
|
work: async (signal) => {
|
|
993
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
1084
994
|
const token = await getGraphAccessToken(params.tokenProvider);
|
|
1085
|
-
|
|
995
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
996
|
+
const res = await requestSharePoint(`${apiRoot}/sites/${params.siteId}/drive/items/${params.itemId}/createLink`, {
|
|
1086
997
|
method: "POST",
|
|
1087
998
|
headers: {
|
|
1088
999
|
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
@@ -1091,7 +1002,7 @@ async function createSharePointSharingLink(params) {
|
|
|
1091
1002
|
},
|
|
1092
1003
|
body: JSON.stringify(body),
|
|
1093
1004
|
signal
|
|
1094
|
-
});
|
|
1005
|
+
}, params);
|
|
1095
1006
|
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Create SharePoint sharing link failed");
|
|
1096
1007
|
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.createSharePointSharingLink");
|
|
1097
1008
|
}
|
|
@@ -1116,7 +1027,8 @@ async function uploadAndShareSharePoint(params) {
|
|
|
1116
1027
|
contentType: params.contentType,
|
|
1117
1028
|
tokenProvider: params.tokenProvider,
|
|
1118
1029
|
siteId: params.siteId,
|
|
1119
|
-
fetchFn: params.fetchFn
|
|
1030
|
+
fetchFn: params.fetchFn,
|
|
1031
|
+
assertDirectAdapterHandoff: params.assertDirectAdapterHandoff
|
|
1120
1032
|
});
|
|
1121
1033
|
let scope = "organization";
|
|
1122
1034
|
let recipientObjectIds;
|
|
@@ -1124,7 +1036,8 @@ async function uploadAndShareSharePoint(params) {
|
|
|
1124
1036
|
const members = await getChatMembers({
|
|
1125
1037
|
chatId: params.chatId,
|
|
1126
1038
|
tokenProvider: params.tokenProvider,
|
|
1127
|
-
fetchFn: params.fetchFn
|
|
1039
|
+
fetchFn: params.fetchFn,
|
|
1040
|
+
assertDirectAdapterHandoff: params.assertDirectAdapterHandoff
|
|
1128
1041
|
});
|
|
1129
1042
|
if (members.length === 0) throw new Error("MS Teams chat member lookup returned no recipients");
|
|
1130
1043
|
scope = "users";
|
|
@@ -1136,7 +1049,8 @@ async function uploadAndShareSharePoint(params) {
|
|
|
1136
1049
|
tokenProvider: params.tokenProvider,
|
|
1137
1050
|
scope,
|
|
1138
1051
|
recipientObjectIds,
|
|
1139
|
-
fetchFn: params.fetchFn
|
|
1052
|
+
fetchFn: params.fetchFn,
|
|
1053
|
+
assertDirectAdapterHandoff: params.assertDirectAdapterHandoff
|
|
1140
1054
|
});
|
|
1141
1055
|
return {
|
|
1142
1056
|
itemId: uploaded.id,
|
|
@@ -1236,13 +1150,13 @@ function isValidTeamsId(id) {
|
|
|
1236
1150
|
* Returns both the formatted text with <at> tags and the entities array.
|
|
1237
1151
|
*/
|
|
1238
1152
|
function parseMentions(text) {
|
|
1239
|
-
const mentionPattern = /@\[([^\]]+)\]\(([^)]+)\)/g;
|
|
1153
|
+
const mentionPattern = /@\[((?:\\[\s\S]|[^\]\\])+)\]\(([^)]+)\)/g;
|
|
1240
1154
|
const entities = [];
|
|
1241
1155
|
return {
|
|
1242
1156
|
text: text.replace(mentionPattern, (match, name, id) => {
|
|
1243
1157
|
const trimmedId = id.trim();
|
|
1244
1158
|
if (!isValidTeamsId(trimmedId)) return match;
|
|
1245
|
-
const trimmedName = name.trim();
|
|
1159
|
+
const trimmedName = name.replace(/\\([\\[\]])/g, "$1").trim();
|
|
1246
1160
|
const mentionTag = `<at>${trimmedName}</at>`;
|
|
1247
1161
|
entities.push({
|
|
1248
1162
|
type: "mention",
|
|
@@ -1390,24 +1304,28 @@ function mergeReferenceIntoActivity(activity, ref) {
|
|
|
1390
1304
|
};
|
|
1391
1305
|
}
|
|
1392
1306
|
async function sendMSTeamsActivityWithReference(app, source, activity, options) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
const
|
|
1307
|
+
return require_resolve_allowlist.withMSTeamsConnectorHandoff(options ?? {}, async (handoff) => {
|
|
1308
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(handoff);
|
|
1309
|
+
const ref = buildSdkConversationReference(source, options);
|
|
1310
|
+
const activities = (await getApiClientForReference(app, ref)).conversations.activities(ref.conversation.id);
|
|
1311
|
+
const activityWithRef = mergeReferenceIntoActivity(options?.quoteActivityId ? await quoteMSTeamsActivity(activity, options.quoteActivityId) : activity, ref);
|
|
1312
|
+
const isTargeted = activityWithRef.recipient?.isTargeted === true;
|
|
1313
|
+
if (isTargeted && ref.conversation.conversationType === "personal") throw new Error("Targeted messages are not supported in 1:1 (personal) chats.");
|
|
1314
|
+
const activityId = typeof activityWithRef.id === "string" ? activityWithRef.id : void 0;
|
|
1315
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(handoff);
|
|
1316
|
+
if (activityId) {
|
|
1317
|
+
const res = isTargeted && activities.updateTargeted ? await activities.updateTargeted(activityId, activityWithRef) : await activities.update(activityId, activityWithRef);
|
|
1318
|
+
return {
|
|
1319
|
+
...activityWithRef,
|
|
1320
|
+
...res && typeof res === "object" ? res : {}
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
const res = isTargeted && activities.createTargeted ? await activities.createTargeted(activityWithRef) : await activities.create(activityWithRef);
|
|
1401
1324
|
return {
|
|
1402
1325
|
...activityWithRef,
|
|
1403
|
-
...res
|
|
1326
|
+
...res
|
|
1404
1327
|
};
|
|
1405
|
-
}
|
|
1406
|
-
const res = isTargeted && activities.createTargeted ? await activities.createTargeted(activityWithRef) : await activities.create(activityWithRef);
|
|
1407
|
-
return {
|
|
1408
|
-
...activityWithRef,
|
|
1409
|
-
...res
|
|
1410
|
-
};
|
|
1328
|
+
});
|
|
1411
1329
|
}
|
|
1412
1330
|
async function updateMSTeamsActivityWithReference(app, source, activityId, activity, options) {
|
|
1413
1331
|
const ref = buildSdkConversationReference(source, options);
|
|
@@ -1566,6 +1484,7 @@ async function buildActivity(msg, conversationRef, tokenProvider, sharePointSite
|
|
|
1566
1484
|
thresholdBytes: FILE_CONSENT_THRESHOLD_BYTES
|
|
1567
1485
|
})) {
|
|
1568
1486
|
const conversationId = conversationRef.conversation?.id ?? "unknown";
|
|
1487
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(options);
|
|
1569
1488
|
const { activity: consentActivity, uploadId } = prepareFileConsentActivity({
|
|
1570
1489
|
media: {
|
|
1571
1490
|
buffer: media.buffer,
|
|
@@ -1582,17 +1501,20 @@ async function buildActivity(msg, conversationRef, tokenProvider, sharePointSite
|
|
|
1582
1501
|
const siteId = requireMSTeamsSharePointSiteId(sharePointSiteId);
|
|
1583
1502
|
if (!tokenProvider) throw new Error("MS Teams Graph token provider unavailable for SharePoint file send");
|
|
1584
1503
|
const chatId = conversationRef.conversation?.id;
|
|
1504
|
+
const uploaded = await uploadAndShareSharePoint({
|
|
1505
|
+
assertDirectAdapterHandoff: options?.assertDirectAdapterHandoff,
|
|
1506
|
+
buffer: media.buffer,
|
|
1507
|
+
filename: fileName,
|
|
1508
|
+
contentType,
|
|
1509
|
+
tokenProvider,
|
|
1510
|
+
siteId,
|
|
1511
|
+
chatId: chatId ?? void 0,
|
|
1512
|
+
usePerUserSharing: conversationType === "groupchat"
|
|
1513
|
+
});
|
|
1585
1514
|
activity.attachments = [buildTeamsFileInfoCard(await getDriveItemProperties({
|
|
1515
|
+
assertDirectAdapterHandoff: options?.assertDirectAdapterHandoff,
|
|
1586
1516
|
siteId,
|
|
1587
|
-
itemId:
|
|
1588
|
-
buffer: media.buffer,
|
|
1589
|
-
filename: fileName,
|
|
1590
|
-
contentType,
|
|
1591
|
-
tokenProvider,
|
|
1592
|
-
siteId,
|
|
1593
|
-
chatId: chatId ?? void 0,
|
|
1594
|
-
usePerUserSharing: conversationType === "groupchat"
|
|
1595
|
-
})).itemId,
|
|
1517
|
+
itemId: uploaded.itemId,
|
|
1596
1518
|
tokenProvider
|
|
1597
1519
|
}))];
|
|
1598
1520
|
return activity;
|
|
@@ -1640,9 +1562,14 @@ async function sendMSTeamsMessages(params) {
|
|
|
1640
1562
|
let response;
|
|
1641
1563
|
try {
|
|
1642
1564
|
response = await sendWithRetry(async () => {
|
|
1643
|
-
|
|
1565
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
1566
|
+
activity ??= await buildActivity(message, params.conversationRef, params.tokenProvider, params.sharePointSiteId, params.mediaMaxBytes, {
|
|
1567
|
+
feedbackLoopEnabled: params.feedbackLoopEnabled,
|
|
1568
|
+
assertDirectAdapterHandoff: params.assertDirectAdapterHandoff
|
|
1569
|
+
});
|
|
1644
1570
|
pendingUploadId ??= typeof activity["_pendingUploadId"] === "string" ? activity["_pendingUploadId"] : void 0;
|
|
1645
1571
|
delete activity["_pendingUploadId"];
|
|
1572
|
+
require_resolve_allowlist.assertMSTeamsSendHandoff(params);
|
|
1646
1573
|
providerDispatchStarted = true;
|
|
1647
1574
|
return await sendFn(activity);
|
|
1648
1575
|
}, {
|
|
@@ -1650,10 +1577,11 @@ async function sendMSTeamsMessages(params) {
|
|
|
1650
1577
|
messageCount: messages.length
|
|
1651
1578
|
});
|
|
1652
1579
|
} catch (error) {
|
|
1653
|
-
if (!providerDispatchStarted) throw new openclaw_plugin_sdk_error_runtime.PlatformMessageNotDispatchedError(error instanceof Error ? error.message : "Teams activity preparation failed", { cause: error });
|
|
1580
|
+
if (!providerDispatchStarted && !(error instanceof openclaw_plugin_sdk_error_runtime.PlatformMessageNotDispatchedError)) throw new openclaw_plugin_sdk_error_runtime.PlatformMessageNotDispatchedError(error instanceof Error ? error.message : "Teams activity preparation failed", { cause: error });
|
|
1654
1581
|
throw error;
|
|
1655
1582
|
}
|
|
1656
1583
|
const messageId = extractMessageId(response) ?? "unknown";
|
|
1584
|
+
await params.onMessageSent?.(messageId, messageIndex);
|
|
1657
1585
|
if (pendingUploadId && messageId !== "unknown") setPendingUploadActivityId(pendingUploadId, messageId);
|
|
1658
1586
|
return messageId;
|
|
1659
1587
|
};
|
|
@@ -1672,6 +1600,8 @@ async function sendMSTeamsMessages(params) {
|
|
|
1672
1600
|
}
|
|
1673
1601
|
const isChannel = params.conversationRef.conversation?.conversationType === "channel";
|
|
1674
1602
|
const sendFn = (activity) => sendMSTeamsActivityWithReference(params.app, baseRef, activity, {
|
|
1603
|
+
assertDirectAdapterHandoff: params.assertDirectAdapterHandoff,
|
|
1604
|
+
onPlatformSendDispatch: params.onPlatformSendDispatch,
|
|
1675
1605
|
threadActivityId: isChannel ? threadActivityId : void 0,
|
|
1676
1606
|
serviceUrlBoundary: params.serviceUrlBoundary
|
|
1677
1607
|
});
|
|
@@ -1681,7 +1611,7 @@ async function sendMSTeamsMessages(params) {
|
|
|
1681
1611
|
if (params.replyStyle === "thread") {
|
|
1682
1612
|
const ctx = params.context;
|
|
1683
1613
|
if (!ctx) return await sendProactively(messages, 0, resolvedThreadId);
|
|
1684
|
-
const sendFn = ctx.sendActivity;
|
|
1614
|
+
const sendFn = (activity) => require_resolve_allowlist.withMSTeamsConnectorHandoff(params, () => ctx.sendActivity(activity));
|
|
1685
1615
|
const messageIds = [];
|
|
1686
1616
|
for (const [idx, message] of messages.entries()) {
|
|
1687
1617
|
const result = await withRevokedProxyFallback({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
1
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CHzaaWiC.cjs");
|
|
2
2
|
let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
|
|
3
3
|
let openclaw_plugin_sdk_provider_auth = require("openclaw/plugin-sdk/provider-auth");
|
|
4
4
|
let openclaw_plugin_sdk_provider_auth_runtime = require("openclaw/plugin-sdk/provider-auth-runtime");
|
|
@@ -224,7 +224,6 @@ const MSTEAMS_SQLITE_MAX_POLL_ROWS = 2e3;
|
|
|
224
224
|
const MSTEAMS_POLL_VOTE_BUCKET_COUNT = 32;
|
|
225
225
|
const MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS = 1001 * MSTEAMS_POLL_VOTE_BUCKET_COUNT;
|
|
226
226
|
const MSTEAMS_POLL_TTL_MS = 2592e6;
|
|
227
|
-
const POLL_MUTATION_KEY = "polls";
|
|
228
227
|
function normalizeChoiceValue(value) {
|
|
229
228
|
if (typeof value === "string") {
|
|
230
229
|
const trimmed = value.trim();
|
|
@@ -404,8 +403,11 @@ function createMSTeamsPollStoreState(params) {
|
|
|
404
403
|
for (const row of await voteBucketStore.entries()) if (row.value.pollId === pollId) Object.assign(votes, row.value.votes);
|
|
405
404
|
return votes;
|
|
406
405
|
};
|
|
407
|
-
const deletePollVotes = async (pollId) => {
|
|
408
|
-
for (const row of await voteBucketStore.entries()) if (row.value.pollId === pollId)
|
|
406
|
+
const deletePollVotes = async (pollId, cachedRows) => {
|
|
407
|
+
for (const row of cachedRows?.values() ?? await voteBucketStore.entries()) if (row.value.pollId === pollId) {
|
|
408
|
+
await voteBucketStore.delete(row.key);
|
|
409
|
+
cachedRows?.delete(row.key);
|
|
410
|
+
}
|
|
409
411
|
};
|
|
410
412
|
const registerPollVotes = async (pollId, votes, updatedAt) => {
|
|
411
413
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -450,11 +452,16 @@ function createMSTeamsPollStoreState(params) {
|
|
|
450
452
|
};
|
|
451
453
|
};
|
|
452
454
|
const prunePollStoreToLimit = async () => {
|
|
455
|
+
let voteRows;
|
|
456
|
+
const deletePrunedPollVotes = async (pollId) => {
|
|
457
|
+
voteRows ??= new Map((await voteBucketStore.entries()).map((row) => [row.key, row]));
|
|
458
|
+
await deletePollVotes(pollId, voteRows);
|
|
459
|
+
};
|
|
453
460
|
const rows = [];
|
|
454
461
|
for (const row of await pollStore.entries()) {
|
|
455
462
|
if (!pruneExpired({ [row.key]: row.value })[row.key]) {
|
|
456
463
|
await pollStore.delete(row.key);
|
|
457
|
-
await
|
|
464
|
+
await deletePrunedPollVotes(row.value.id);
|
|
458
465
|
continue;
|
|
459
466
|
}
|
|
460
467
|
rows.push(row);
|
|
@@ -465,11 +472,11 @@ function createMSTeamsPollStoreState(params) {
|
|
|
465
472
|
});
|
|
466
473
|
for (const row of sorted.slice(0, rows.length - MSTEAMS_MAX_POLLS)) {
|
|
467
474
|
await pollStore.delete(row.key);
|
|
468
|
-
await
|
|
475
|
+
await deletePrunedPollVotes(row.value.id);
|
|
469
476
|
}
|
|
470
477
|
};
|
|
471
478
|
const createPoll = async (poll) => {
|
|
472
|
-
await withMSTeamsSqliteMutationLock(params,
|
|
479
|
+
await withMSTeamsSqliteMutationLock(params, MSTEAMS_POLLS_NAMESPACE, async () => {
|
|
473
480
|
const { metadata, votes } = splitMSTeamsPoll(poll);
|
|
474
481
|
await pollStore.register(buildMSTeamsPollStateKey(poll.id), toPluginJsonValue(metadata));
|
|
475
482
|
await deletePollVotes(poll.id);
|
|
@@ -484,7 +491,7 @@ function createMSTeamsPollStoreState(params) {
|
|
|
484
491
|
return await reconstructPoll(poll);
|
|
485
492
|
};
|
|
486
493
|
const recordVote = async (vote) => {
|
|
487
|
-
return await withMSTeamsSqliteMutationLock(params,
|
|
494
|
+
return await withMSTeamsSqliteMutationLock(params, MSTEAMS_POLLS_NAMESPACE, async () => {
|
|
488
495
|
const pollKey = buildMSTeamsPollStateKey(vote.pollId);
|
|
489
496
|
const poll = await pollStore.lookup(pollKey);
|
|
490
497
|
if (!poll) return null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
1
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CHzaaWiC.cjs");
|
|
2
2
|
let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
|
|
3
3
|
//#region extensions/msteams/src/graph-thread.ts
|
|
4
4
|
/**
|