@openclaw/msteams 2026.7.1 → 2026.7.2-beta.2
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.cjs +8 -0
- package/dist/{channel-Cf5LJ4aO.js → channel-BKc8zroK.cjs} +648 -240
- package/dist/channel-config-api.cjs +3 -0
- package/dist/channel-plugin-api.cjs +3 -0
- package/dist/channel.runtime-hd1Zsoo2.cjs +1372 -0
- package/dist/{config-schema-BL4qQZiA.js → config-schema-BSNLJUta.cjs} +13 -3
- package/dist/{directory-contract-api.js → directory-contract-api.cjs} +8 -7
- package/dist/{doctor-contract-api.js → doctor-contract-api.cjs} +73 -57
- package/dist/index.cjs +21 -0
- package/dist/{probe-BnyZRZsD.js → messenger-BVcKl6dv.cjs} +436 -891
- package/dist/{oauth-BifWxWzq.js → oauth-yNoKtU_3.cjs} +21 -21
- package/dist/{polls-B_hs4aKm.js → polls-BhoI4VaN.cjs} +188 -38
- package/dist/{resolve-allowlist-Dnw4aNOu.js → resolve-allowlist-DXd097EP.cjs} +849 -140
- package/dist/rolldown-runtime-D6vf50IK.cjs +28 -0
- package/dist/runtime-api.cjs +207 -0
- package/dist/runtime-gZTAuFux.cjs +24 -0
- package/dist/secret-contract-api.cjs +31 -0
- package/dist/setup-entry.cjs +14 -0
- package/dist/setup-plugin-api.cjs +65 -0
- package/dist/{setup-surface-qW-ECHL-.js → setup-surface-D4f6x5cx.cjs} +127 -61
- package/dist/{src-DZFs5XtZ.js → src-20YasZEp.cjs} +686 -748
- package/dist/{sso-token-store-DrVbnCUF.js → sso-token-store-CktCz88k.cjs} +51 -10
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +10 -31
- package/package.json +8 -7
- package/dist/api.js +0 -3
- package/dist/channel-config-api.js +0 -2
- package/dist/channel-plugin-api.js +0 -2
- package/dist/channel.runtime-Bwu6Tjhf.js +0 -664
- package/dist/index.js +0 -22
- package/dist/runtime-BS5AZrKK.js +0 -8
- package/dist/runtime-api.js +0 -20
- package/dist/secret-contract-api.js +0 -35
- package/dist/setup-entry.js +0 -15
- package/dist/setup-plugin-api.js +0 -64
|
@@ -1,24 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
|
|
2
|
+
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
3
|
+
require("./runtime-api.cjs");
|
|
4
|
+
const require_resolve_allowlist = require("./resolve-allowlist-DXd097EP.cjs");
|
|
5
|
+
const require_setup_surface = require("./setup-surface-D4f6x5cx.cjs");
|
|
6
|
+
const require_polls = require("./polls-BhoI4VaN.cjs");
|
|
7
|
+
let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
|
|
8
|
+
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
9
|
+
let openclaw_plugin_sdk_reply_payload = require("openclaw/plugin-sdk/reply-payload");
|
|
10
|
+
let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
|
|
11
|
+
let node_dns_promises = require("node:dns/promises");
|
|
12
|
+
let openclaw_plugin_sdk_ssrf_policy = require("openclaw/plugin-sdk/ssrf-policy");
|
|
13
|
+
let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text-utility-runtime");
|
|
14
|
+
let node_path = require("node:path");
|
|
15
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
16
|
+
let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
|
|
17
|
+
let node_crypto = require("node:crypto");
|
|
18
|
+
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
19
|
+
let openclaw_plugin_sdk_reply_chunking = require("openclaw/plugin-sdk/reply-chunking");
|
|
20
|
+
let openclaw_plugin_sdk_web_media = require("openclaw/plugin-sdk/web-media");
|
|
21
|
+
let openclaw_plugin_sdk_media_runtime = require("openclaw/plugin-sdk/media-runtime");
|
|
22
|
+
//#region extensions/msteams/src/graph-thread.ts
|
|
23
|
+
/**
|
|
24
|
+
* Strip HTML tags from Teams message content, preserving @mention display names.
|
|
25
|
+
* Teams wraps mentions in <at>Name</at> tags.
|
|
26
|
+
*/
|
|
27
|
+
function stripHtmlFromTeamsMessage(html) {
|
|
28
|
+
let text = html.replace(/<at[^>]*>(.*?)<\/at>/gi, "@$1");
|
|
29
|
+
text = text.replace(/<[^>]*>/g, " ");
|
|
30
|
+
text = (0, openclaw_plugin_sdk_html_entity_runtime.decodeHtmlEntities)(text).replaceAll("\xA0", " ");
|
|
31
|
+
return text.replace(/\s+/g, " ").trim();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Fetch a single channel message (the parent/root of a thread).
|
|
35
|
+
* Returns undefined on error so callers can degrade gracefully.
|
|
36
|
+
*/
|
|
37
|
+
async function fetchChannelMessage(token, groupId, channelId, messageId, deadline) {
|
|
38
|
+
const path = `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}?$select=id,from,body,createdDateTime`;
|
|
39
|
+
try {
|
|
40
|
+
return await require_resolve_allowlist.fetchGraphJson({
|
|
41
|
+
token,
|
|
42
|
+
path,
|
|
43
|
+
...deadline ? { deadline } : {}
|
|
44
|
+
});
|
|
45
|
+
} catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch a single chat message's full text via Graph and return plain text.
|
|
51
|
+
*
|
|
52
|
+
* Used to recover the complete quoted message for Teams quote replies: the
|
|
53
|
+
* inbound blockquote only carries a Teams-truncated `preview` snippet. The
|
|
54
|
+
* app-only `GET /chats/{chatId}/messages/{messageId}` endpoint IS permitted
|
|
55
|
+
* with the `Chat.Read.All` application permission.
|
|
56
|
+
*
|
|
57
|
+
* Returns undefined on any failure so callers degrade to the truncated preview.
|
|
58
|
+
*/
|
|
59
|
+
async function fetchChatMessageText(token, chatId, messageId, deadline) {
|
|
60
|
+
const path = `/chats/${encodeURIComponent(chatId)}/messages/${encodeURIComponent(messageId)}`;
|
|
61
|
+
try {
|
|
62
|
+
const msg = await require_resolve_allowlist.fetchGraphJson({
|
|
63
|
+
token,
|
|
64
|
+
path,
|
|
65
|
+
...deadline ? { deadline } : {}
|
|
66
|
+
});
|
|
67
|
+
const raw = msg.body?.content ?? "";
|
|
68
|
+
return (msg.body?.contentType === "html" ? stripHtmlFromTeamsMessage(raw) : raw.trim()) || void 0;
|
|
69
|
+
} catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Fetch thread replies for a channel message, ordered chronologically.
|
|
75
|
+
*
|
|
76
|
+
* **Limitation:** The Graph API replies endpoint (`/messages/{id}/replies`) does not
|
|
77
|
+
* support `$orderby`, so results are always returned in ascending (oldest-first) order.
|
|
78
|
+
* Combined with the `$top` cap of 50, this means only the **oldest 50 replies** are
|
|
79
|
+
* returned for long threads — newer replies are silently omitted. There is currently no
|
|
80
|
+
* Graph API workaround for this; pagination via `@odata.nextLink` can retrieve more
|
|
81
|
+
* replies but still in ascending order only.
|
|
82
|
+
*/
|
|
83
|
+
async function fetchThreadReplies(token, groupId, channelId, messageId, limit = 50, deadline) {
|
|
84
|
+
return (await require_resolve_allowlist.fetchGraphJson({
|
|
85
|
+
token,
|
|
86
|
+
path: `/teams/${encodeURIComponent(groupId)}/channels/${encodeURIComponent(channelId)}/messages/${encodeURIComponent(messageId)}/replies?$top=${Math.min(Math.max(limit, 1), 50)}&$select=id,from,body,createdDateTime`,
|
|
87
|
+
...deadline ? { deadline } : {}
|
|
88
|
+
})).value ?? [];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format thread messages into a context string for the agent.
|
|
92
|
+
* Skips the current message (by id) and blank messages.
|
|
93
|
+
*/
|
|
94
|
+
function formatThreadContext(messages, currentMessageId) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
for (const msg of messages) {
|
|
97
|
+
if (msg.id && msg.id === currentMessageId) continue;
|
|
98
|
+
const sender = msg.from?.user?.displayName ?? msg.from?.application?.displayName ?? "unknown";
|
|
99
|
+
const contentType = msg.body?.contentType ?? "text";
|
|
100
|
+
const rawContent = msg.body?.content ?? "";
|
|
101
|
+
const content = contentType === "html" ? stripHtmlFromTeamsMessage(rawContent) : rawContent.trim();
|
|
102
|
+
if (!content) continue;
|
|
103
|
+
lines.push(`${sender}: ${content}`);
|
|
104
|
+
}
|
|
105
|
+
return lines.join("\n");
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region extensions/msteams/src/reaction-types.ts
|
|
109
|
+
const TEAMS_REACTION_EMOJI = {
|
|
110
|
+
like: "👍",
|
|
111
|
+
heart: "❤️",
|
|
112
|
+
laugh: "😆",
|
|
113
|
+
surprised: "😮",
|
|
114
|
+
sad: "😢",
|
|
115
|
+
angry: "😡"
|
|
116
|
+
};
|
|
117
|
+
const TEAMS_REACTION_TYPES = Object.keys(TEAMS_REACTION_EMOJI);
|
|
118
|
+
function getMSTeamsReactionEmoji(raw) {
|
|
119
|
+
return TEAMS_REACTION_EMOJI[raw.trim().toLowerCase()];
|
|
120
|
+
}
|
|
121
|
+
function resolveMSTeamsReactionEmoji(raw) {
|
|
122
|
+
const normalized = raw.trim();
|
|
123
|
+
if (!normalized) throw new Error(`Reaction type is required. Common types: ${TEAMS_REACTION_TYPES.join(", ")}`);
|
|
124
|
+
return getMSTeamsReactionEmoji(normalized) ?? normalized;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
22
127
|
//#region extensions/msteams/src/file-consent.ts
|
|
23
128
|
/**
|
|
24
129
|
* FileConsentCard utilities for MS Teams large file uploads (>4MB) in personal chats.
|
|
@@ -52,7 +157,7 @@ const CONSENT_UPLOAD_HOST_ALLOWLIST = [
|
|
|
52
157
|
* Returns true if the given IPv4 or IPv6 address is private, internal, or
|
|
53
158
|
* special-use and must never be reached via consent uploads.
|
|
54
159
|
*/
|
|
55
|
-
const isPrivateOrReservedIP = isPrivateIpAddress;
|
|
160
|
+
const isPrivateOrReservedIP = openclaw_plugin_sdk_ssrf_policy.isPrivateIpAddress;
|
|
56
161
|
/**
|
|
57
162
|
* Validate that a consent upload URL is safe to PUT to.
|
|
58
163
|
* Checks:
|
|
@@ -70,9 +175,9 @@ async function validateConsentUploadUrl(url, opts) {
|
|
|
70
175
|
throw new Error("Consent upload URL is not a valid URL");
|
|
71
176
|
}
|
|
72
177
|
if (parsed.protocol !== "https:") throw new Error(`Consent upload URL must use HTTPS, got ${parsed.protocol}`);
|
|
73
|
-
const hostname = normalizeLowercaseStringOrEmpty(parsed.hostname);
|
|
178
|
+
const hostname = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(parsed.hostname);
|
|
74
179
|
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`);
|
|
75
|
-
const resolveFn = opts?.resolveFn ?? ((name) => lookup(name, { all: true }));
|
|
180
|
+
const resolveFn = opts?.resolveFn ?? ((name) => (0, node_dns_promises.lookup)(name, { all: true }));
|
|
76
181
|
let resolved;
|
|
77
182
|
try {
|
|
78
183
|
const result = await resolveFn(hostname);
|
|
@@ -141,15 +246,16 @@ function parseFileConsentInvoke(activity) {
|
|
|
141
246
|
*/
|
|
142
247
|
async function uploadToConsentUrl(params) {
|
|
143
248
|
await validateConsentUploadUrl(params.url, params.validationOpts);
|
|
144
|
-
const
|
|
249
|
+
const fetchFn = params.fetchFn ?? fetch;
|
|
250
|
+
const res = await (0, openclaw_plugin_sdk_text_utility_runtime.fetchWithTimeout)(params.url, {
|
|
145
251
|
method: "PUT",
|
|
146
252
|
headers: {
|
|
147
|
-
"User-Agent": buildUserAgent(),
|
|
253
|
+
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
148
254
|
"Content-Type": params.contentType ?? "application/octet-stream",
|
|
149
255
|
"Content-Range": `bytes 0-${params.buffer.length - 1}/${params.buffer.length}`
|
|
150
256
|
},
|
|
151
257
|
body: new Uint8Array(params.buffer)
|
|
152
|
-
});
|
|
258
|
+
}, params.timeoutMs ?? require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length), fetchFn);
|
|
153
259
|
if (!res.ok) throw new Error(`File upload to consent URL failed: ${res.status} ${res.statusText}`);
|
|
154
260
|
}
|
|
155
261
|
//#endregion
|
|
@@ -166,21 +272,21 @@ const PENDING_UPLOAD_META_NAMESPACE = "pending-uploads";
|
|
|
166
272
|
const PENDING_UPLOAD_CHUNKS_NAMESPACE = "pending-upload-chunks";
|
|
167
273
|
const PENDING_UPLOAD_LOCK_FILENAME = "msteams-pending-uploads.sqlite.lock";
|
|
168
274
|
function createMetaStore(options) {
|
|
169
|
-
return getMSTeamsRuntime().state.openKeyedStore({
|
|
275
|
+
return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
|
|
170
276
|
namespace: PENDING_UPLOAD_META_NAMESPACE,
|
|
171
277
|
maxEntries: PENDING_UPLOAD_META_MAX_ENTRIES,
|
|
172
|
-
env: resolveMSTeamsSqliteStateEnv(options)
|
|
278
|
+
env: require_polls.resolveMSTeamsSqliteStateEnv(options)
|
|
173
279
|
});
|
|
174
280
|
}
|
|
175
281
|
function createChunkStore(options) {
|
|
176
|
-
return getMSTeamsRuntime().state.openKeyedStore({
|
|
282
|
+
return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
|
|
177
283
|
namespace: PENDING_UPLOAD_CHUNKS_NAMESPACE,
|
|
178
284
|
maxEntries: MAX_PENDING_UPLOAD_CHUNK_ROWS,
|
|
179
|
-
env: resolveMSTeamsSqliteStateEnv(options)
|
|
285
|
+
env: require_polls.resolveMSTeamsSqliteStateEnv(options)
|
|
180
286
|
});
|
|
181
287
|
}
|
|
182
288
|
function buildUploadKey(id) {
|
|
183
|
-
return `upload:${createHash("sha256").update(id).digest("hex")}`;
|
|
289
|
+
return `upload:${(0, node_crypto.createHash)("sha256").update(id).digest("hex")}`;
|
|
184
290
|
}
|
|
185
291
|
function buildMetaKey(id) {
|
|
186
292
|
return `${buildUploadKey(id)}:meta`;
|
|
@@ -215,13 +321,13 @@ async function registerUploadRows(record, metaStore, chunkStore, ttlMs, overwrit
|
|
|
215
321
|
await pruneUploadStore(metaStore, chunkStore, ttlMs, chunkCount);
|
|
216
322
|
for (let index = 0; index < chunkCount; index += 1) {
|
|
217
323
|
const chunk = buffer.subarray(index * RAW_CHUNK_BYTES, (index + 1) * RAW_CHUNK_BYTES);
|
|
218
|
-
await chunkStore.register(buildChunkKey(record.id, index), toPluginJsonValue({
|
|
324
|
+
await chunkStore.register(buildChunkKey(record.id, index), require_polls.toPluginJsonValue({
|
|
219
325
|
id: record.id,
|
|
220
326
|
index,
|
|
221
327
|
dataBase64: chunk.toString("base64")
|
|
222
328
|
}));
|
|
223
329
|
}
|
|
224
|
-
await metaStore.register(buildMetaKey(record.id), toPluginJsonValue({
|
|
330
|
+
await metaStore.register(buildMetaKey(record.id), require_polls.toPluginJsonValue({
|
|
225
331
|
id: record.id,
|
|
226
332
|
filename: record.filename,
|
|
227
333
|
contentType: record.contentType,
|
|
@@ -233,7 +339,7 @@ async function registerUploadRows(record, metaStore, chunkStore, ttlMs, overwrit
|
|
|
233
339
|
}));
|
|
234
340
|
}
|
|
235
341
|
async function withPendingUploadLock(options, run) {
|
|
236
|
-
return await withMSTeamsSqliteMutationLock(options, PENDING_UPLOAD_LOCK_FILENAME, run);
|
|
342
|
+
return await require_polls.withMSTeamsSqliteMutationLock(options, PENDING_UPLOAD_LOCK_FILENAME, run);
|
|
237
343
|
}
|
|
238
344
|
async function readUploadRows(id, metaStore, chunkStore) {
|
|
239
345
|
const meta = await metaStore.lookup(buildMetaKey(id));
|
|
@@ -326,7 +432,7 @@ async function setPendingUploadActivityIdFs(id, activityId, options) {
|
|
|
326
432
|
await withPendingUploadLock(options, async () => {
|
|
327
433
|
const record = await metaStore.lookup(buildMetaKey(id));
|
|
328
434
|
if (!record || Date.now() - record.createdAt > ttlMs) return;
|
|
329
|
-
await metaStore.register(buildMetaKey(id), toPluginJsonValue({
|
|
435
|
+
await metaStore.register(buildMetaKey(id), require_polls.toPluginJsonValue({
|
|
330
436
|
...record,
|
|
331
437
|
consentCardActivityId: activityId
|
|
332
438
|
}));
|
|
@@ -351,7 +457,7 @@ const PENDING_UPLOAD_TTL_MS = 300 * 1e3;
|
|
|
351
457
|
* Returns the upload ID to include in the FileConsentCard context.
|
|
352
458
|
*/
|
|
353
459
|
function storePendingUpload(upload) {
|
|
354
|
-
const id =
|
|
460
|
+
const id = node_crypto.default.randomUUID();
|
|
355
461
|
const entry = {
|
|
356
462
|
...upload,
|
|
357
463
|
id,
|
|
@@ -485,7 +591,7 @@ async function prepareFileConsentActivityFs(params) {
|
|
|
485
591
|
* True for: personal chat AND (large file OR non-image)
|
|
486
592
|
*/
|
|
487
593
|
function requiresFileConsent(params) {
|
|
488
|
-
const isPersonal = normalizeOptionalLowercaseString(params.conversationType) === "personal";
|
|
594
|
+
const isPersonal = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalLowercaseString)(params.conversationType) === "personal";
|
|
489
595
|
const isImage = params.contentType?.startsWith("image/") ?? false;
|
|
490
596
|
const isLargeFile = params.bufferSize >= params.thresholdBytes;
|
|
491
597
|
return isPersonal && (isLargeFile || !isImage);
|
|
@@ -496,7 +602,7 @@ function buildTeamsFileInfoCard(file) {
|
|
|
496
602
|
const rawETag = file.eTag;
|
|
497
603
|
const uniqueId = rawETag.replace(/^["']|["']$/g, "").replace(/[{}]/g, "").split(",")[0] ?? rawETag;
|
|
498
604
|
const lastDot = file.name.lastIndexOf(".");
|
|
499
|
-
const fileType = lastDot >= 0 ? normalizeLowercaseStringOrEmpty(file.name.slice(lastDot + 1)) : "";
|
|
605
|
+
const fileType = lastDot >= 0 ? (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(file.name.slice(lastDot + 1)) : "";
|
|
500
606
|
return {
|
|
501
607
|
contentType: "application/vnd.microsoft.teams.card.file.info",
|
|
502
608
|
contentUrl: file.webDavUrl,
|
|
@@ -510,11 +616,10 @@ function buildTeamsFileInfoCard(file) {
|
|
|
510
616
|
//#endregion
|
|
511
617
|
//#region extensions/msteams/src/graph-upload.ts
|
|
512
618
|
/**
|
|
513
|
-
*
|
|
619
|
+
* SharePoint upload utilities for MS Teams file sending.
|
|
514
620
|
*
|
|
515
621
|
* For group chats and channels, files are uploaded to SharePoint and shared via a link.
|
|
516
622
|
* This module provides utilities for:
|
|
517
|
-
* - Uploading files to OneDrive (personal scope - now deprecated for bot use)
|
|
518
623
|
* - Uploading files to SharePoint (group/channel scope)
|
|
519
624
|
* - Creating sharing links (organization-wide or per-user)
|
|
520
625
|
* - Getting chat members for per-user sharing
|
|
@@ -522,80 +627,19 @@ function buildTeamsFileInfoCard(file) {
|
|
|
522
627
|
const GRAPH_ROOT = "https://graph.microsoft.com/v1.0";
|
|
523
628
|
const GRAPH_BETA = "https://graph.microsoft.com/beta";
|
|
524
629
|
const GRAPH_SCOPE = "https://graph.microsoft.com";
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
Authorization: `Bearer ${token}`,
|
|
538
|
-
"Content-Type": params.contentType ?? "application/octet-stream"
|
|
539
|
-
},
|
|
540
|
-
body: new Uint8Array(params.buffer)
|
|
541
|
-
});
|
|
542
|
-
if (!res.ok) throw await createMSTeamsHttpError(res, "OneDrive upload failed");
|
|
543
|
-
const data = await readProviderJsonResponse(res, "msteams.graph-upload.uploadOneDriveFile");
|
|
544
|
-
if (!data.id || !data.webUrl || !data.name) throw new Error("OneDrive upload response missing required fields");
|
|
545
|
-
return {
|
|
546
|
-
id: data.id,
|
|
547
|
-
webUrl: data.webUrl,
|
|
548
|
-
name: data.name
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Create a sharing link for a OneDrive file.
|
|
553
|
-
* The link allows organization members to view the file.
|
|
554
|
-
*/
|
|
555
|
-
async function createSharingLink(params) {
|
|
556
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
557
|
-
const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
|
|
558
|
-
const res = await fetchFn(`${GRAPH_ROOT}/me/drive/items/${params.itemId}/createLink`, {
|
|
559
|
-
method: "POST",
|
|
560
|
-
headers: {
|
|
561
|
-
"User-Agent": buildUserAgent(),
|
|
562
|
-
Authorization: `Bearer ${token}`,
|
|
563
|
-
"Content-Type": "application/json"
|
|
564
|
-
},
|
|
565
|
-
body: JSON.stringify({
|
|
566
|
-
type: "view",
|
|
567
|
-
scope: params.scope ?? "organization"
|
|
568
|
-
})
|
|
569
|
-
});
|
|
570
|
-
if (!res.ok) throw await createMSTeamsHttpError(res, "Create sharing link failed");
|
|
571
|
-
const data = await readProviderJsonResponse(res, "msteams.graph-upload.createOneDriveSharingLink");
|
|
572
|
-
if (!data.link?.webUrl) throw new Error("Create sharing link response missing webUrl");
|
|
573
|
-
return { webUrl: data.link.webUrl };
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Upload a file to OneDrive and create a sharing link.
|
|
577
|
-
* Convenience function for the common case.
|
|
578
|
-
*/
|
|
579
|
-
async function uploadAndShareOneDrive(params) {
|
|
580
|
-
const uploaded = await uploadToOneDrive({
|
|
581
|
-
buffer: params.buffer,
|
|
582
|
-
filename: params.filename,
|
|
583
|
-
contentType: params.contentType,
|
|
584
|
-
tokenProvider: params.tokenProvider,
|
|
585
|
-
fetchFn: params.fetchFn
|
|
630
|
+
function requireMSTeamsSharePointSiteId(siteId) {
|
|
631
|
+
const normalized = siteId?.trim();
|
|
632
|
+
if (!normalized) throw new Error("channels.msteams.sharePointSiteId is required to send files to group chats or channels");
|
|
633
|
+
return normalized;
|
|
634
|
+
}
|
|
635
|
+
const SHAREPOINT_REQUEST_TIMEOUT_LABEL = "MS Teams SharePoint request";
|
|
636
|
+
const SHAREPOINT_UPLOAD_TIMEOUT_LABEL = "MS Teams SharePoint upload";
|
|
637
|
+
const GRAPH_TOKEN_TIMEOUT_LABEL = "MS Teams Graph token acquisition";
|
|
638
|
+
async function getGraphAccessToken(tokenProvider) {
|
|
639
|
+
return await require_resolve_allowlist.withMSTeamsRequestDeadline({
|
|
640
|
+
label: GRAPH_TOKEN_TIMEOUT_LABEL,
|
|
641
|
+
work: async () => await tokenProvider.getAccessToken(GRAPH_SCOPE)
|
|
586
642
|
});
|
|
587
|
-
const shareLink = await createSharingLink({
|
|
588
|
-
itemId: uploaded.id,
|
|
589
|
-
tokenProvider: params.tokenProvider,
|
|
590
|
-
scope: params.scope,
|
|
591
|
-
fetchFn: params.fetchFn
|
|
592
|
-
});
|
|
593
|
-
return {
|
|
594
|
-
itemId: uploaded.id,
|
|
595
|
-
webUrl: uploaded.webUrl,
|
|
596
|
-
shareUrl: shareLink.webUrl,
|
|
597
|
-
name: uploaded.name
|
|
598
|
-
};
|
|
599
643
|
}
|
|
600
644
|
/**
|
|
601
645
|
* Upload a file to a SharePoint site.
|
|
@@ -605,19 +649,26 @@ async function uploadAndShareOneDrive(params) {
|
|
|
605
649
|
*/
|
|
606
650
|
async function uploadToSharePoint(params) {
|
|
607
651
|
const fetchFn = params.fetchFn ?? fetch;
|
|
608
|
-
const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
|
|
609
652
|
const uploadPath = `/OpenClawShared/${encodeURIComponent(params.filename)}`;
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
653
|
+
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
654
|
+
label: SHAREPOINT_UPLOAD_TIMEOUT_LABEL,
|
|
655
|
+
timeoutMs: require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length),
|
|
656
|
+
work: async (signal) => {
|
|
657
|
+
const token = await getGraphAccessToken(params.tokenProvider);
|
|
658
|
+
const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content`, {
|
|
659
|
+
method: "PUT",
|
|
660
|
+
headers: {
|
|
661
|
+
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
662
|
+
Authorization: `Bearer ${token}`,
|
|
663
|
+
"Content-Type": params.contentType ?? "application/octet-stream"
|
|
664
|
+
},
|
|
665
|
+
body: new Uint8Array(params.buffer),
|
|
666
|
+
signal
|
|
667
|
+
});
|
|
668
|
+
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "SharePoint upload failed");
|
|
669
|
+
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.uploadSharePointFile");
|
|
670
|
+
}
|
|
618
671
|
});
|
|
619
|
-
if (!res.ok) throw await createMSTeamsHttpError(res, "SharePoint upload failed");
|
|
620
|
-
const data = await readProviderJsonResponse(res, "msteams.graph-upload.uploadSharePointFile");
|
|
621
672
|
if (!data.id || !data.webUrl || !data.name) throw new Error("SharePoint upload response missing required fields");
|
|
622
673
|
return {
|
|
623
674
|
id: data.id,
|
|
@@ -634,13 +685,21 @@ async function uploadToSharePoint(params) {
|
|
|
634
685
|
*/
|
|
635
686
|
async function getDriveItemProperties(params) {
|
|
636
687
|
const fetchFn = params.fetchFn ?? fetch;
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
688
|
+
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
689
|
+
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
690
|
+
work: async (signal) => {
|
|
691
|
+
const token = await getGraphAccessToken(params.tokenProvider);
|
|
692
|
+
const res = await fetchFn(`${GRAPH_ROOT}/sites/${params.siteId}/drive/items/${params.itemId}?$select=eTag,webDavUrl,name`, {
|
|
693
|
+
headers: {
|
|
694
|
+
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
695
|
+
Authorization: `Bearer ${token}`
|
|
696
|
+
},
|
|
697
|
+
signal
|
|
698
|
+
});
|
|
699
|
+
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Get driveItem properties failed");
|
|
700
|
+
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getDriveItemProperties");
|
|
701
|
+
}
|
|
702
|
+
});
|
|
644
703
|
if (!data.eTag || !data.webDavUrl || !data.name) throw new Error("DriveItem response missing required properties (eTag, webDavUrl, or name)");
|
|
645
704
|
return {
|
|
646
705
|
eTag: data.eTag,
|
|
@@ -649,49 +708,26 @@ async function getDriveItemProperties(params) {
|
|
|
649
708
|
};
|
|
650
709
|
}
|
|
651
710
|
/**
|
|
652
|
-
* Resolve the Graph API-native chat ID from a Bot Framework conversation ID.
|
|
653
|
-
*
|
|
654
|
-
* Bot Framework personal DM conversation IDs use formats like `a:1xxx@unq.gbl.spaces`
|
|
655
|
-
* or `8:orgid:xxx` that the Graph API does not accept. Graph API requires the
|
|
656
|
-
* `19:xxx@thread.tacv2` or `19:xxx@unq.gbl.spaces` format.
|
|
657
|
-
*
|
|
658
|
-
* This function looks up the matching Graph chat by querying the bot's chats filtered
|
|
659
|
-
* by the target user's AAD object ID.
|
|
660
|
-
*/
|
|
661
|
-
async function resolveGraphChatId(params) {
|
|
662
|
-
const { botFrameworkConversationId, userAadObjectId, tokenProvider } = params;
|
|
663
|
-
const fetchFn = params.fetchFn ?? fetch;
|
|
664
|
-
if (botFrameworkConversationId.startsWith("19:")) return botFrameworkConversationId;
|
|
665
|
-
const token = await tokenProvider.getAccessToken(GRAPH_SCOPE);
|
|
666
|
-
let path;
|
|
667
|
-
if (userAadObjectId) path = `/me/chats?$filter=${encodeURIComponent(`chatType eq 'oneOnOne' and members/any(m:m/microsoft.graph.aadUserConversationMember/userId eq '${userAadObjectId}')`)}&$select=id`;
|
|
668
|
-
else path = `/me/chats?$filter=${encodeURIComponent("chatType eq 'oneOnOne'")}&$select=id`;
|
|
669
|
-
const res = await fetchFn(`${GRAPH_ROOT}${path}`, { headers: {
|
|
670
|
-
"User-Agent": buildUserAgent(),
|
|
671
|
-
Authorization: `Bearer ${token}`
|
|
672
|
-
} });
|
|
673
|
-
if (!res.ok) return null;
|
|
674
|
-
const chats = (await readProviderJsonResponse(res, "msteams.graph-upload.getOneOnOneChatId")).value ?? [];
|
|
675
|
-
if (userAadObjectId && chats.length > 0 && chats[0]?.id) return chats[0].id;
|
|
676
|
-
if (!userAadObjectId && chats.length === 1 && chats[0]?.id) return chats[0].id;
|
|
677
|
-
return null;
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
711
|
* Get members of a Teams chat for per-user sharing.
|
|
681
712
|
* Used to create sharing links scoped to only the chat participants.
|
|
682
713
|
*/
|
|
683
714
|
async function getChatMembers(params) {
|
|
684
715
|
const fetchFn = params.fetchFn ?? fetch;
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
716
|
+
return await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
717
|
+
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
718
|
+
work: async (signal) => {
|
|
719
|
+
const token = await getGraphAccessToken(params.tokenProvider);
|
|
720
|
+
const res = await fetchFn(`${GRAPH_ROOT}/chats/${params.chatId}/members`, {
|
|
721
|
+
headers: {
|
|
722
|
+
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
723
|
+
Authorization: `Bearer ${token}`
|
|
724
|
+
},
|
|
725
|
+
signal
|
|
726
|
+
});
|
|
727
|
+
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, res.status === 403 ? "Get chat members failed; verify Graph chat-member permissions and tenant access policies" : "Get chat members failed");
|
|
728
|
+
return ((await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.getChatMembers")).value ?? []).map((member) => ({ aadObjectId: member.userId ?? "" })).filter((member) => member.aadObjectId);
|
|
729
|
+
}
|
|
730
|
+
});
|
|
695
731
|
}
|
|
696
732
|
/**
|
|
697
733
|
* Create a sharing link for a SharePoint drive item.
|
|
@@ -700,7 +736,6 @@ async function getChatMembers(params) {
|
|
|
700
736
|
*/
|
|
701
737
|
async function createSharePointSharingLink(params) {
|
|
702
738
|
const fetchFn = params.fetchFn ?? fetch;
|
|
703
|
-
const token = await params.tokenProvider.getAccessToken(GRAPH_SCOPE);
|
|
704
739
|
const scope = params.scope ?? "organization";
|
|
705
740
|
const apiRoot = scope === "users" ? GRAPH_BETA : GRAPH_ROOT;
|
|
706
741
|
const body = {
|
|
@@ -708,17 +743,24 @@ async function createSharePointSharingLink(params) {
|
|
|
708
743
|
scope: scope === "users" ? "users" : "organization"
|
|
709
744
|
};
|
|
710
745
|
if (scope === "users" && params.recipientObjectIds?.length) body.recipients = params.recipientObjectIds.map((id) => ({ objectId: id }));
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
746
|
+
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
747
|
+
label: SHAREPOINT_REQUEST_TIMEOUT_LABEL,
|
|
748
|
+
work: async (signal) => {
|
|
749
|
+
const token = await getGraphAccessToken(params.tokenProvider);
|
|
750
|
+
const res = await fetchFn(`${apiRoot}/sites/${params.siteId}/drive/items/${params.itemId}/createLink`, {
|
|
751
|
+
method: "POST",
|
|
752
|
+
headers: {
|
|
753
|
+
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
754
|
+
Authorization: `Bearer ${token}`,
|
|
755
|
+
"Content-Type": "application/json"
|
|
756
|
+
},
|
|
757
|
+
body: JSON.stringify(body),
|
|
758
|
+
signal
|
|
759
|
+
});
|
|
760
|
+
if (!res.ok) throw await require_resolve_allowlist.createMSTeamsHttpError(res, "Create SharePoint sharing link failed");
|
|
761
|
+
return await (0, openclaw_plugin_sdk_provider_http.readProviderJsonResponse)(res, "msteams.graph-upload.createSharePointSharingLink");
|
|
762
|
+
}
|
|
719
763
|
});
|
|
720
|
-
if (!res.ok) throw await createMSTeamsHttpError(res, "Create SharePoint sharing link failed");
|
|
721
|
-
const data = await readProviderJsonResponse(res, "msteams.graph-upload.createSharePointSharingLink");
|
|
722
764
|
if (!data.link?.webUrl) throw new Error("Create SharePoint sharing link response missing webUrl");
|
|
723
765
|
return { webUrl: data.link.webUrl };
|
|
724
766
|
}
|
|
@@ -730,7 +772,7 @@ async function createSharePointSharingLink(params) {
|
|
|
730
772
|
*
|
|
731
773
|
* @param params.siteId - SharePoint site ID
|
|
732
774
|
* @param params.chatId - Optional chat ID for per-user sharing (group chats)
|
|
733
|
-
* @param params.usePerUserSharing - Whether to use per-user sharing (requires beta API +
|
|
775
|
+
* @param params.usePerUserSharing - Whether to use per-user sharing (requires beta API + chat-member read access)
|
|
734
776
|
*/
|
|
735
777
|
async function uploadAndShareSharePoint(params) {
|
|
736
778
|
const uploaded = await uploadToSharePoint({
|
|
@@ -743,17 +785,16 @@ async function uploadAndShareSharePoint(params) {
|
|
|
743
785
|
});
|
|
744
786
|
let scope = "organization";
|
|
745
787
|
let recipientObjectIds;
|
|
746
|
-
if (params.usePerUserSharing && params.chatId)
|
|
788
|
+
if (params.usePerUserSharing && params.chatId) {
|
|
747
789
|
const members = await getChatMembers({
|
|
748
790
|
chatId: params.chatId,
|
|
749
791
|
tokenProvider: params.tokenProvider,
|
|
750
792
|
fetchFn: params.fetchFn
|
|
751
793
|
});
|
|
752
|
-
if (members.length
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
} catch {}
|
|
794
|
+
if (members.length === 0) throw new Error("MS Teams chat member lookup returned no recipients");
|
|
795
|
+
scope = "users";
|
|
796
|
+
recipientObjectIds = members.map((member) => member.aadObjectId);
|
|
797
|
+
}
|
|
757
798
|
const shareLink = await createSharePointSharingLink({
|
|
758
799
|
siteId: params.siteId,
|
|
759
800
|
itemId: uploaded.id,
|
|
@@ -783,7 +824,7 @@ async function getMimeType(url) {
|
|
|
783
824
|
const match = url.match(/^data:([^;,]+)/);
|
|
784
825
|
if (match?.[1]) return match[1];
|
|
785
826
|
}
|
|
786
|
-
return await detectMime({ filePath: url }) ?? "application/octet-stream";
|
|
827
|
+
return await (0, openclaw_plugin_sdk_media_runtime.detectMime)({ filePath: url }) ?? "application/octet-stream";
|
|
787
828
|
}
|
|
788
829
|
/**
|
|
789
830
|
* Extract filename from URL or local path.
|
|
@@ -793,20 +834,20 @@ async function getMimeType(url) {
|
|
|
793
834
|
async function extractFilename(url) {
|
|
794
835
|
if (url.startsWith("data:")) {
|
|
795
836
|
const mime = await getMimeType(url);
|
|
796
|
-
const ext = extensionForMime(mime) ?? ".bin";
|
|
837
|
+
const ext = (0, openclaw_plugin_sdk_media_runtime.extensionForMime)(mime) ?? ".bin";
|
|
797
838
|
return `${mime.startsWith("image/") ? "image" : "file"}${ext}`;
|
|
798
839
|
}
|
|
799
840
|
try {
|
|
800
841
|
const pathname = new URL(url).pathname;
|
|
801
|
-
const basename =
|
|
802
|
-
const existingExt = getFileExtension(pathname);
|
|
842
|
+
const basename = node_path.default.basename(pathname);
|
|
843
|
+
const existingExt = (0, openclaw_plugin_sdk_media_runtime.getFileExtension)(pathname);
|
|
803
844
|
if (basename && existingExt) return basename;
|
|
804
845
|
const mime = await getMimeType(url);
|
|
805
|
-
const ext = extensionForMime(mime) ?? ".bin";
|
|
846
|
+
const ext = (0, openclaw_plugin_sdk_media_runtime.extensionForMime)(mime) ?? ".bin";
|
|
806
847
|
const prefix = mime.startsWith("image/") ? "image" : "file";
|
|
807
848
|
return basename ? `${basename}${ext}` : `${prefix}${ext}`;
|
|
808
849
|
} catch {
|
|
809
|
-
return extractOriginalFilename(url);
|
|
850
|
+
return (0, openclaw_plugin_sdk_media_runtime.extractOriginalFilename)(url);
|
|
810
851
|
}
|
|
811
852
|
}
|
|
812
853
|
/**
|
|
@@ -883,21 +924,21 @@ async function withRevokedProxyFallback(params) {
|
|
|
883
924
|
try {
|
|
884
925
|
return await params.run();
|
|
885
926
|
} catch (err) {
|
|
886
|
-
if (!isRevokedProxyError(err)) throw err;
|
|
927
|
+
if (!require_setup_surface.isRevokedProxyError(err)) throw err;
|
|
887
928
|
params.onRevokedLog?.();
|
|
888
929
|
return await params.onRevoked();
|
|
889
930
|
}
|
|
890
931
|
}
|
|
891
932
|
//#endregion
|
|
892
933
|
//#region extensions/msteams/src/sdk-proactive.ts
|
|
893
|
-
const loadMSTeamsApiModule = createLazyRuntimeModule(() => import("@microsoft/teams.api"));
|
|
934
|
+
const loadMSTeamsApiModule = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api"));
|
|
894
935
|
function resolveThreadedConversationId(conversationId, threadActivityId) {
|
|
895
936
|
if (!threadActivityId) return conversationId.split(";")[0] ?? conversationId;
|
|
896
937
|
return `${conversationId.split(";")[0] ?? conversationId};messageid=${threadActivityId}`;
|
|
897
938
|
}
|
|
898
939
|
function normalizeRequiredServiceUrl(ref) {
|
|
899
940
|
if (!ref.serviceUrl) throw new Error("Invalid stored reference: missing serviceUrl");
|
|
900
|
-
return normalizeBotFrameworkServiceUrl(ref.serviceUrl);
|
|
941
|
+
return require_resolve_allowlist.normalizeBotFrameworkServiceUrl(ref.serviceUrl);
|
|
901
942
|
}
|
|
902
943
|
function buildSdkConversationReference(source, options) {
|
|
903
944
|
const bot = source.agent ?? source.bot ?? void 0;
|
|
@@ -905,7 +946,7 @@ function buildSdkConversationReference(source, options) {
|
|
|
905
946
|
const conversationId = resolveThreadedConversationId(source.conversation.id, options?.threadActivityId);
|
|
906
947
|
const tenantId = source.tenantId ?? source.conversation.tenantId;
|
|
907
948
|
const serviceUrl = normalizeRequiredServiceUrl(source);
|
|
908
|
-
if (options?.serviceUrlBoundary) validateMSTeamsProactiveServiceUrlBoundary({
|
|
949
|
+
if (options?.serviceUrlBoundary) require_resolve_allowlist.validateMSTeamsProactiveServiceUrlBoundary({
|
|
909
950
|
cloud: options.serviceUrlBoundary.cloud,
|
|
910
951
|
conversationId,
|
|
911
952
|
storedServiceUrl: serviceUrl,
|
|
@@ -938,7 +979,7 @@ function getStructuralApiClient(app) {
|
|
|
938
979
|
function sameServiceUrl(left, right) {
|
|
939
980
|
if (!left) return false;
|
|
940
981
|
try {
|
|
941
|
-
return normalizeBotFrameworkServiceUrl(left) === right;
|
|
982
|
+
return require_resolve_allowlist.normalizeBotFrameworkServiceUrl(left) === right;
|
|
942
983
|
} catch {
|
|
943
984
|
return false;
|
|
944
985
|
}
|
|
@@ -1026,14 +1067,14 @@ const AI_GENERATED_ENTITY = {
|
|
|
1026
1067
|
//#region extensions/msteams/src/messenger.ts
|
|
1027
1068
|
/**
|
|
1028
1069
|
* MSTeams-specific media size limit (100MB).
|
|
1029
|
-
* Higher than the default
|
|
1070
|
+
* Higher than the default to support Teams file-consent and SharePoint uploads.
|
|
1030
1071
|
*/
|
|
1031
|
-
const MSTEAMS_MAX_MEDIA_BYTES
|
|
1072
|
+
const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
1032
1073
|
/**
|
|
1033
1074
|
* Threshold for large files that require FileConsentCard flow in personal chats.
|
|
1034
1075
|
* Files >= 4MB use consent flow; smaller images can use inline base64.
|
|
1035
1076
|
*/
|
|
1036
|
-
const FILE_CONSENT_THRESHOLD_BYTES
|
|
1077
|
+
const FILE_CONSENT_THRESHOLD_BYTES = 4 * 1024 * 1024;
|
|
1037
1078
|
function normalizeConversationId(rawId) {
|
|
1038
1079
|
return rawId.split(";")[0] ?? rawId;
|
|
1039
1080
|
}
|
|
@@ -1068,15 +1109,15 @@ function buildConversationReference(ref) {
|
|
|
1068
1109
|
function pushTextMessages(out, text, opts) {
|
|
1069
1110
|
if (!text) return;
|
|
1070
1111
|
if (opts.chunkText) {
|
|
1071
|
-
for (const chunk of getMSTeamsRuntime().channel.text.chunkMarkdownTextWithMode(text, opts.chunkLimit, opts.chunkMode)) {
|
|
1112
|
+
for (const chunk of require_runtime.getMSTeamsRuntime().channel.text.chunkMarkdownTextWithMode(text, opts.chunkLimit, opts.chunkMode)) {
|
|
1072
1113
|
const trimmed = chunk.trim();
|
|
1073
|
-
if (!trimmed || isSilentReplyText(trimmed, SILENT_REPLY_TOKEN)) continue;
|
|
1114
|
+
if (!trimmed || (0, openclaw_plugin_sdk_reply_chunking.isSilentReplyText)(trimmed, openclaw_plugin_sdk_reply_chunking.SILENT_REPLY_TOKEN)) continue;
|
|
1074
1115
|
out.push({ text: trimmed });
|
|
1075
1116
|
}
|
|
1076
1117
|
return;
|
|
1077
1118
|
}
|
|
1078
1119
|
const trimmed = text.trim();
|
|
1079
|
-
if (!trimmed || isSilentReplyText(trimmed, SILENT_REPLY_TOKEN)) return;
|
|
1120
|
+
if (!trimmed || (0, openclaw_plugin_sdk_reply_chunking.isSilentReplyText)(trimmed, openclaw_plugin_sdk_reply_chunking.SILENT_REPLY_TOKEN)) return;
|
|
1080
1121
|
out.push({ text: trimmed });
|
|
1081
1122
|
}
|
|
1082
1123
|
function clampMs(value, maxMs) {
|
|
@@ -1110,12 +1151,12 @@ function renderReplyPayloadsToMessages(replies, options) {
|
|
|
1110
1151
|
const chunkText = options.chunkText !== false;
|
|
1111
1152
|
const chunkMode = options.chunkMode ?? "length";
|
|
1112
1153
|
const mediaMode = options.mediaMode ?? "split";
|
|
1113
|
-
const tableMode = options.tableMode ?? getMSTeamsRuntime().channel.text.resolveMarkdownTableMode({
|
|
1114
|
-
cfg: getMSTeamsRuntime().config.current(),
|
|
1154
|
+
const tableMode = options.tableMode ?? require_runtime.getMSTeamsRuntime().channel.text.resolveMarkdownTableMode({
|
|
1155
|
+
cfg: require_runtime.getMSTeamsRuntime().config.current(),
|
|
1115
1156
|
channel: "msteams"
|
|
1116
1157
|
});
|
|
1117
1158
|
for (const payload of replies) {
|
|
1118
|
-
const reply = resolveSendableOutboundReplyParts(payload, { text: getMSTeamsRuntime().channel.text.convertMarkdownTables(payload.text ?? "", tableMode) });
|
|
1159
|
+
const reply = (0, openclaw_plugin_sdk_reply_payload.resolveSendableOutboundReplyParts)(payload, { text: require_runtime.getMSTeamsRuntime().channel.text.convertMarkdownTables(payload.text ?? "", tableMode) });
|
|
1119
1160
|
if (!reply.hasContent) continue;
|
|
1120
1161
|
if (!reply.hasMedia) {
|
|
1121
1162
|
pushTextMessages(out, reply.text, {
|
|
@@ -1165,18 +1206,18 @@ async function buildActivity(msg, conversationRef, tokenProvider, sharePointSite
|
|
|
1165
1206
|
let contentType = await getMimeType(msg.mediaUrl);
|
|
1166
1207
|
let fileName = await extractFilename(msg.mediaUrl);
|
|
1167
1208
|
if (isLocalPath(msg.mediaUrl)) {
|
|
1168
|
-
const maxBytes = mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES
|
|
1169
|
-
const media = await loadWebMedia(msg.mediaUrl, maxBytes);
|
|
1209
|
+
const maxBytes = mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES;
|
|
1210
|
+
const media = await (0, openclaw_plugin_sdk_web_media.loadWebMedia)(msg.mediaUrl, maxBytes);
|
|
1170
1211
|
contentType = media.contentType ?? contentType;
|
|
1171
1212
|
fileName = media.fileName ?? fileName;
|
|
1172
|
-
const conversationType = normalizeOptionalLowercaseString(conversationRef.conversation?.conversationType);
|
|
1213
|
+
const conversationType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalLowercaseString)(conversationRef.conversation?.conversationType);
|
|
1173
1214
|
const isPersonal = conversationType === "personal";
|
|
1174
1215
|
const isImage = media.kind === "image";
|
|
1175
1216
|
if (requiresFileConsent({
|
|
1176
1217
|
conversationType,
|
|
1177
1218
|
contentType,
|
|
1178
1219
|
bufferSize: media.buffer.length,
|
|
1179
|
-
thresholdBytes: FILE_CONSENT_THRESHOLD_BYTES
|
|
1220
|
+
thresholdBytes: FILE_CONSENT_THRESHOLD_BYTES
|
|
1180
1221
|
})) {
|
|
1181
1222
|
const conversationId = conversationRef.conversation?.id ?? "unknown";
|
|
1182
1223
|
const { activity: consentActivity, uploadId } = prepareFileConsentActivity({
|
|
@@ -1191,16 +1232,18 @@ async function buildActivity(msg, conversationRef, tokenProvider, sharePointSite
|
|
|
1191
1232
|
consentActivity["_pendingUploadId"] = uploadId;
|
|
1192
1233
|
return consentActivity;
|
|
1193
1234
|
}
|
|
1194
|
-
if (!isPersonal && !isImage
|
|
1195
|
-
const
|
|
1235
|
+
if (!isPersonal && !isImage) {
|
|
1236
|
+
const siteId = requireMSTeamsSharePointSiteId(sharePointSiteId);
|
|
1237
|
+
if (!tokenProvider) throw new Error("MS Teams Graph token provider unavailable for SharePoint file send");
|
|
1238
|
+
const chatId = conversationRef.conversation?.id;
|
|
1196
1239
|
activity.attachments = [buildTeamsFileInfoCard(await getDriveItemProperties({
|
|
1197
|
-
siteId
|
|
1240
|
+
siteId,
|
|
1198
1241
|
itemId: (await uploadAndShareSharePoint({
|
|
1199
1242
|
buffer: media.buffer,
|
|
1200
1243
|
filename: fileName,
|
|
1201
1244
|
contentType,
|
|
1202
1245
|
tokenProvider,
|
|
1203
|
-
siteId
|
|
1246
|
+
siteId,
|
|
1204
1247
|
chatId: chatId ?? void 0,
|
|
1205
1248
|
usePerUserSharing: conversationType === "groupchat"
|
|
1206
1249
|
})).itemId,
|
|
@@ -1208,18 +1251,6 @@ async function buildActivity(msg, conversationRef, tokenProvider, sharePointSite
|
|
|
1208
1251
|
}))];
|
|
1209
1252
|
return activity;
|
|
1210
1253
|
}
|
|
1211
|
-
if (!isPersonal && media.kind !== "image" && tokenProvider) {
|
|
1212
|
-
const uploaded = await uploadAndShareOneDrive({
|
|
1213
|
-
buffer: media.buffer,
|
|
1214
|
-
filename: fileName,
|
|
1215
|
-
contentType,
|
|
1216
|
-
tokenProvider
|
|
1217
|
-
});
|
|
1218
|
-
const fileLink = `📎 [${uploaded.name}](${uploaded.shareUrl})`;
|
|
1219
|
-
const existingText = typeof activity.text === "string" ? activity.text : void 0;
|
|
1220
|
-
activity.text = existingText ? `${existingText}\n\n${fileLink}` : fileLink;
|
|
1221
|
-
return activity;
|
|
1222
|
-
}
|
|
1223
1254
|
const base64 = media.buffer.toString("base64");
|
|
1224
1255
|
contentUrl = `data:${media.contentType};base64,${base64}`;
|
|
1225
1256
|
}
|
|
@@ -1240,7 +1271,7 @@ async function sendMSTeamsMessages(params) {
|
|
|
1240
1271
|
for (const attempt of Array.from({ length: retryOptions.maxAttempts }, (_, index) => index + 1)) try {
|
|
1241
1272
|
return await sendOnce();
|
|
1242
1273
|
} catch (err) {
|
|
1243
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1274
|
+
const classification = require_setup_surface.classifyMSTeamsSendError(err);
|
|
1244
1275
|
if (!(attempt < retryOptions.maxAttempts && shouldRetry(classification))) throw err;
|
|
1245
1276
|
const delayMs = computeRetryDelayMs(attempt, classification, retryOptions);
|
|
1246
1277
|
const nextAttempt = attempt + 1;
|
|
@@ -1252,7 +1283,7 @@ async function sendMSTeamsMessages(params) {
|
|
|
1252
1283
|
delayMs,
|
|
1253
1284
|
classification
|
|
1254
1285
|
});
|
|
1255
|
-
await sleep(delayMs);
|
|
1286
|
+
await (0, openclaw_plugin_sdk_text_utility_runtime.sleep)(delayMs);
|
|
1256
1287
|
}
|
|
1257
1288
|
throw new Error("unreachable Teams send retry loop exit");
|
|
1258
1289
|
};
|
|
@@ -1312,675 +1343,189 @@ async function sendMSTeamsMessages(params) {
|
|
|
1312
1343
|
return await sendProactively(messages, 0);
|
|
1313
1344
|
}
|
|
1314
1345
|
//#endregion
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
const routeConfig = resolveMSTeamsRouteConfig({
|
|
1320
|
-
cfg: params.cfg,
|
|
1321
|
-
teamId: params.ref.teamId,
|
|
1322
|
-
conversationId: params.conversationId,
|
|
1323
|
-
allowNameMatching: false
|
|
1324
|
-
});
|
|
1325
|
-
const { replyStyle } = resolveMSTeamsReplyPolicy({
|
|
1326
|
-
isDirectMessage: false,
|
|
1327
|
-
globalConfig: params.cfg,
|
|
1328
|
-
teamConfig: routeConfig.teamConfig,
|
|
1329
|
-
channelConfig: routeConfig.channelConfig
|
|
1330
|
-
});
|
|
1331
|
-
return replyStyle;
|
|
1332
|
-
}
|
|
1333
|
-
/**
|
|
1334
|
-
* Parse the target value into a conversation reference lookup key.
|
|
1335
|
-
* Supported formats:
|
|
1336
|
-
* - conversation:19:abc@thread.tacv2 → lookup by conversation ID
|
|
1337
|
-
* - user:aad-object-id → lookup by user AAD object ID
|
|
1338
|
-
* - 19:abc@thread.tacv2 → direct conversation ID
|
|
1339
|
-
*/
|
|
1340
|
-
function parseRecipient(to) {
|
|
1341
|
-
const trimmed = to.trim();
|
|
1342
|
-
const finalize = (type, id) => {
|
|
1343
|
-
const normalized = id.trim();
|
|
1344
|
-
if (!normalized) throw new Error(`Invalid target value: missing ${type} id`);
|
|
1345
|
-
return {
|
|
1346
|
-
type,
|
|
1347
|
-
id: normalized
|
|
1348
|
-
};
|
|
1349
|
-
};
|
|
1350
|
-
if (trimmed.startsWith("conversation:")) return finalize("conversation", trimmed.slice(13));
|
|
1351
|
-
if (trimmed.startsWith("user:")) return finalize("user", trimmed.slice(5));
|
|
1352
|
-
if (trimmed.startsWith("19:") || trimmed.includes("@thread")) return finalize("conversation", trimmed);
|
|
1353
|
-
return finalize("user", trimmed);
|
|
1354
|
-
}
|
|
1355
|
-
/**
|
|
1356
|
-
* Find a stored conversation reference for the given recipient.
|
|
1357
|
-
*/
|
|
1358
|
-
async function findConversationReference(recipient) {
|
|
1359
|
-
if (recipient.type === "conversation") {
|
|
1360
|
-
const ref = await recipient.store.get(recipient.id);
|
|
1361
|
-
if (ref) return {
|
|
1362
|
-
conversationId: recipient.id,
|
|
1363
|
-
ref
|
|
1364
|
-
};
|
|
1365
|
-
return null;
|
|
1346
|
+
Object.defineProperty(exports, "buildConversationReference", {
|
|
1347
|
+
enumerable: true,
|
|
1348
|
+
get: function() {
|
|
1349
|
+
return buildConversationReference;
|
|
1366
1350
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
};
|
|
1373
|
-
}
|
|
1374
|
-
async function resolveMSTeamsSendContext(params) {
|
|
1375
|
-
const msteamsCfg = params.cfg.channels?.msteams;
|
|
1376
|
-
if (!msteamsCfg?.enabled) throw new Error("msteams provider is not enabled");
|
|
1377
|
-
const creds = resolveMSTeamsCredentials(msteamsCfg);
|
|
1378
|
-
if (!creds) throw new Error("msteams credentials not configured");
|
|
1379
|
-
const store = createMSTeamsConversationStoreState();
|
|
1380
|
-
const recipient = parseRecipient(params.to);
|
|
1381
|
-
const found = await findConversationReference({
|
|
1382
|
-
...recipient,
|
|
1383
|
-
store
|
|
1384
|
-
});
|
|
1385
|
-
if (!found) throw new Error(`No conversation reference found for ${recipient.type}:${recipient.id}. The bot must receive a message from this conversation before it can send proactively.`);
|
|
1386
|
-
const { conversationId, ref } = found;
|
|
1387
|
-
const log = getMSTeamsRuntime().logging.getChildLogger({ name: "msteams:send" });
|
|
1388
|
-
if (ref.serviceUrl && !isAllowedBotFrameworkServiceUrl(ref.serviceUrl)) {
|
|
1389
|
-
try {
|
|
1390
|
-
await store.remove(conversationId);
|
|
1391
|
-
} catch (err) {
|
|
1392
|
-
log.warn?.("failed to remove blocked msteams conversation reference", {
|
|
1393
|
-
conversationId,
|
|
1394
|
-
error: formatUnknownError(err)
|
|
1395
|
-
});
|
|
1396
|
-
}
|
|
1397
|
-
throw new Error(`Stored Microsoft Teams conversation reference has blocked serviceUrl host: ${describeBotFrameworkServiceUrlHost(ref.serviceUrl)}. The bot must receive a new message from this conversation before it can send proactively.`);
|
|
1351
|
+
});
|
|
1352
|
+
Object.defineProperty(exports, "buildFileInfoCard", {
|
|
1353
|
+
enumerable: true,
|
|
1354
|
+
get: function() {
|
|
1355
|
+
return buildFileInfoCard;
|
|
1398
1356
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
const resolvedType = normalizeLowercaseStringOrEmpty(safeRef.conversation?.conversationType ?? "");
|
|
1405
|
-
if (resolvedType && resolvedType !== "personal") throw new Error(`Conversation reference for user:${recipient.id} resolved to a ${resolvedType} conversation (${conversationId}) instead of a personal DM. The bot must receive a DM from this user before it can send proactively.`);
|
|
1357
|
+
});
|
|
1358
|
+
Object.defineProperty(exports, "buildTeamsFileInfoCard", {
|
|
1359
|
+
enumerable: true,
|
|
1360
|
+
get: function() {
|
|
1361
|
+
return buildTeamsFileInfoCard;
|
|
1406
1362
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
storedServiceUrl: safeRef.serviceUrl,
|
|
1413
|
-
configuredServiceUrl: sdkCloudOptions.serviceUrl
|
|
1414
|
-
});
|
|
1415
|
-
const tokenProvider = createMSTeamsTokenProvider(app);
|
|
1416
|
-
const storedConversationType = normalizeLowercaseStringOrEmpty(safeRef.conversation?.conversationType ?? "");
|
|
1417
|
-
let conversationType;
|
|
1418
|
-
if (storedConversationType === "personal") conversationType = "personal";
|
|
1419
|
-
else if (storedConversationType === "channel") conversationType = "channel";
|
|
1420
|
-
else conversationType = "groupChat";
|
|
1421
|
-
const replyStyle = resolveMSTeamsProactiveReplyStyle({
|
|
1422
|
-
cfg: msteamsCfg,
|
|
1423
|
-
conversationId,
|
|
1424
|
-
ref: safeRef,
|
|
1425
|
-
conversationType
|
|
1426
|
-
});
|
|
1427
|
-
const sharePointSiteId = msteamsCfg.sharePointSiteId;
|
|
1428
|
-
const mediaMaxBytes = resolveChannelMediaMaxBytes({
|
|
1429
|
-
cfg: params.cfg,
|
|
1430
|
-
resolveChannelLimitMb: ({ cfg }) => cfg.channels?.msteams?.mediaMaxMb
|
|
1431
|
-
});
|
|
1432
|
-
let graphChatId = safeRef.graphChatId ?? void 0;
|
|
1433
|
-
if (graphChatId === void 0 && sharePointSiteId) try {
|
|
1434
|
-
const resolved = await resolveGraphChatId({
|
|
1435
|
-
botFrameworkConversationId: conversationId,
|
|
1436
|
-
userAadObjectId: safeRef.user?.aadObjectId,
|
|
1437
|
-
tokenProvider
|
|
1438
|
-
});
|
|
1439
|
-
graphChatId = resolved;
|
|
1440
|
-
if (resolved) await store.upsert(conversationId, {
|
|
1441
|
-
...safeRef,
|
|
1442
|
-
graphChatId: resolved
|
|
1443
|
-
});
|
|
1444
|
-
else log.warn?.("could not resolve Graph chat ID; file uploads may fail for this conversation", { conversationId });
|
|
1445
|
-
} catch (err) {
|
|
1446
|
-
log.warn?.("failed to resolve Graph chat ID; file uploads may fall back to Bot Framework ID", {
|
|
1447
|
-
conversationId,
|
|
1448
|
-
error: formatUnknownError(err)
|
|
1449
|
-
});
|
|
1450
|
-
graphChatId = null;
|
|
1363
|
+
});
|
|
1364
|
+
Object.defineProperty(exports, "deleteMSTeamsActivityWithReference", {
|
|
1365
|
+
enumerable: true,
|
|
1366
|
+
get: function() {
|
|
1367
|
+
return deleteMSTeamsActivityWithReference;
|
|
1451
1368
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
log,
|
|
1458
|
-
conversationType,
|
|
1459
|
-
replyStyle,
|
|
1460
|
-
sdkCloudOptions,
|
|
1461
|
-
tokenProvider,
|
|
1462
|
-
sharePointSiteId,
|
|
1463
|
-
mediaMaxBytes,
|
|
1464
|
-
graphChatId
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
//#endregion
|
|
1468
|
-
//#region extensions/msteams/src/send.ts
|
|
1469
|
-
/** Threshold for large files that require FileConsentCard flow in personal chats */
|
|
1470
|
-
const FILE_CONSENT_THRESHOLD_BYTES = 4 * 1024 * 1024;
|
|
1471
|
-
/**
|
|
1472
|
-
* MSTeams-specific media size limit (100MB).
|
|
1473
|
-
* Higher than the default because OneDrive upload handles large files well.
|
|
1474
|
-
*/
|
|
1475
|
-
const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
1476
|
-
function createMSTeamsSendReceipt(params) {
|
|
1477
|
-
return createMessageReceiptFromOutboundResults({
|
|
1478
|
-
kind: params.kind,
|
|
1479
|
-
results: params.platformMessageIds.map((messageId) => ({
|
|
1480
|
-
channel: "msteams",
|
|
1481
|
-
messageId,
|
|
1482
|
-
conversationId: params.conversationId
|
|
1483
|
-
}))
|
|
1484
|
-
});
|
|
1485
|
-
}
|
|
1486
|
-
function createMSTeamsSendResult(params) {
|
|
1487
|
-
const platformMessageIds = (params.platformMessageIds?.length ? [...params.platformMessageIds] : [params.messageId]).map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown");
|
|
1488
|
-
return {
|
|
1489
|
-
messageId: params.messageId,
|
|
1490
|
-
conversationId: params.conversationId,
|
|
1491
|
-
receipt: createMSTeamsSendReceipt({
|
|
1492
|
-
conversationId: params.conversationId,
|
|
1493
|
-
platformMessageIds,
|
|
1494
|
-
kind: params.kind
|
|
1495
|
-
}),
|
|
1496
|
-
...params.pendingUploadId ? { pendingUploadId: params.pendingUploadId } : {}
|
|
1497
|
-
};
|
|
1498
|
-
}
|
|
1499
|
-
/**
|
|
1500
|
-
* Send a message to a Teams conversation or user.
|
|
1501
|
-
*
|
|
1502
|
-
* Uses the stored ConversationReference from previous interactions.
|
|
1503
|
-
* The bot must have received at least one message from the conversation
|
|
1504
|
-
* before proactive messaging works.
|
|
1505
|
-
*
|
|
1506
|
-
* File handling by conversation type:
|
|
1507
|
-
* - Personal (1:1) chats: small images (<4MB) use base64, large files and non-images use FileConsentCard
|
|
1508
|
-
* - Group chats / channels: files are uploaded to OneDrive and shared via link
|
|
1509
|
-
*/
|
|
1510
|
-
async function sendMessageMSTeams(params) {
|
|
1511
|
-
const { cfg, to, text, mediaUrl, filename, mediaLocalRoots, mediaReadFile } = params;
|
|
1512
|
-
const tableMode = resolveMarkdownTableMode({
|
|
1513
|
-
cfg,
|
|
1514
|
-
channel: "msteams"
|
|
1515
|
-
});
|
|
1516
|
-
const messageText = convertMarkdownTables(text ?? "", tableMode);
|
|
1517
|
-
const ctx = await resolveMSTeamsSendContext({
|
|
1518
|
-
cfg,
|
|
1519
|
-
to
|
|
1520
|
-
});
|
|
1521
|
-
const { app, conversationId, ref, log, conversationType, tokenProvider, sharePointSiteId, sdkCloudOptions } = ctx;
|
|
1522
|
-
log.debug?.("sending proactive message", {
|
|
1523
|
-
conversationId,
|
|
1524
|
-
conversationType,
|
|
1525
|
-
textLength: messageText.length,
|
|
1526
|
-
hasMedia: Boolean(mediaUrl)
|
|
1527
|
-
});
|
|
1528
|
-
if (mediaUrl) {
|
|
1529
|
-
const media = await loadOutboundMediaFromUrl(mediaUrl, {
|
|
1530
|
-
maxBytes: ctx.mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES,
|
|
1531
|
-
mediaLocalRoots,
|
|
1532
|
-
mediaReadFile
|
|
1533
|
-
});
|
|
1534
|
-
const isLargeFile = media.buffer.length >= FILE_CONSENT_THRESHOLD_BYTES;
|
|
1535
|
-
const isImage = media.contentType?.startsWith("image/") ?? false;
|
|
1536
|
-
const fallbackFileName = await extractFilename(mediaUrl);
|
|
1537
|
-
const fileName = filename?.trim() || media.fileName || fallbackFileName;
|
|
1538
|
-
log.debug?.("processing media", {
|
|
1539
|
-
fileName,
|
|
1540
|
-
contentType: media.contentType,
|
|
1541
|
-
size: media.buffer.length,
|
|
1542
|
-
isLargeFile,
|
|
1543
|
-
isImage,
|
|
1544
|
-
conversationType
|
|
1545
|
-
});
|
|
1546
|
-
if (requiresFileConsent({
|
|
1547
|
-
conversationType,
|
|
1548
|
-
contentType: media.contentType,
|
|
1549
|
-
bufferSize: media.buffer.length,
|
|
1550
|
-
thresholdBytes: FILE_CONSENT_THRESHOLD_BYTES
|
|
1551
|
-
})) {
|
|
1552
|
-
const { activity, uploadId } = await prepareFileConsentActivityFs({
|
|
1553
|
-
media: {
|
|
1554
|
-
buffer: media.buffer,
|
|
1555
|
-
filename: fileName,
|
|
1556
|
-
contentType: media.contentType
|
|
1557
|
-
},
|
|
1558
|
-
conversationId,
|
|
1559
|
-
description: messageText || void 0
|
|
1560
|
-
});
|
|
1561
|
-
log.debug?.("sending file consent card", {
|
|
1562
|
-
uploadId,
|
|
1563
|
-
fileName,
|
|
1564
|
-
size: media.buffer.length
|
|
1565
|
-
});
|
|
1566
|
-
const messageId = await sendProactiveActivity({
|
|
1567
|
-
app,
|
|
1568
|
-
ref,
|
|
1569
|
-
activity,
|
|
1570
|
-
errorPrefix: "msteams consent card send",
|
|
1571
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1572
|
-
});
|
|
1573
|
-
setPendingUploadActivityId(uploadId, messageId);
|
|
1574
|
-
await setPendingUploadActivityIdFs(uploadId, messageId);
|
|
1575
|
-
log.info("sent file consent card", {
|
|
1576
|
-
conversationId,
|
|
1577
|
-
messageId,
|
|
1578
|
-
uploadId
|
|
1579
|
-
});
|
|
1580
|
-
return createMSTeamsSendResult({
|
|
1581
|
-
messageId,
|
|
1582
|
-
conversationId,
|
|
1583
|
-
kind: "card",
|
|
1584
|
-
pendingUploadId: uploadId
|
|
1585
|
-
});
|
|
1586
|
-
}
|
|
1587
|
-
if (conversationType === "personal") {
|
|
1588
|
-
const base64 = media.buffer.toString("base64");
|
|
1589
|
-
return sendTextWithMedia(ctx, messageText, `data:${media.contentType};base64,${base64}`);
|
|
1590
|
-
}
|
|
1591
|
-
if (isImage && !sharePointSiteId) {
|
|
1592
|
-
const base64 = media.buffer.toString("base64");
|
|
1593
|
-
return sendTextWithMedia(ctx, messageText, `data:${media.contentType};base64,${base64}`);
|
|
1594
|
-
}
|
|
1595
|
-
try {
|
|
1596
|
-
if (sharePointSiteId) {
|
|
1597
|
-
log.debug?.("uploading to SharePoint for native file card", {
|
|
1598
|
-
fileName,
|
|
1599
|
-
conversationType,
|
|
1600
|
-
siteId: sharePointSiteId
|
|
1601
|
-
});
|
|
1602
|
-
const uploaded = await uploadAndShareSharePoint({
|
|
1603
|
-
buffer: media.buffer,
|
|
1604
|
-
filename: fileName,
|
|
1605
|
-
contentType: media.contentType,
|
|
1606
|
-
tokenProvider,
|
|
1607
|
-
siteId: sharePointSiteId,
|
|
1608
|
-
chatId: ctx.graphChatId ?? conversationId,
|
|
1609
|
-
usePerUserSharing: conversationType === "groupChat"
|
|
1610
|
-
});
|
|
1611
|
-
log.debug?.("SharePoint upload complete", {
|
|
1612
|
-
itemId: uploaded.itemId,
|
|
1613
|
-
shareUrl: uploaded.shareUrl
|
|
1614
|
-
});
|
|
1615
|
-
const driveItem = await getDriveItemProperties({
|
|
1616
|
-
siteId: sharePointSiteId,
|
|
1617
|
-
itemId: uploaded.itemId,
|
|
1618
|
-
tokenProvider
|
|
1619
|
-
});
|
|
1620
|
-
log.debug?.("driveItem properties retrieved", {
|
|
1621
|
-
eTag: driveItem.eTag,
|
|
1622
|
-
webDavUrl: driveItem.webDavUrl
|
|
1623
|
-
});
|
|
1624
|
-
const fileCardAttachment = buildTeamsFileInfoCard(driveItem);
|
|
1625
|
-
const messageId = await sendProactiveActivityRaw({
|
|
1626
|
-
app,
|
|
1627
|
-
ref,
|
|
1628
|
-
activity: {
|
|
1629
|
-
type: "message",
|
|
1630
|
-
text: messageText || void 0,
|
|
1631
|
-
attachments: [fileCardAttachment]
|
|
1632
|
-
},
|
|
1633
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1634
|
-
});
|
|
1635
|
-
log.info("sent native file card", {
|
|
1636
|
-
conversationId,
|
|
1637
|
-
messageId,
|
|
1638
|
-
fileName: driveItem.name
|
|
1639
|
-
});
|
|
1640
|
-
return createMSTeamsSendResult({
|
|
1641
|
-
messageId,
|
|
1642
|
-
conversationId,
|
|
1643
|
-
kind: "media"
|
|
1644
|
-
});
|
|
1645
|
-
}
|
|
1646
|
-
log.debug?.("uploading to OneDrive (no SharePoint site configured)", {
|
|
1647
|
-
fileName,
|
|
1648
|
-
conversationType
|
|
1649
|
-
});
|
|
1650
|
-
const uploaded = await uploadAndShareOneDrive({
|
|
1651
|
-
buffer: media.buffer,
|
|
1652
|
-
filename: fileName,
|
|
1653
|
-
contentType: media.contentType,
|
|
1654
|
-
tokenProvider
|
|
1655
|
-
});
|
|
1656
|
-
log.debug?.("OneDrive upload complete", {
|
|
1657
|
-
itemId: uploaded.itemId,
|
|
1658
|
-
shareUrl: uploaded.shareUrl
|
|
1659
|
-
});
|
|
1660
|
-
const fileLink = `📎 [${uploaded.name}](${uploaded.shareUrl})`;
|
|
1661
|
-
const messageId = await sendProactiveActivityRaw({
|
|
1662
|
-
app,
|
|
1663
|
-
ref,
|
|
1664
|
-
activity: {
|
|
1665
|
-
type: "message",
|
|
1666
|
-
text: messageText ? `${messageText}\n\n${fileLink}` : fileLink
|
|
1667
|
-
},
|
|
1668
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1669
|
-
});
|
|
1670
|
-
log.info("sent message with OneDrive file link", {
|
|
1671
|
-
conversationId,
|
|
1672
|
-
messageId,
|
|
1673
|
-
shareUrl: uploaded.shareUrl
|
|
1674
|
-
});
|
|
1675
|
-
return createMSTeamsSendResult({
|
|
1676
|
-
messageId,
|
|
1677
|
-
conversationId,
|
|
1678
|
-
kind: "media"
|
|
1679
|
-
});
|
|
1680
|
-
} catch (err) {
|
|
1681
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1682
|
-
const hint = formatMSTeamsSendErrorHint(classification);
|
|
1683
|
-
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1684
|
-
throw new Error(`msteams file send failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1685
|
-
}
|
|
1369
|
+
});
|
|
1370
|
+
Object.defineProperty(exports, "extractFilename", {
|
|
1371
|
+
enumerable: true,
|
|
1372
|
+
get: function() {
|
|
1373
|
+
return extractFilename;
|
|
1686
1374
|
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
1693
|
-
const { app, appId, conversationId, ref, log, tokenProvider, sharePointSiteId, mediaMaxBytes, replyStyle } = ctx;
|
|
1694
|
-
let platformMessageIds;
|
|
1695
|
-
try {
|
|
1696
|
-
platformMessageIds = await sendMSTeamsMessages({
|
|
1697
|
-
replyStyle,
|
|
1698
|
-
app,
|
|
1699
|
-
appId,
|
|
1700
|
-
conversationRef: ref,
|
|
1701
|
-
messages: [{
|
|
1702
|
-
text: text || void 0,
|
|
1703
|
-
mediaUrl
|
|
1704
|
-
}],
|
|
1705
|
-
retry: {},
|
|
1706
|
-
onRetry: (event) => {
|
|
1707
|
-
log.debug?.("retrying send", {
|
|
1708
|
-
conversationId,
|
|
1709
|
-
...event
|
|
1710
|
-
});
|
|
1711
|
-
},
|
|
1712
|
-
tokenProvider,
|
|
1713
|
-
sharePointSiteId,
|
|
1714
|
-
mediaMaxBytes,
|
|
1715
|
-
serviceUrlBoundary: ctx.sdkCloudOptions
|
|
1716
|
-
});
|
|
1717
|
-
} catch (err) {
|
|
1718
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1719
|
-
const hint = formatMSTeamsSendErrorHint(classification);
|
|
1720
|
-
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1721
|
-
throw new Error(`msteams send failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1375
|
+
});
|
|
1376
|
+
Object.defineProperty(exports, "extractMessageId", {
|
|
1377
|
+
enumerable: true,
|
|
1378
|
+
get: function() {
|
|
1379
|
+
return extractMessageId;
|
|
1722
1380
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
return {
|
|
1729
|
-
messageId,
|
|
1730
|
-
conversationId,
|
|
1731
|
-
receipt: createMSTeamsSendReceipt({
|
|
1732
|
-
conversationId,
|
|
1733
|
-
platformMessageIds,
|
|
1734
|
-
kind: mediaUrl ? "media" : "text"
|
|
1735
|
-
})
|
|
1736
|
-
};
|
|
1737
|
-
}
|
|
1738
|
-
async function sendProactiveActivityRaw({ app, ref, activity, serviceUrlBoundary }) {
|
|
1739
|
-
return extractMessageId(await sendMSTeamsActivityWithReference(app, buildConversationReference(ref), activity, { serviceUrlBoundary })) ?? "unknown";
|
|
1740
|
-
}
|
|
1741
|
-
async function sendProactiveActivity({ app, ref, activity, errorPrefix, serviceUrlBoundary }) {
|
|
1742
|
-
try {
|
|
1743
|
-
return await sendProactiveActivityRaw({
|
|
1744
|
-
app,
|
|
1745
|
-
ref,
|
|
1746
|
-
activity,
|
|
1747
|
-
serviceUrlBoundary
|
|
1748
|
-
});
|
|
1749
|
-
} catch (err) {
|
|
1750
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1751
|
-
const hint = formatMSTeamsSendErrorHint(classification);
|
|
1752
|
-
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1753
|
-
throw new Error(`${errorPrefix} failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1381
|
+
});
|
|
1382
|
+
Object.defineProperty(exports, "fetchChannelMessage", {
|
|
1383
|
+
enumerable: true,
|
|
1384
|
+
get: function() {
|
|
1385
|
+
return fetchChannelMessage;
|
|
1754
1386
|
}
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
const { cfg, to, question, options, maxSelections } = params;
|
|
1761
|
-
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
1762
|
-
cfg,
|
|
1763
|
-
to
|
|
1764
|
-
});
|
|
1765
|
-
const pollCard = buildMSTeamsPollCard({
|
|
1766
|
-
question,
|
|
1767
|
-
options,
|
|
1768
|
-
maxSelections
|
|
1769
|
-
});
|
|
1770
|
-
log.debug?.("sending poll", {
|
|
1771
|
-
conversationId,
|
|
1772
|
-
pollId: pollCard.pollId,
|
|
1773
|
-
optionCount: pollCard.options.length
|
|
1774
|
-
});
|
|
1775
|
-
const messageId = await sendProactiveActivity({
|
|
1776
|
-
app,
|
|
1777
|
-
ref,
|
|
1778
|
-
activity: {
|
|
1779
|
-
type: "message",
|
|
1780
|
-
attachments: [{
|
|
1781
|
-
contentType: "application/vnd.microsoft.card.adaptive",
|
|
1782
|
-
content: pollCard.card
|
|
1783
|
-
}]
|
|
1784
|
-
},
|
|
1785
|
-
errorPrefix: "msteams poll send",
|
|
1786
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1787
|
-
});
|
|
1788
|
-
log.info("sent poll", {
|
|
1789
|
-
conversationId,
|
|
1790
|
-
pollId: pollCard.pollId,
|
|
1791
|
-
messageId
|
|
1792
|
-
});
|
|
1793
|
-
return {
|
|
1794
|
-
pollId: pollCard.pollId,
|
|
1795
|
-
messageId,
|
|
1796
|
-
conversationId
|
|
1797
|
-
};
|
|
1798
|
-
}
|
|
1799
|
-
/**
|
|
1800
|
-
* Send an arbitrary Adaptive Card to a Teams conversation or user.
|
|
1801
|
-
*/
|
|
1802
|
-
async function sendAdaptiveCardMSTeams(params) {
|
|
1803
|
-
const { cfg, to, card } = params;
|
|
1804
|
-
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
1805
|
-
cfg,
|
|
1806
|
-
to
|
|
1807
|
-
});
|
|
1808
|
-
log.debug?.("sending adaptive card", {
|
|
1809
|
-
conversationId,
|
|
1810
|
-
cardType: card.type,
|
|
1811
|
-
cardVersion: card.version
|
|
1812
|
-
});
|
|
1813
|
-
const messageId = await sendProactiveActivity({
|
|
1814
|
-
app,
|
|
1815
|
-
ref,
|
|
1816
|
-
activity: {
|
|
1817
|
-
type: "message",
|
|
1818
|
-
attachments: [{
|
|
1819
|
-
contentType: "application/vnd.microsoft.card.adaptive",
|
|
1820
|
-
content: card
|
|
1821
|
-
}]
|
|
1822
|
-
},
|
|
1823
|
-
errorPrefix: "msteams card send",
|
|
1824
|
-
serviceUrlBoundary: sdkCloudOptions
|
|
1825
|
-
});
|
|
1826
|
-
log.info("sent adaptive card", {
|
|
1827
|
-
conversationId,
|
|
1828
|
-
messageId
|
|
1829
|
-
});
|
|
1830
|
-
return {
|
|
1831
|
-
messageId,
|
|
1832
|
-
conversationId
|
|
1833
|
-
};
|
|
1834
|
-
}
|
|
1835
|
-
/**
|
|
1836
|
-
* Edit (update) a previously sent message in a Teams conversation.
|
|
1837
|
-
*
|
|
1838
|
-
* Uses the Bot Framework REST API for proactive edits outside of the
|
|
1839
|
-
* original turn context.
|
|
1840
|
-
*/
|
|
1841
|
-
async function editMessageMSTeams(params) {
|
|
1842
|
-
const { cfg, to, activityId, text } = params;
|
|
1843
|
-
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
1844
|
-
cfg,
|
|
1845
|
-
to
|
|
1846
|
-
});
|
|
1847
|
-
log.debug?.("editing proactive message", {
|
|
1848
|
-
conversationId,
|
|
1849
|
-
activityId,
|
|
1850
|
-
textLength: text.length
|
|
1851
|
-
});
|
|
1852
|
-
try {
|
|
1853
|
-
await updateMSTeamsActivityWithReference(app, buildConversationReference(ref), activityId, {
|
|
1854
|
-
type: "message",
|
|
1855
|
-
id: activityId,
|
|
1856
|
-
text
|
|
1857
|
-
}, { serviceUrlBoundary: sdkCloudOptions });
|
|
1858
|
-
} catch (err) {
|
|
1859
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1860
|
-
const hint = formatMSTeamsSendErrorHint(classification);
|
|
1861
|
-
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1862
|
-
throw new Error(`msteams edit failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1387
|
+
});
|
|
1388
|
+
Object.defineProperty(exports, "fetchChatMessageText", {
|
|
1389
|
+
enumerable: true,
|
|
1390
|
+
get: function() {
|
|
1391
|
+
return fetchChatMessageText;
|
|
1863
1392
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
}
|
|
1870
|
-
/**
|
|
1871
|
-
* Delete a previously sent message in a Teams conversation.
|
|
1872
|
-
*
|
|
1873
|
-
* Uses the Bot Framework REST API for proactive deletes outside of the
|
|
1874
|
-
* original turn context.
|
|
1875
|
-
*/
|
|
1876
|
-
async function deleteMessageMSTeams(params) {
|
|
1877
|
-
const { cfg, to, activityId } = params;
|
|
1878
|
-
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
1879
|
-
cfg,
|
|
1880
|
-
to
|
|
1881
|
-
});
|
|
1882
|
-
log.debug?.("deleting proactive message", {
|
|
1883
|
-
conversationId,
|
|
1884
|
-
activityId
|
|
1885
|
-
});
|
|
1886
|
-
try {
|
|
1887
|
-
await deleteMSTeamsActivityWithReference(app, buildConversationReference(ref), activityId, { serviceUrlBoundary: sdkCloudOptions });
|
|
1888
|
-
} catch (err) {
|
|
1889
|
-
const classification = classifyMSTeamsSendError(err);
|
|
1890
|
-
const hint = formatMSTeamsSendErrorHint(classification);
|
|
1891
|
-
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
1892
|
-
throw new Error(`msteams delete failed${status}: ${formatUnknownError(err)}${hint ? ` (${hint})` : ""}`, { cause: err });
|
|
1393
|
+
});
|
|
1394
|
+
Object.defineProperty(exports, "fetchThreadReplies", {
|
|
1395
|
+
enumerable: true,
|
|
1396
|
+
get: function() {
|
|
1397
|
+
return fetchThreadReplies;
|
|
1893
1398
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
}
|
|
1900
|
-
//#endregion
|
|
1901
|
-
//#region extensions/msteams/src/probe.ts
|
|
1902
|
-
function decodeJwtPayload(token) {
|
|
1903
|
-
const parts = token.split(".");
|
|
1904
|
-
if (parts.length < 2) return null;
|
|
1905
|
-
const payload = parts[1] ?? "";
|
|
1906
|
-
const normalized = payload.padEnd(payload.length + (4 - payload.length % 4) % 4, "=").replace(/-/g, "+").replace(/_/g, "/");
|
|
1907
|
-
try {
|
|
1908
|
-
const decoded = Buffer.from(normalized, "base64").toString("utf8");
|
|
1909
|
-
const parsed = JSON.parse(decoded);
|
|
1910
|
-
return parsed && typeof parsed === "object" ? parsed : null;
|
|
1911
|
-
} catch {
|
|
1912
|
-
return null;
|
|
1399
|
+
});
|
|
1400
|
+
Object.defineProperty(exports, "formatThreadContext", {
|
|
1401
|
+
enumerable: true,
|
|
1402
|
+
get: function() {
|
|
1403
|
+
return formatThreadContext;
|
|
1913
1404
|
}
|
|
1914
|
-
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
}
|
|
1920
|
-
function readScopes(value) {
|
|
1921
|
-
if (typeof value !== "string") return;
|
|
1922
|
-
const out = normalizeStringEntries$1(value.split(/\s+/));
|
|
1923
|
-
return out.length > 0 ? out : void 0;
|
|
1924
|
-
}
|
|
1925
|
-
async function probeMSTeams(cfg) {
|
|
1926
|
-
const creds = resolveMSTeamsCredentials(cfg);
|
|
1927
|
-
if (!creds) return {
|
|
1928
|
-
ok: false,
|
|
1929
|
-
error: "missing credentials (appId, appPassword, tenantId)"
|
|
1930
|
-
};
|
|
1931
|
-
try {
|
|
1932
|
-
const { app } = await loadMSTeamsSdkWithAuth(creds, resolveMSTeamsSdkCloudOptions(cfg));
|
|
1933
|
-
const tokenProvider = createMSTeamsTokenProvider(app);
|
|
1934
|
-
if (!await tokenProvider.getAccessToken("https://api.botframework.com")) throw new Error("Failed to acquire bot token");
|
|
1935
|
-
let graph;
|
|
1936
|
-
try {
|
|
1937
|
-
const accessToken = readAccessToken(await tokenProvider.getAccessToken("https://graph.microsoft.com"));
|
|
1938
|
-
const payload = accessToken ? decodeJwtPayload(accessToken) : null;
|
|
1939
|
-
graph = {
|
|
1940
|
-
ok: true,
|
|
1941
|
-
roles: readStringArray(payload?.roles),
|
|
1942
|
-
scopes: readScopes(payload?.scp)
|
|
1943
|
-
};
|
|
1944
|
-
} catch (err) {
|
|
1945
|
-
graph = {
|
|
1946
|
-
ok: false,
|
|
1947
|
-
error: formatUnknownError(err)
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
let delegatedAuth;
|
|
1951
|
-
if (cfg?.delegatedAuth?.enabled) try {
|
|
1952
|
-
const tokens = loadDelegatedTokens();
|
|
1953
|
-
if (tokens) {
|
|
1954
|
-
const isExpired = !isFutureDateTimestampMs(tokens.expiresAt);
|
|
1955
|
-
delegatedAuth = {
|
|
1956
|
-
ok: !isExpired,
|
|
1957
|
-
scopes: tokens.scopes,
|
|
1958
|
-
userPrincipalName: tokens.userPrincipalName,
|
|
1959
|
-
...isExpired ? { error: "token expired (will auto-refresh on next use)" } : {}
|
|
1960
|
-
};
|
|
1961
|
-
} else delegatedAuth = {
|
|
1962
|
-
ok: false,
|
|
1963
|
-
error: "no delegated tokens found (run setup wizard)"
|
|
1964
|
-
};
|
|
1965
|
-
} catch {
|
|
1966
|
-
delegatedAuth = {
|
|
1967
|
-
ok: false,
|
|
1968
|
-
error: "failed to load delegated tokens"
|
|
1969
|
-
};
|
|
1970
|
-
}
|
|
1971
|
-
return {
|
|
1972
|
-
ok: true,
|
|
1973
|
-
appId: creds.appId,
|
|
1974
|
-
...graph ? { graph } : {},
|
|
1975
|
-
...delegatedAuth ? { delegatedAuth } : {}
|
|
1976
|
-
};
|
|
1977
|
-
} catch (err) {
|
|
1978
|
-
return {
|
|
1979
|
-
ok: false,
|
|
1980
|
-
appId: creds.appId,
|
|
1981
|
-
error: formatUnknownError(err)
|
|
1982
|
-
};
|
|
1405
|
+
});
|
|
1406
|
+
Object.defineProperty(exports, "getDriveItemProperties", {
|
|
1407
|
+
enumerable: true,
|
|
1408
|
+
get: function() {
|
|
1409
|
+
return getDriveItemProperties;
|
|
1983
1410
|
}
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1411
|
+
});
|
|
1412
|
+
Object.defineProperty(exports, "getMSTeamsReactionEmoji", {
|
|
1413
|
+
enumerable: true,
|
|
1414
|
+
get: function() {
|
|
1415
|
+
return getMSTeamsReactionEmoji;
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
Object.defineProperty(exports, "getPendingUpload", {
|
|
1419
|
+
enumerable: true,
|
|
1420
|
+
get: function() {
|
|
1421
|
+
return getPendingUpload;
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
Object.defineProperty(exports, "getPendingUploadFs", {
|
|
1425
|
+
enumerable: true,
|
|
1426
|
+
get: function() {
|
|
1427
|
+
return getPendingUploadFs;
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
Object.defineProperty(exports, "parseFileConsentInvoke", {
|
|
1431
|
+
enumerable: true,
|
|
1432
|
+
get: function() {
|
|
1433
|
+
return parseFileConsentInvoke;
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
Object.defineProperty(exports, "prepareFileConsentActivityFs", {
|
|
1437
|
+
enumerable: true,
|
|
1438
|
+
get: function() {
|
|
1439
|
+
return prepareFileConsentActivityFs;
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
Object.defineProperty(exports, "removePendingUpload", {
|
|
1443
|
+
enumerable: true,
|
|
1444
|
+
get: function() {
|
|
1445
|
+
return removePendingUpload;
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
Object.defineProperty(exports, "removePendingUploadFs", {
|
|
1449
|
+
enumerable: true,
|
|
1450
|
+
get: function() {
|
|
1451
|
+
return removePendingUploadFs;
|
|
1452
|
+
}
|
|
1453
|
+
});
|
|
1454
|
+
Object.defineProperty(exports, "renderReplyPayloadsToMessages", {
|
|
1455
|
+
enumerable: true,
|
|
1456
|
+
get: function() {
|
|
1457
|
+
return renderReplyPayloadsToMessages;
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
Object.defineProperty(exports, "requireMSTeamsSharePointSiteId", {
|
|
1461
|
+
enumerable: true,
|
|
1462
|
+
get: function() {
|
|
1463
|
+
return requireMSTeamsSharePointSiteId;
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
1466
|
+
Object.defineProperty(exports, "requiresFileConsent", {
|
|
1467
|
+
enumerable: true,
|
|
1468
|
+
get: function() {
|
|
1469
|
+
return requiresFileConsent;
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
Object.defineProperty(exports, "resolveMSTeamsReactionEmoji", {
|
|
1473
|
+
enumerable: true,
|
|
1474
|
+
get: function() {
|
|
1475
|
+
return resolveMSTeamsReactionEmoji;
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
Object.defineProperty(exports, "sendMSTeamsActivityWithReference", {
|
|
1479
|
+
enumerable: true,
|
|
1480
|
+
get: function() {
|
|
1481
|
+
return sendMSTeamsActivityWithReference;
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
1484
|
+
Object.defineProperty(exports, "sendMSTeamsMessages", {
|
|
1485
|
+
enumerable: true,
|
|
1486
|
+
get: function() {
|
|
1487
|
+
return sendMSTeamsMessages;
|
|
1488
|
+
}
|
|
1489
|
+
});
|
|
1490
|
+
Object.defineProperty(exports, "setPendingUploadActivityId", {
|
|
1491
|
+
enumerable: true,
|
|
1492
|
+
get: function() {
|
|
1493
|
+
return setPendingUploadActivityId;
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
Object.defineProperty(exports, "setPendingUploadActivityIdFs", {
|
|
1497
|
+
enumerable: true,
|
|
1498
|
+
get: function() {
|
|
1499
|
+
return setPendingUploadActivityIdFs;
|
|
1500
|
+
}
|
|
1501
|
+
});
|
|
1502
|
+
Object.defineProperty(exports, "stripHtmlFromTeamsMessage", {
|
|
1503
|
+
enumerable: true,
|
|
1504
|
+
get: function() {
|
|
1505
|
+
return stripHtmlFromTeamsMessage;
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
Object.defineProperty(exports, "updateMSTeamsActivityWithReference", {
|
|
1509
|
+
enumerable: true,
|
|
1510
|
+
get: function() {
|
|
1511
|
+
return updateMSTeamsActivityWithReference;
|
|
1512
|
+
}
|
|
1513
|
+
});
|
|
1514
|
+
Object.defineProperty(exports, "uploadAndShareSharePoint", {
|
|
1515
|
+
enumerable: true,
|
|
1516
|
+
get: function() {
|
|
1517
|
+
return uploadAndShareSharePoint;
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
Object.defineProperty(exports, "uploadToConsentUrl", {
|
|
1521
|
+
enumerable: true,
|
|
1522
|
+
get: function() {
|
|
1523
|
+
return uploadToConsentUrl;
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
Object.defineProperty(exports, "withRevokedProxyFallback", {
|
|
1527
|
+
enumerable: true,
|
|
1528
|
+
get: function() {
|
|
1529
|
+
return withRevokedProxyFallback;
|
|
1530
|
+
}
|
|
1531
|
+
});
|