@openclaw/msteams 2026.8.1-beta.2 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter.runtime-DEYjslFX.cjs → adapter.runtime-8g-MOPfb.cjs} +4 -2
- package/dist/api.cjs +6 -6
- package/dist/approval-card-B6ZIMO83.cjs +303 -0
- package/dist/approval-handler.runtime-B-ZA6Vjp.cjs +107 -0
- package/dist/{channel-DfCbi0d_.cjs → channel-ChmCvkuA.cjs} +174 -106
- package/dist/channel-config-api.cjs +1 -1
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/{channel.runtime-BJmueA4q.cjs → channel.runtime-D3qqruU3.cjs} +38 -598
- package/dist/{setup-surface-DAhGL2h8.cjs → channel.setup-CKb8aKCV.cjs} +89 -36
- package/dist/{config-schema-C4CszdDi.cjs → config-schema-MyN2lamA.cjs} +12 -11
- package/dist/configured-state.cjs +20 -0
- package/dist/directory-contract-api.cjs +1 -1
- package/dist/doctor-contract-api.cjs +76 -39
- package/dist/{messenger-BqA8G3pY.cjs → messenger-Ctb9_CO7.cjs} +46 -188
- package/dist/{oauth-DktsbN22.cjs → oauth-BV7HWGe0.cjs} +2 -2
- package/dist/qa-runner-api.cjs +1 -1
- package/dist/reaction-types-DtWOWuDN.cjs +149 -0
- package/dist/{resolve-allowlist-C6YcNC9a.cjs → resolve-allowlist-CWbvAW4v.cjs} +90 -114
- package/dist/runtime-api.cjs +3 -2
- package/dist/secret-input-C65t6kjM.cjs +1 -0
- package/dist/send-Bym7IH-v.cjs +627 -0
- package/dist/setup-plugin-api.cjs +2 -36
- package/dist/{src-Bz9wY0Mr.cjs → src-BGhvpEOP.cjs} +244 -110
- package/dist/thread-session-Br3R0ovy.cjs +63 -0
- package/package.json +13 -11
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
2
|
+
require("./runtime-api.cjs");
|
|
3
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CWbvAW4v.cjs");
|
|
4
|
+
const require_channel = require("./channel-ChmCvkuA.cjs");
|
|
5
|
+
const require_channel_setup = require("./channel.setup-CKb8aKCV.cjs");
|
|
6
|
+
const require_polls = require("./polls-DvuJvaDG.cjs");
|
|
7
|
+
const require_messenger = require("./messenger-Ctb9_CO7.cjs");
|
|
8
|
+
let openclaw_plugin_sdk_channel_outbound = require("openclaw/plugin-sdk/channel-outbound");
|
|
9
|
+
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
10
|
+
let openclaw_plugin_sdk_markdown_table_runtime = require("openclaw/plugin-sdk/markdown-table-runtime");
|
|
11
|
+
let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
|
|
12
|
+
let openclaw_plugin_sdk_outbound_media = require("openclaw/plugin-sdk/outbound-media");
|
|
13
|
+
//#region extensions/msteams/src/send-context.ts
|
|
14
|
+
function resolveMSTeamsProactiveReplyTarget(params) {
|
|
15
|
+
const threadRootId = params.ref.threadId ?? params.ref.activityId;
|
|
16
|
+
if (params.conversationType !== "channel" || !threadRootId) return { replyStyle: "top-level" };
|
|
17
|
+
const routeConfig = require_channel.resolveMSTeamsRouteConfig({
|
|
18
|
+
cfg: params.cfg,
|
|
19
|
+
teamId: params.ref.teamId,
|
|
20
|
+
conversationId: params.conversationId,
|
|
21
|
+
allowNameMatching: false
|
|
22
|
+
});
|
|
23
|
+
const { replyStyle } = require_channel.resolveMSTeamsReplyPolicy({
|
|
24
|
+
isDirectMessage: false,
|
|
25
|
+
globalConfig: params.cfg,
|
|
26
|
+
teamConfig: routeConfig.teamConfig,
|
|
27
|
+
channelConfig: routeConfig.channelConfig
|
|
28
|
+
});
|
|
29
|
+
return replyStyle === "thread" ? {
|
|
30
|
+
replyStyle,
|
|
31
|
+
threadActivityId: threadRootId
|
|
32
|
+
} : { replyStyle };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse the target value into a conversation reference lookup key.
|
|
36
|
+
* Supported formats:
|
|
37
|
+
* - conversation:19:abc@thread.tacv2 → lookup by conversation ID
|
|
38
|
+
* - conversation:19:abc@thread.tacv2;messageid=root → lookup base ID, use root
|
|
39
|
+
* - user:aad-object-id → lookup by user AAD object ID
|
|
40
|
+
* - 19:abc@thread.tacv2 → direct conversation ID
|
|
41
|
+
*/
|
|
42
|
+
function parseRecipient(to) {
|
|
43
|
+
const trimmed = to.trim();
|
|
44
|
+
const finalize = (type, id) => {
|
|
45
|
+
const normalized = id.trim();
|
|
46
|
+
if (!normalized) throw new Error(`Invalid target value: missing ${type} id`);
|
|
47
|
+
if (type === "conversation") {
|
|
48
|
+
const threadId = require_resolve_allowlist.extractMSTeamsConversationMessageId(normalized);
|
|
49
|
+
const normalizedConversationId = require_resolve_allowlist.normalizeMSTeamsConversationId(normalized);
|
|
50
|
+
const slashIndex = normalizedConversationId.indexOf("/");
|
|
51
|
+
const graphChannelId = slashIndex > 0 ? normalizedConversationId.slice(slashIndex + 1) : void 0;
|
|
52
|
+
return {
|
|
53
|
+
type,
|
|
54
|
+
id: graphChannelId && (graphChannelId.startsWith("19:") || graphChannelId.includes("@thread")) ? graphChannelId : normalizedConversationId,
|
|
55
|
+
...threadId ? { threadId } : {}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
type,
|
|
60
|
+
id: normalized
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
if (trimmed.startsWith("conversation:")) return finalize("conversation", trimmed.slice(13));
|
|
64
|
+
if (trimmed.startsWith("user:")) return finalize("user", trimmed.slice(5));
|
|
65
|
+
if (trimmed.startsWith("19:") || trimmed.includes("@thread")) return finalize("conversation", trimmed);
|
|
66
|
+
return finalize("user", trimmed);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Find a stored conversation reference for the given recipient.
|
|
70
|
+
*/
|
|
71
|
+
async function findConversationReference(recipient) {
|
|
72
|
+
if (recipient.type === "conversation") {
|
|
73
|
+
const ref = await recipient.store.get(recipient.id);
|
|
74
|
+
if (ref) return {
|
|
75
|
+
conversationId: recipient.id,
|
|
76
|
+
ref
|
|
77
|
+
};
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const found = await recipient.store.findPreferredDmByUserId(recipient.id);
|
|
81
|
+
if (!found) return null;
|
|
82
|
+
return {
|
|
83
|
+
conversationId: found.conversationId,
|
|
84
|
+
ref: found.reference
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function resolveMSTeamsSendContext(params) {
|
|
88
|
+
const msteamsCfg = params.cfg.channels?.msteams;
|
|
89
|
+
if (!msteamsCfg?.enabled) throw new Error("msteams provider is not enabled");
|
|
90
|
+
const account = require_channel_setup.resolveMSTeamsAccount(params.cfg);
|
|
91
|
+
if (account.tokenStatus === "configured_unavailable") throw new Error("msteams credential file is configured but unavailable");
|
|
92
|
+
if (!account.configured) throw new Error("msteams credentials not configured");
|
|
93
|
+
const creds = require_resolve_allowlist.resolveMSTeamsCredentials(msteamsCfg);
|
|
94
|
+
if (!creds) throw new Error("msteams credentials not configured");
|
|
95
|
+
const store = require_polls.createMSTeamsConversationStoreState();
|
|
96
|
+
const recipient = parseRecipient(params.to);
|
|
97
|
+
const found = await findConversationReference({
|
|
98
|
+
...recipient,
|
|
99
|
+
store
|
|
100
|
+
});
|
|
101
|
+
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.`);
|
|
102
|
+
const conversationId = found.conversationId;
|
|
103
|
+
const ref = recipient.threadId ? {
|
|
104
|
+
...found.ref,
|
|
105
|
+
threadId: recipient.threadId
|
|
106
|
+
} : found.ref;
|
|
107
|
+
const log = require_runtime.getMSTeamsRuntime().logging.getChildLogger({ name: "msteams:send" });
|
|
108
|
+
if (ref.serviceUrl && !require_resolve_allowlist.isAllowedBotFrameworkServiceUrl(ref.serviceUrl)) {
|
|
109
|
+
try {
|
|
110
|
+
await store.remove(conversationId);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
log.warn?.("failed to remove blocked msteams conversation reference", {
|
|
113
|
+
conversationId,
|
|
114
|
+
error: require_channel_setup.formatUnknownError(err)
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
throw new Error(`Stored Microsoft Teams conversation reference has blocked serviceUrl host: ${require_resolve_allowlist.describeBotFrameworkServiceUrlHost(ref.serviceUrl)}. The bot must receive a new message from this conversation before it can send proactively.`);
|
|
118
|
+
}
|
|
119
|
+
const safeRef = ref.serviceUrl ? {
|
|
120
|
+
...ref,
|
|
121
|
+
serviceUrl: require_resolve_allowlist.normalizeBotFrameworkServiceUrl(ref.serviceUrl)
|
|
122
|
+
} : ref;
|
|
123
|
+
if (recipient.type === "user") {
|
|
124
|
+
const resolvedType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(safeRef.conversation?.conversationType ?? "");
|
|
125
|
+
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.`);
|
|
126
|
+
}
|
|
127
|
+
const sdkCloudOptions = require_resolve_allowlist.resolveMSTeamsSdkCloudOptions(msteamsCfg);
|
|
128
|
+
const { app } = await require_resolve_allowlist.loadMSTeamsSdkWithAuth(creds, sdkCloudOptions);
|
|
129
|
+
require_resolve_allowlist.validateMSTeamsProactiveServiceUrlBoundary({
|
|
130
|
+
cloud: sdkCloudOptions.cloud,
|
|
131
|
+
conversationId,
|
|
132
|
+
storedServiceUrl: safeRef.serviceUrl,
|
|
133
|
+
configuredServiceUrl: sdkCloudOptions.serviceUrl
|
|
134
|
+
});
|
|
135
|
+
const tokenProvider = require_resolve_allowlist.createMSTeamsTokenProvider(app);
|
|
136
|
+
const storedConversationType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(safeRef.conversation?.conversationType ?? "");
|
|
137
|
+
let conversationType;
|
|
138
|
+
if (storedConversationType === "personal") conversationType = "personal";
|
|
139
|
+
else if (storedConversationType === "channel") conversationType = "channel";
|
|
140
|
+
else conversationType = "groupChat";
|
|
141
|
+
const replyTarget = recipient.threadId && conversationType === "channel" ? {
|
|
142
|
+
replyStyle: "thread",
|
|
143
|
+
threadActivityId: recipient.threadId
|
|
144
|
+
} : resolveMSTeamsProactiveReplyTarget({
|
|
145
|
+
cfg: msteamsCfg,
|
|
146
|
+
conversationId,
|
|
147
|
+
ref: safeRef,
|
|
148
|
+
conversationType
|
|
149
|
+
});
|
|
150
|
+
const sharePointSiteId = msteamsCfg.sharePointSiteId;
|
|
151
|
+
const mediaMaxBytes = (0, openclaw_plugin_sdk_account_helpers.resolveChannelMediaMaxBytes)({
|
|
152
|
+
cfg: params.cfg,
|
|
153
|
+
resolveChannelLimitMb: ({ cfg }) => cfg.channels?.msteams?.mediaMaxMb
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
appId: creds.appId,
|
|
157
|
+
conversationId,
|
|
158
|
+
ref: safeRef,
|
|
159
|
+
app,
|
|
160
|
+
log,
|
|
161
|
+
conversationType,
|
|
162
|
+
...replyTarget,
|
|
163
|
+
sdkCloudOptions,
|
|
164
|
+
tokenProvider,
|
|
165
|
+
sharePointSiteId,
|
|
166
|
+
mediaMaxBytes
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region extensions/msteams/src/send.ts
|
|
171
|
+
/** Threshold for large files that require FileConsentCard flow in personal chats */
|
|
172
|
+
const FILE_CONSENT_THRESHOLD_BYTES = 4 * 1024 * 1024;
|
|
173
|
+
/**
|
|
174
|
+
* MSTeams-specific media size limit (100MB).
|
|
175
|
+
* Higher than the default to support Teams file-consent and SharePoint uploads.
|
|
176
|
+
*/
|
|
177
|
+
const MSTEAMS_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
178
|
+
function createMSTeamsSendError(errorPrefix, error) {
|
|
179
|
+
const classification = require_channel_setup.classifyMSTeamsSendError(error);
|
|
180
|
+
const hint = require_channel_setup.formatMSTeamsSendErrorHint(classification);
|
|
181
|
+
const status = classification.statusCode ? ` (HTTP ${classification.statusCode})` : "";
|
|
182
|
+
return new Error(`${errorPrefix} failed${status}: ${require_channel_setup.formatUnknownError(error)}${hint ? ` (${hint})` : ""}`, { cause: error });
|
|
183
|
+
}
|
|
184
|
+
function createMSTeamsSendReceipt(params) {
|
|
185
|
+
const receipt = (0, openclaw_plugin_sdk_channel_outbound.createMessageReceiptFromOutboundResults)({
|
|
186
|
+
kind: params.kind,
|
|
187
|
+
results: params.platformMessageIds.map((messageId) => ({
|
|
188
|
+
channel: "msteams",
|
|
189
|
+
messageId,
|
|
190
|
+
conversationId: params.conversationId
|
|
191
|
+
}))
|
|
192
|
+
});
|
|
193
|
+
if (!params.kinds) return receipt;
|
|
194
|
+
const kinds = params.kinds;
|
|
195
|
+
return {
|
|
196
|
+
...receipt,
|
|
197
|
+
parts: receipt.parts.map((part, index) => {
|
|
198
|
+
const nextPart = {
|
|
199
|
+
platformMessageId: part.platformMessageId,
|
|
200
|
+
kind: kinds[index] ?? params.kind,
|
|
201
|
+
index: part.index
|
|
202
|
+
};
|
|
203
|
+
if (part.threadId) nextPart.threadId = part.threadId;
|
|
204
|
+
if (part.replyToId) nextPart.replyToId = part.replyToId;
|
|
205
|
+
if (part.raw) nextPart.raw = part.raw;
|
|
206
|
+
return nextPart;
|
|
207
|
+
})
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function createMSTeamsSendResult(params) {
|
|
211
|
+
const platformMessageIds = (params.platformMessageIds?.length ? [...params.platformMessageIds] : [params.messageId]).map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown");
|
|
212
|
+
return {
|
|
213
|
+
messageId: params.messageId,
|
|
214
|
+
conversationId: params.conversationId,
|
|
215
|
+
receipt: createMSTeamsSendReceipt({
|
|
216
|
+
conversationId: params.conversationId,
|
|
217
|
+
platformMessageIds,
|
|
218
|
+
kind: params.kind
|
|
219
|
+
}),
|
|
220
|
+
...params.pendingUploadId ? { pendingUploadId: params.pendingUploadId } : {}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Send a message to a Teams conversation or user.
|
|
225
|
+
*
|
|
226
|
+
* Uses the stored ConversationReference from previous interactions.
|
|
227
|
+
* The bot must have received at least one message from the conversation
|
|
228
|
+
* before proactive messaging works.
|
|
229
|
+
*
|
|
230
|
+
* File handling by conversation type:
|
|
231
|
+
* - Personal (1:1) chats: small images (<4MB) use base64, large files and non-images use FileConsentCard
|
|
232
|
+
* - Group chats / channels: files require configured SharePoint storage
|
|
233
|
+
*/
|
|
234
|
+
async function sendMessageMSTeams(params) {
|
|
235
|
+
const { cfg, to, text, mediaUrl, filename, mediaAccess, mediaLocalRoots, mediaReadFile } = params;
|
|
236
|
+
const tableMode = (0, openclaw_plugin_sdk_markdown_table_runtime.resolveMarkdownTableMode)({
|
|
237
|
+
cfg,
|
|
238
|
+
channel: "msteams"
|
|
239
|
+
});
|
|
240
|
+
const messageText = require_messenger.formatMSTeamsMarkdown(text ?? "", tableMode);
|
|
241
|
+
const ctx = await resolveMSTeamsSendContext({
|
|
242
|
+
cfg,
|
|
243
|
+
to
|
|
244
|
+
});
|
|
245
|
+
const { conversationId, log, conversationType, tokenProvider, sharePointSiteId } = ctx;
|
|
246
|
+
log.debug?.("sending proactive message", {
|
|
247
|
+
conversationId,
|
|
248
|
+
conversationType,
|
|
249
|
+
textLength: messageText.length,
|
|
250
|
+
hasMedia: Boolean(mediaUrl)
|
|
251
|
+
});
|
|
252
|
+
if (mediaUrl) {
|
|
253
|
+
const media = await (0, openclaw_plugin_sdk_outbound_media.loadOutboundMediaFromUrl)(mediaUrl, {
|
|
254
|
+
maxBytes: ctx.mediaMaxBytes ?? MSTEAMS_MAX_MEDIA_BYTES,
|
|
255
|
+
mediaAccess,
|
|
256
|
+
mediaLocalRoots,
|
|
257
|
+
mediaReadFile
|
|
258
|
+
});
|
|
259
|
+
const isLargeFile = media.buffer.length >= FILE_CONSENT_THRESHOLD_BYTES;
|
|
260
|
+
const isImage = media.contentType?.startsWith("image/") ?? false;
|
|
261
|
+
const fallbackFileName = await require_messenger.extractFilename(mediaUrl);
|
|
262
|
+
const fileName = filename?.trim() || media.fileName || fallbackFileName;
|
|
263
|
+
log.debug?.("processing media", {
|
|
264
|
+
fileName,
|
|
265
|
+
contentType: media.contentType,
|
|
266
|
+
size: media.buffer.length,
|
|
267
|
+
isLargeFile,
|
|
268
|
+
isImage,
|
|
269
|
+
conversationType
|
|
270
|
+
});
|
|
271
|
+
if (require_messenger.requiresFileConsent({
|
|
272
|
+
conversationType,
|
|
273
|
+
contentType: media.contentType,
|
|
274
|
+
bufferSize: media.buffer.length,
|
|
275
|
+
thresholdBytes: FILE_CONSENT_THRESHOLD_BYTES
|
|
276
|
+
})) {
|
|
277
|
+
const { activity, uploadId } = await require_messenger.prepareFileConsentActivityFs({
|
|
278
|
+
media: {
|
|
279
|
+
buffer: media.buffer,
|
|
280
|
+
filename: fileName,
|
|
281
|
+
contentType: media.contentType
|
|
282
|
+
},
|
|
283
|
+
conversationId,
|
|
284
|
+
description: messageText || void 0
|
|
285
|
+
});
|
|
286
|
+
log.debug?.("sending file consent card", {
|
|
287
|
+
uploadId,
|
|
288
|
+
fileName,
|
|
289
|
+
size: media.buffer.length
|
|
290
|
+
});
|
|
291
|
+
const messageId = await sendProactiveActivity({
|
|
292
|
+
ctx,
|
|
293
|
+
activity,
|
|
294
|
+
errorPrefix: "msteams consent card send"
|
|
295
|
+
});
|
|
296
|
+
require_messenger.setPendingUploadActivityId(uploadId, messageId);
|
|
297
|
+
await require_messenger.setPendingUploadActivityIdFs(uploadId, messageId);
|
|
298
|
+
log.info("sent file consent card", {
|
|
299
|
+
conversationId,
|
|
300
|
+
messageId,
|
|
301
|
+
uploadId
|
|
302
|
+
});
|
|
303
|
+
return createMSTeamsSendResult({
|
|
304
|
+
messageId,
|
|
305
|
+
conversationId,
|
|
306
|
+
kind: "card",
|
|
307
|
+
pendingUploadId: uploadId
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
if (conversationType === "personal") {
|
|
311
|
+
const base64 = media.buffer.toString("base64");
|
|
312
|
+
return sendTextWithMedia(ctx, messageText, `data:${media.contentType};base64,${base64}`);
|
|
313
|
+
}
|
|
314
|
+
if (isImage && !sharePointSiteId) {
|
|
315
|
+
const base64 = media.buffer.toString("base64");
|
|
316
|
+
return sendTextWithMedia(ctx, messageText, `data:${media.contentType};base64,${base64}`);
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const siteId = require_messenger.requireMSTeamsSharePointSiteId(sharePointSiteId);
|
|
320
|
+
log.debug?.("uploading to SharePoint for native file card", {
|
|
321
|
+
fileName,
|
|
322
|
+
conversationType,
|
|
323
|
+
siteId
|
|
324
|
+
});
|
|
325
|
+
const uploaded = await require_messenger.uploadAndShareSharePoint({
|
|
326
|
+
buffer: media.buffer,
|
|
327
|
+
filename: fileName,
|
|
328
|
+
contentType: media.contentType,
|
|
329
|
+
tokenProvider,
|
|
330
|
+
siteId,
|
|
331
|
+
chatId: conversationId,
|
|
332
|
+
usePerUserSharing: conversationType === "groupChat"
|
|
333
|
+
});
|
|
334
|
+
log.debug?.("SharePoint upload complete", {
|
|
335
|
+
itemId: uploaded.itemId,
|
|
336
|
+
shareUrl: uploaded.shareUrl
|
|
337
|
+
});
|
|
338
|
+
const driveItem = await require_messenger.getDriveItemProperties({
|
|
339
|
+
siteId,
|
|
340
|
+
itemId: uploaded.itemId,
|
|
341
|
+
tokenProvider
|
|
342
|
+
});
|
|
343
|
+
log.debug?.("driveItem properties retrieved", {
|
|
344
|
+
eTag: driveItem.eTag,
|
|
345
|
+
webDavUrl: driveItem.webDavUrl
|
|
346
|
+
});
|
|
347
|
+
const fileCardAttachment = require_messenger.buildTeamsFileInfoCard(driveItem);
|
|
348
|
+
const messageId = await sendProactiveActivityRaw({
|
|
349
|
+
ctx,
|
|
350
|
+
activity: {
|
|
351
|
+
type: "message",
|
|
352
|
+
text: messageText || void 0,
|
|
353
|
+
attachments: [fileCardAttachment]
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
log.info("sent native file card", {
|
|
357
|
+
conversationId,
|
|
358
|
+
messageId,
|
|
359
|
+
fileName: driveItem.name
|
|
360
|
+
});
|
|
361
|
+
return createMSTeamsSendResult({
|
|
362
|
+
messageId,
|
|
363
|
+
conversationId,
|
|
364
|
+
kind: "media"
|
|
365
|
+
});
|
|
366
|
+
} catch (err) {
|
|
367
|
+
throw createMSTeamsSendError("msteams file send", err);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return sendTextWithMedia(ctx, messageText, void 0);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Send a text message with optional base64 media URL.
|
|
374
|
+
*/
|
|
375
|
+
async function sendTextWithMedia(ctx, text, mediaUrl) {
|
|
376
|
+
const { app, appId, conversationId, ref, log, tokenProvider, sharePointSiteId, mediaMaxBytes, replyStyle } = ctx;
|
|
377
|
+
const messages = text && mediaUrl ? [{ text }, { mediaUrl }] : [{
|
|
378
|
+
text: text || void 0,
|
|
379
|
+
mediaUrl
|
|
380
|
+
}];
|
|
381
|
+
let platformMessageIds;
|
|
382
|
+
try {
|
|
383
|
+
platformMessageIds = await require_messenger.sendMSTeamsMessages({
|
|
384
|
+
replyStyle,
|
|
385
|
+
app,
|
|
386
|
+
appId,
|
|
387
|
+
conversationRef: ref,
|
|
388
|
+
messages,
|
|
389
|
+
retry: {},
|
|
390
|
+
onRetry: (event) => {
|
|
391
|
+
log.debug?.("retrying send", {
|
|
392
|
+
conversationId,
|
|
393
|
+
...event
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
tokenProvider,
|
|
397
|
+
sharePointSiteId,
|
|
398
|
+
mediaMaxBytes,
|
|
399
|
+
serviceUrlBoundary: ctx.sdkCloudOptions
|
|
400
|
+
});
|
|
401
|
+
} catch (err) {
|
|
402
|
+
throw createMSTeamsSendError("msteams send", err);
|
|
403
|
+
}
|
|
404
|
+
const messageId = platformMessageIds[0] ?? "unknown";
|
|
405
|
+
log.info("sent proactive message", {
|
|
406
|
+
conversationId,
|
|
407
|
+
messageId
|
|
408
|
+
});
|
|
409
|
+
return {
|
|
410
|
+
messageId,
|
|
411
|
+
conversationId,
|
|
412
|
+
receipt: createMSTeamsSendReceipt({
|
|
413
|
+
conversationId,
|
|
414
|
+
platformMessageIds,
|
|
415
|
+
kind: mediaUrl ? "media" : "text",
|
|
416
|
+
...text && mediaUrl ? { kinds: ["text", "media"] } : {}
|
|
417
|
+
})
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
async function sendProactiveActivityRaw({ ctx, activity }) {
|
|
421
|
+
const baseRef = require_messenger.buildConversationReference(ctx.ref);
|
|
422
|
+
return require_messenger.extractMessageId(await require_messenger.sendMSTeamsActivityWithReference(ctx.app, baseRef, activity, {
|
|
423
|
+
...ctx.threadActivityId ? { threadActivityId: ctx.threadActivityId } : {},
|
|
424
|
+
serviceUrlBoundary: ctx.sdkCloudOptions
|
|
425
|
+
})) ?? "unknown";
|
|
426
|
+
}
|
|
427
|
+
async function sendProactiveActivity({ ctx, activity, errorPrefix }) {
|
|
428
|
+
try {
|
|
429
|
+
return await sendProactiveActivityRaw({
|
|
430
|
+
ctx,
|
|
431
|
+
activity
|
|
432
|
+
});
|
|
433
|
+
} catch (err) {
|
|
434
|
+
throw createMSTeamsSendError(errorPrefix, err);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Send a poll (Adaptive Card) to a Teams conversation or user.
|
|
439
|
+
*/
|
|
440
|
+
async function sendPollMSTeams(params) {
|
|
441
|
+
const { cfg, to, question, options, maxSelections } = params;
|
|
442
|
+
const ctx = await resolveMSTeamsSendContext({
|
|
443
|
+
cfg,
|
|
444
|
+
to
|
|
445
|
+
});
|
|
446
|
+
const { conversationId, log } = ctx;
|
|
447
|
+
const pollCard = require_polls.buildMSTeamsPollCard({
|
|
448
|
+
question,
|
|
449
|
+
options,
|
|
450
|
+
maxSelections
|
|
451
|
+
});
|
|
452
|
+
log.debug?.("sending poll", {
|
|
453
|
+
conversationId,
|
|
454
|
+
pollId: pollCard.pollId,
|
|
455
|
+
optionCount: pollCard.options.length
|
|
456
|
+
});
|
|
457
|
+
const messageId = await sendProactiveActivity({
|
|
458
|
+
ctx,
|
|
459
|
+
activity: {
|
|
460
|
+
type: "message",
|
|
461
|
+
attachments: [{
|
|
462
|
+
contentType: "application/vnd.microsoft.card.adaptive",
|
|
463
|
+
content: pollCard.card
|
|
464
|
+
}]
|
|
465
|
+
},
|
|
466
|
+
errorPrefix: "msteams poll send"
|
|
467
|
+
});
|
|
468
|
+
log.info("sent poll", {
|
|
469
|
+
conversationId,
|
|
470
|
+
pollId: pollCard.pollId,
|
|
471
|
+
messageId
|
|
472
|
+
});
|
|
473
|
+
return {
|
|
474
|
+
pollId: pollCard.pollId,
|
|
475
|
+
messageId,
|
|
476
|
+
conversationId
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Send an arbitrary Adaptive Card to a Teams conversation or user.
|
|
481
|
+
*/
|
|
482
|
+
async function sendAdaptiveCardMSTeams(params) {
|
|
483
|
+
const { cfg, to, card } = params;
|
|
484
|
+
const ctx = await resolveMSTeamsSendContext({
|
|
485
|
+
cfg,
|
|
486
|
+
to
|
|
487
|
+
});
|
|
488
|
+
const { conversationId, log } = ctx;
|
|
489
|
+
log.debug?.("sending adaptive card", {
|
|
490
|
+
conversationId,
|
|
491
|
+
cardType: card.type,
|
|
492
|
+
cardVersion: card.version
|
|
493
|
+
});
|
|
494
|
+
const messageId = await sendProactiveActivity({
|
|
495
|
+
ctx,
|
|
496
|
+
activity: {
|
|
497
|
+
type: "message",
|
|
498
|
+
attachments: [{
|
|
499
|
+
contentType: "application/vnd.microsoft.card.adaptive",
|
|
500
|
+
content: card
|
|
501
|
+
}]
|
|
502
|
+
},
|
|
503
|
+
errorPrefix: "msteams card send"
|
|
504
|
+
});
|
|
505
|
+
log.info("sent adaptive card", {
|
|
506
|
+
conversationId,
|
|
507
|
+
messageId
|
|
508
|
+
});
|
|
509
|
+
return {
|
|
510
|
+
messageId,
|
|
511
|
+
conversationId
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Edit (update) a previously sent message in a Teams conversation.
|
|
516
|
+
*
|
|
517
|
+
* Uses the Bot Framework REST API for proactive edits outside of the
|
|
518
|
+
* original turn context.
|
|
519
|
+
*/
|
|
520
|
+
async function editMessageMSTeams(params) {
|
|
521
|
+
return updateMSTeamsMessageActivity({
|
|
522
|
+
...params,
|
|
523
|
+
activity: {
|
|
524
|
+
type: "message",
|
|
525
|
+
id: params.activityId,
|
|
526
|
+
text: params.text
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
async function editAdaptiveCardMSTeams(params) {
|
|
531
|
+
return updateMSTeamsMessageActivity({
|
|
532
|
+
...params,
|
|
533
|
+
activity: {
|
|
534
|
+
type: "message",
|
|
535
|
+
id: params.activityId,
|
|
536
|
+
attachments: [{
|
|
537
|
+
contentType: "application/vnd.microsoft.card.adaptive",
|
|
538
|
+
content: params.card
|
|
539
|
+
}]
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
async function updateMSTeamsMessageActivity(params) {
|
|
544
|
+
const { cfg, to, activityId, activity } = params;
|
|
545
|
+
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
546
|
+
cfg,
|
|
547
|
+
to
|
|
548
|
+
});
|
|
549
|
+
log.debug?.("editing proactive message", {
|
|
550
|
+
conversationId,
|
|
551
|
+
activityId
|
|
552
|
+
});
|
|
553
|
+
try {
|
|
554
|
+
await require_messenger.updateMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activityId, activity, { serviceUrlBoundary: sdkCloudOptions });
|
|
555
|
+
} catch (err) {
|
|
556
|
+
throw createMSTeamsSendError("msteams edit", err);
|
|
557
|
+
}
|
|
558
|
+
log.info("edited proactive message", {
|
|
559
|
+
conversationId,
|
|
560
|
+
activityId
|
|
561
|
+
});
|
|
562
|
+
return { conversationId };
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Delete a previously sent message in a Teams conversation.
|
|
566
|
+
*
|
|
567
|
+
* Uses the Bot Framework REST API for proactive deletes outside of the
|
|
568
|
+
* original turn context.
|
|
569
|
+
*/
|
|
570
|
+
async function deleteMessageMSTeams(params) {
|
|
571
|
+
const { cfg, to, activityId } = params;
|
|
572
|
+
const { app, conversationId, ref, log, sdkCloudOptions } = await resolveMSTeamsSendContext({
|
|
573
|
+
cfg,
|
|
574
|
+
to
|
|
575
|
+
});
|
|
576
|
+
log.debug?.("deleting proactive message", {
|
|
577
|
+
conversationId,
|
|
578
|
+
activityId
|
|
579
|
+
});
|
|
580
|
+
try {
|
|
581
|
+
await require_messenger.deleteMSTeamsActivityWithReference(app, require_messenger.buildConversationReference(ref), activityId, { serviceUrlBoundary: sdkCloudOptions });
|
|
582
|
+
} catch (err) {
|
|
583
|
+
throw createMSTeamsSendError("msteams delete", err);
|
|
584
|
+
}
|
|
585
|
+
log.info("deleted proactive message", {
|
|
586
|
+
conversationId,
|
|
587
|
+
activityId
|
|
588
|
+
});
|
|
589
|
+
return { conversationId };
|
|
590
|
+
}
|
|
591
|
+
//#endregion
|
|
592
|
+
Object.defineProperty(exports, "deleteMessageMSTeams", {
|
|
593
|
+
enumerable: true,
|
|
594
|
+
get: function() {
|
|
595
|
+
return deleteMessageMSTeams;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
Object.defineProperty(exports, "editAdaptiveCardMSTeams", {
|
|
599
|
+
enumerable: true,
|
|
600
|
+
get: function() {
|
|
601
|
+
return editAdaptiveCardMSTeams;
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
Object.defineProperty(exports, "editMessageMSTeams", {
|
|
605
|
+
enumerable: true,
|
|
606
|
+
get: function() {
|
|
607
|
+
return editMessageMSTeams;
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
Object.defineProperty(exports, "sendAdaptiveCardMSTeams", {
|
|
611
|
+
enumerable: true,
|
|
612
|
+
get: function() {
|
|
613
|
+
return sendAdaptiveCardMSTeams;
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
Object.defineProperty(exports, "sendMessageMSTeams", {
|
|
617
|
+
enumerable: true,
|
|
618
|
+
get: function() {
|
|
619
|
+
return sendMessageMSTeams;
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
Object.defineProperty(exports, "sendPollMSTeams", {
|
|
623
|
+
enumerable: true,
|
|
624
|
+
get: function() {
|
|
625
|
+
return sendPollMSTeams;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
@@ -1,37 +1,3 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
const require_config_schema = require("./config-schema-C4CszdDi.cjs");
|
|
5
|
-
let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
|
|
6
|
-
//#region extensions/msteams/src/channel.setup.ts
|
|
7
|
-
const msteamsSetupPlugin = {
|
|
8
|
-
id: "msteams",
|
|
9
|
-
meta: {
|
|
10
|
-
...require_setup_surface.msteamsMeta,
|
|
11
|
-
aliases: [...require_setup_surface.msteamsMeta.aliases]
|
|
12
|
-
},
|
|
13
|
-
capabilities: {
|
|
14
|
-
chatTypes: [
|
|
15
|
-
"direct",
|
|
16
|
-
"channel",
|
|
17
|
-
"thread"
|
|
18
|
-
],
|
|
19
|
-
polls: true,
|
|
20
|
-
threads: true,
|
|
21
|
-
media: true
|
|
22
|
-
},
|
|
23
|
-
reload: { configPrefixes: ["channels.msteams"] },
|
|
24
|
-
configSchema: require_config_schema.MSTeamsChannelConfigSchema,
|
|
25
|
-
config: {
|
|
26
|
-
...require_setup_surface.msteamsConfigAdapter,
|
|
27
|
-
isConfigured: (_account, cfg) => Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams)),
|
|
28
|
-
describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
|
|
29
|
-
account,
|
|
30
|
-
configured: account.configured
|
|
31
|
-
})
|
|
32
|
-
},
|
|
33
|
-
setupWizard: require_setup_surface.msteamsSetupWizard,
|
|
34
|
-
setupContract: require_setup_surface.msteamsSetupContract
|
|
35
|
-
};
|
|
36
|
-
//#endregion
|
|
37
|
-
exports.msteamsSetupPlugin = msteamsSetupPlugin;
|
|
2
|
+
const require_channel_setup = require("./channel.setup-CKb8aKCV.cjs");
|
|
3
|
+
exports.msteamsSetupPlugin = require_channel_setup.msteamsSetupPlugin;
|