@openclaw/msteams 2026.9.6 → 2026.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/icon.png +0 -0
- package/dist/.setup/{adapter.runtime-CQWZeqB5.cjs → adapter.runtime-BiWeMKXE.cjs} +21 -29
- package/dist/.setup/{approval-card-CPNH_q3P.cjs → approval-card-DWPDItvq.cjs} +6 -3
- package/dist/.setup/{approval-handler.runtime-CUnanUdR.cjs → approval-handler.runtime-D1s7UR3U.cjs} +4 -4
- package/dist/.setup/bot-framework-service-url-BUhTe8F3.cjs +55 -0
- package/dist/.setup/{channel-BDp16XRR.cjs → channel-ByzS7QJ0.cjs} +286 -180
- package/dist/.setup/{channel.runtime-Cv5F8JCa.cjs → channel.runtime-Baz8XDFs.cjs} +43 -142
- package/dist/.setup/{channel.setup-BVDfgdCc.cjs → channel.setup-DL8lcWT_.cjs} +6 -6
- package/dist/.setup/{config-schema-D22Lr1Qk.cjs → config-schema-0KoBzb0t.cjs} +24 -38
- package/dist/.setup/{messenger-8RA1FUJa.cjs → conversation-store-state-B7JuyZTm.cjs} +693 -287
- package/dist/.setup/{src-BfOCwlHp.cjs → monitor-BJ7IyH4y.cjs} +422 -592
- package/dist/.setup/{oauth-C6m7dvHj.cjs → oauth-DQjOnJ4l.cjs} +1 -1
- package/dist/.setup/{reaction-types-C7RA7Wxt.cjs → reaction-types-CQ4oSUe7.cjs} +2 -6
- package/dist/.setup/{resolve-allowlist-CHzaaWiC.cjs → resolve-allowlist-Pl_NQFYH.cjs} +55 -312
- package/dist/.setup/{rolldown-runtime-VH7oDXx4.cjs → rolldown-runtime-BloeesfJ.cjs} +22 -0
- package/dist/.setup/{send-CYN_N7O1.cjs → send-VUM7Sryb.cjs} +43 -96
- package/dist/.setup/{setup-plugin-api-DpiaA8z1.cjs → setup-plugin-api-Dyf8kF-l.cjs} +1 -1
- package/dist/.setup/{thread-session-CXgHK-yi.cjs → thread-session--rw3BTal.cjs} +2 -5
- package/dist/api.cjs +2 -2
- package/dist/channel-config-api.cjs +1 -1
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/configured-state.cjs +0 -1
- package/dist/directory-contract-api.cjs +1 -1
- package/dist/doctor-contract-api.cjs +201 -371
- package/dist/qa-runner-api.cjs +1 -1
- package/dist/runtime-api.cjs +0 -6
- package/dist/setup-entry.cjs +1 -1
- package/dist/setup-plugin-api.cjs +1 -1
- package/openclaw.plugin.json +46 -5
- package/package.json +9 -9
- package/dist/.setup/polls-BJ4-4uZm.cjs +0 -668
- package/dist/.setup/secret-input-C65t6kjM.cjs +0 -1
- package/dist/.setup/sso-token-store-YYLHXgFH.cjs +0 -111
|
@@ -1,668 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
|
|
2
|
-
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
3
|
-
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
4
|
-
let openclaw_plugin_sdk_file_lock = require("openclaw/plugin-sdk/file-lock");
|
|
5
|
-
let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
|
|
6
|
-
let node_crypto = require("node:crypto");
|
|
7
|
-
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
8
|
-
let node_path = require("node:path");
|
|
9
|
-
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
10
|
-
let openclaw_plugin_sdk_keyed_async_queue = require("openclaw/plugin-sdk/keyed-async-queue");
|
|
11
|
-
//#region extensions/msteams/src/conversation-store-helpers.ts
|
|
12
|
-
function normalizeStoredConversationId(raw) {
|
|
13
|
-
return raw.split(";")[0] ?? raw;
|
|
14
|
-
}
|
|
15
|
-
function toConversationStoreEntries(entries) {
|
|
16
|
-
return Array.from(entries, ([conversationId, reference]) => ({
|
|
17
|
-
conversationId,
|
|
18
|
-
reference
|
|
19
|
-
}));
|
|
20
|
-
}
|
|
21
|
-
function mergeStoredConversationReference(existing, incoming, nowIso) {
|
|
22
|
-
return {
|
|
23
|
-
...existing?.timezone && !incoming.timezone ? { timezone: existing.timezone } : {},
|
|
24
|
-
...existing?.tenantId && !incoming.tenantId ? { tenantId: existing.tenantId } : {},
|
|
25
|
-
...existing?.aadObjectId && !incoming.aadObjectId ? { aadObjectId: existing.aadObjectId } : {},
|
|
26
|
-
...incoming,
|
|
27
|
-
lastSeenAt: nowIso
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function findPreferredDmConversationByUserId(entries, id) {
|
|
31
|
-
const target = id.trim();
|
|
32
|
-
if (!target) return null;
|
|
33
|
-
const personalMatches = [];
|
|
34
|
-
const unknownTypeMatches = [];
|
|
35
|
-
for (const entry of entries) {
|
|
36
|
-
if (entry.reference.user?.aadObjectId !== target && entry.reference.user?.id !== target) continue;
|
|
37
|
-
const convType = (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeLowercaseStringOrEmpty)(entry.reference.conversation?.conversationType ?? "");
|
|
38
|
-
if (convType === "personal") personalMatches.push(entry);
|
|
39
|
-
else if (convType === "channel" || convType === "groupchat") {} else unknownTypeMatches.push(entry);
|
|
40
|
-
}
|
|
41
|
-
const candidates = personalMatches.length > 0 ? personalMatches : unknownTypeMatches;
|
|
42
|
-
if (candidates.length === 0) return null;
|
|
43
|
-
if (candidates.length > 1) candidates.sort((a, b) => ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(b.reference.lastSeenAt) ?? 0) - ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(a.reference.lastSeenAt) ?? 0));
|
|
44
|
-
return candidates[0] ?? null;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region extensions/msteams/src/sqlite-state.ts
|
|
48
|
-
function resolveStateDirOverride(options) {
|
|
49
|
-
if (!options) return;
|
|
50
|
-
if (options.stateDir) return options.stateDir;
|
|
51
|
-
if (options.storePath) return node_path.default.dirname(options.storePath);
|
|
52
|
-
if (options.homedir) return require_runtime.getMSTeamsRuntime().state.resolveStateDir(options.env ?? process.env, options.homedir);
|
|
53
|
-
return options.env?.OPENCLAW_STATE_DIR?.trim() || void 0;
|
|
54
|
-
}
|
|
55
|
-
function resolveMSTeamsSqliteStateEnv(options) {
|
|
56
|
-
const stateDir = resolveStateDirOverride(options);
|
|
57
|
-
if (!stateDir) return options?.env;
|
|
58
|
-
return {
|
|
59
|
-
...options?.env ?? process.env,
|
|
60
|
-
OPENCLAW_STATE_DIR: stateDir
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
function toPluginJsonValue(value) {
|
|
64
|
-
const serialized = JSON.stringify(value);
|
|
65
|
-
return JSON.parse(serialized);
|
|
66
|
-
}
|
|
67
|
-
function resolveMSTeamsSqliteStateDir(options) {
|
|
68
|
-
return resolveStateDirOverride(options) ?? require_runtime.getMSTeamsRuntime().state.resolveStateDir(options?.env ?? process.env, options?.homedir);
|
|
69
|
-
}
|
|
70
|
-
const sqliteMutationLocks = new openclaw_plugin_sdk_keyed_async_queue.KeyedAsyncQueue();
|
|
71
|
-
const MSTEAMS_MUTATION_LOCK_OPTIONS = {
|
|
72
|
-
retries: {
|
|
73
|
-
retries: 10,
|
|
74
|
-
factor: 2,
|
|
75
|
-
minTimeout: 100,
|
|
76
|
-
maxTimeout: 1e4,
|
|
77
|
-
randomize: true
|
|
78
|
-
},
|
|
79
|
-
stale: 3e4
|
|
80
|
-
};
|
|
81
|
-
async function withProcessMutationLock(lockPath, fn) {
|
|
82
|
-
return await sqliteMutationLocks.enqueue(lockPath, fn);
|
|
83
|
-
}
|
|
84
|
-
async function withMSTeamsSqliteMutationLock(options, mutationKey, fn) {
|
|
85
|
-
const scopedMutationKey = node_path.default.join(resolveMSTeamsSqliteStateDir(options), mutationKey);
|
|
86
|
-
return await withProcessMutationLock(scopedMutationKey, async () => {
|
|
87
|
-
return await (0, openclaw_plugin_sdk_file_lock.withFileLock)(scopedMutationKey, MSTEAMS_MUTATION_LOCK_OPTIONS, fn);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region extensions/msteams/src/conversation-store-state.ts
|
|
92
|
-
const MSTEAMS_CONVERSATIONS_LEGACY_FILENAME = "msteams-conversations.json";
|
|
93
|
-
const MSTEAMS_CONVERSATIONS_NAMESPACE = "conversations";
|
|
94
|
-
const MSTEAMS_MAX_CONVERSATIONS = 1e3;
|
|
95
|
-
const MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS = 2e3;
|
|
96
|
-
const MSTEAMS_CONVERSATION_TTL_MS = 31536e6;
|
|
97
|
-
const CONVERSATION_MUTATION_KEY = "conversations";
|
|
98
|
-
function createConversationStateStore(params) {
|
|
99
|
-
return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
|
|
100
|
-
namespace: MSTEAMS_CONVERSATIONS_NAMESPACE,
|
|
101
|
-
maxEntries: MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS,
|
|
102
|
-
env: resolveMSTeamsSqliteStateEnv(params)
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
function normalizeMSTeamsLegacyConversationStore(value) {
|
|
106
|
-
if (value.version !== 1 || !value.conversations || typeof value.conversations !== "object" || Array.isArray(value.conversations)) return {
|
|
107
|
-
version: 1,
|
|
108
|
-
conversations: {}
|
|
109
|
-
};
|
|
110
|
-
return value;
|
|
111
|
-
}
|
|
112
|
-
function buildMSTeamsConversationStateKey(conversationId) {
|
|
113
|
-
return node_crypto.default.createHash("sha256").update(conversationId).digest("hex");
|
|
114
|
-
}
|
|
115
|
-
function prepareMSTeamsConversationReferenceForStorage(conversationId, reference) {
|
|
116
|
-
return {
|
|
117
|
-
...reference,
|
|
118
|
-
conversation: {
|
|
119
|
-
...reference.conversation,
|
|
120
|
-
id: conversationId
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
function getStoredConversationId(reference) {
|
|
125
|
-
const rawId = reference.conversation?.id;
|
|
126
|
-
return rawId ? normalizeStoredConversationId(rawId) : null;
|
|
127
|
-
}
|
|
128
|
-
function selectRetainedMSTeamsConversations(conversations, ttlMs = MSTEAMS_CONVERSATION_TTL_MS) {
|
|
129
|
-
const retained = Object.entries(conversations).filter(([, reference]) => {
|
|
130
|
-
const lastSeenAt = (0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(reference.lastSeenAt);
|
|
131
|
-
return lastSeenAt == null || Date.now() - lastSeenAt <= ttlMs;
|
|
132
|
-
});
|
|
133
|
-
if (retained.length <= MSTEAMS_MAX_CONVERSATIONS) return retained;
|
|
134
|
-
retained.sort((a, b) => {
|
|
135
|
-
return ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(a[1].lastSeenAt) ?? 0) - ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(b[1].lastSeenAt) ?? 0) || a[0].localeCompare(b[0]);
|
|
136
|
-
});
|
|
137
|
-
return retained.slice(retained.length - MSTEAMS_MAX_CONVERSATIONS);
|
|
138
|
-
}
|
|
139
|
-
function createMSTeamsConversationStoreState(params) {
|
|
140
|
-
const ttlMs = params?.ttlMs ?? MSTEAMS_CONVERSATION_TTL_MS;
|
|
141
|
-
const conversationStore = createConversationStateStore(params);
|
|
142
|
-
const isExpired = (reference) => {
|
|
143
|
-
const lastSeenAt = (0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(reference.lastSeenAt);
|
|
144
|
-
return lastSeenAt != null && Date.now() - lastSeenAt > ttlMs;
|
|
145
|
-
};
|
|
146
|
-
const lookupStored = async (conversationId) => {
|
|
147
|
-
const normalizedId = normalizeStoredConversationId(conversationId);
|
|
148
|
-
const value = await conversationStore.lookup(buildMSTeamsConversationStateKey(normalizedId));
|
|
149
|
-
if (!value) return null;
|
|
150
|
-
if (isExpired(value)) return null;
|
|
151
|
-
return value;
|
|
152
|
-
};
|
|
153
|
-
const entries = async () => {
|
|
154
|
-
const rows = await conversationStore.entries();
|
|
155
|
-
const kept = [];
|
|
156
|
-
for (const row of rows) {
|
|
157
|
-
if (isExpired(row.value)) continue;
|
|
158
|
-
const conversationId = getStoredConversationId(row.value);
|
|
159
|
-
if (conversationId) kept.push([conversationId, row.value]);
|
|
160
|
-
}
|
|
161
|
-
return kept;
|
|
162
|
-
};
|
|
163
|
-
const lookup = async (conversationId) => {
|
|
164
|
-
return await lookupStored(conversationId);
|
|
165
|
-
};
|
|
166
|
-
const register = async (conversationId, reference) => {
|
|
167
|
-
const normalizedId = normalizeStoredConversationId(conversationId);
|
|
168
|
-
await conversationStore.register(buildMSTeamsConversationStateKey(normalizedId), toPluginJsonValue(prepareMSTeamsConversationReferenceForStorage(normalizedId, reference)));
|
|
169
|
-
const rows = [];
|
|
170
|
-
for (const row of await conversationStore.entries()) {
|
|
171
|
-
if (isExpired(row.value)) {
|
|
172
|
-
await conversationStore.delete(row.key);
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
rows.push(row);
|
|
176
|
-
}
|
|
177
|
-
if (rows.length <= MSTEAMS_MAX_CONVERSATIONS) return;
|
|
178
|
-
const sorted = rows.toSorted((a, b) => {
|
|
179
|
-
const aTs = (0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(a.value.lastSeenAt) ?? 0;
|
|
180
|
-
const bTs = (0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(b.value.lastSeenAt) ?? 0;
|
|
181
|
-
const aId = getStoredConversationId(a.value) ?? a.key;
|
|
182
|
-
const bId = getStoredConversationId(b.value) ?? b.key;
|
|
183
|
-
return aTs - bTs || aId.localeCompare(bId);
|
|
184
|
-
});
|
|
185
|
-
for (const row of sorted.slice(0, rows.length - MSTEAMS_MAX_CONVERSATIONS)) await conversationStore.delete(row.key);
|
|
186
|
-
};
|
|
187
|
-
const list = async () => {
|
|
188
|
-
return toConversationStoreEntries(await entries());
|
|
189
|
-
};
|
|
190
|
-
const get = async (conversationId) => {
|
|
191
|
-
return await lookup(conversationId);
|
|
192
|
-
};
|
|
193
|
-
const findPreferredDmByUserId = async (id) => {
|
|
194
|
-
return findPreferredDmConversationByUserId(await list(), id);
|
|
195
|
-
};
|
|
196
|
-
const upsert = async (conversationId, reference) => {
|
|
197
|
-
const normalizedId = normalizeStoredConversationId(conversationId);
|
|
198
|
-
await withMSTeamsSqliteMutationLock(params, CONVERSATION_MUTATION_KEY, async () => {
|
|
199
|
-
const existing = await lookupStored(normalizedId);
|
|
200
|
-
await register(normalizedId, mergeStoredConversationReference(existing ?? void 0, reference, (/* @__PURE__ */ new Date()).toISOString()));
|
|
201
|
-
});
|
|
202
|
-
};
|
|
203
|
-
const remove = async (conversationId) => {
|
|
204
|
-
const normalizedId = normalizeStoredConversationId(conversationId);
|
|
205
|
-
return await withMSTeamsSqliteMutationLock(params, CONVERSATION_MUTATION_KEY, async () => {
|
|
206
|
-
return await conversationStore.delete(buildMSTeamsConversationStateKey(normalizedId));
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
return {
|
|
210
|
-
upsert,
|
|
211
|
-
get,
|
|
212
|
-
list,
|
|
213
|
-
remove,
|
|
214
|
-
findPreferredDmByUserId
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region extensions/msteams/src/polls.ts
|
|
219
|
-
const MSTEAMS_POLLS_LEGACY_FILENAME = "msteams-polls.json";
|
|
220
|
-
const MSTEAMS_POLLS_NAMESPACE = "polls";
|
|
221
|
-
const MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE = "poll-vote-buckets";
|
|
222
|
-
const MSTEAMS_MAX_POLLS = 1e3;
|
|
223
|
-
const MSTEAMS_SQLITE_MAX_POLL_ROWS = 2e3;
|
|
224
|
-
const MSTEAMS_POLL_VOTE_BUCKET_COUNT = 32;
|
|
225
|
-
const MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS = 1001 * MSTEAMS_POLL_VOTE_BUCKET_COUNT;
|
|
226
|
-
const MSTEAMS_POLL_TTL_MS = 2592e6;
|
|
227
|
-
function normalizeChoiceValue(value) {
|
|
228
|
-
if (typeof value === "string") {
|
|
229
|
-
const trimmed = value.trim();
|
|
230
|
-
return trimmed ? trimmed : null;
|
|
231
|
-
}
|
|
232
|
-
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
function extractSelections(value) {
|
|
236
|
-
if (Array.isArray(value)) return value.map(normalizeChoiceValue).filter((entry) => Boolean(entry));
|
|
237
|
-
const normalized = normalizeChoiceValue(value);
|
|
238
|
-
if (!normalized) return [];
|
|
239
|
-
if (normalized.includes(",")) return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeStringEntries)(normalized.split(","));
|
|
240
|
-
return [normalized];
|
|
241
|
-
}
|
|
242
|
-
function readNestedValue(value, keys) {
|
|
243
|
-
let current = value;
|
|
244
|
-
for (const key of keys) {
|
|
245
|
-
if (!(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(current)) return;
|
|
246
|
-
current = current[key];
|
|
247
|
-
}
|
|
248
|
-
return current;
|
|
249
|
-
}
|
|
250
|
-
function readNestedString(value, keys) {
|
|
251
|
-
return (0, openclaw_plugin_sdk_string_coerce_runtime.normalizeOptionalString)(readNestedValue(value, keys));
|
|
252
|
-
}
|
|
253
|
-
function extractMSTeamsPollVote(activity) {
|
|
254
|
-
const value = activity?.value;
|
|
255
|
-
if (!value || !(0, openclaw_plugin_sdk_string_coerce_runtime.isRecord)(value)) return null;
|
|
256
|
-
const pollId = readNestedString(value, ["openclawPollId"]) ?? readNestedString(value, ["pollId"]) ?? readNestedString(value, ["openclaw", "pollId"]) ?? readNestedString(value, [
|
|
257
|
-
"openclaw",
|
|
258
|
-
"poll",
|
|
259
|
-
"id"
|
|
260
|
-
]) ?? readNestedString(value, ["data", "openclawPollId"]) ?? readNestedString(value, ["data", "pollId"]) ?? readNestedString(value, [
|
|
261
|
-
"data",
|
|
262
|
-
"openclaw",
|
|
263
|
-
"pollId"
|
|
264
|
-
]) ?? readNestedString(value, [
|
|
265
|
-
"action",
|
|
266
|
-
"data",
|
|
267
|
-
"openclawPollId"
|
|
268
|
-
]) ?? readNestedString(value, [
|
|
269
|
-
"action",
|
|
270
|
-
"data",
|
|
271
|
-
"pollId"
|
|
272
|
-
]);
|
|
273
|
-
if (!pollId) return null;
|
|
274
|
-
const directSelections = extractSelections(value.choices);
|
|
275
|
-
const nestedSelections = extractSelections(readNestedValue(value, ["choices"]));
|
|
276
|
-
const dataSelections = extractSelections(readNestedValue(value, ["data", "choices"]));
|
|
277
|
-
const actionDataSelections = extractSelections(readNestedValue(value, [
|
|
278
|
-
"action",
|
|
279
|
-
"data",
|
|
280
|
-
"choices"
|
|
281
|
-
]));
|
|
282
|
-
const selections = directSelections.length > 0 ? directSelections : nestedSelections.length > 0 ? nestedSelections : dataSelections.length > 0 ? dataSelections : actionDataSelections;
|
|
283
|
-
if (selections.length === 0) return null;
|
|
284
|
-
return {
|
|
285
|
-
pollId,
|
|
286
|
-
selections
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
function buildMSTeamsPollCard(params) {
|
|
290
|
-
const pollId = params.pollId ?? node_crypto.default.randomUUID();
|
|
291
|
-
const maxSelections = typeof params.maxSelections === "number" && params.maxSelections > 1 ? Math.floor(params.maxSelections) : 1;
|
|
292
|
-
const cappedMaxSelections = Math.min(Math.max(1, maxSelections), params.options.length);
|
|
293
|
-
const choices = params.options.map((option, index) => ({
|
|
294
|
-
title: option,
|
|
295
|
-
value: String(index)
|
|
296
|
-
}));
|
|
297
|
-
const hint = cappedMaxSelections > 1 ? `Select up to ${cappedMaxSelections} option${cappedMaxSelections === 1 ? "" : "s"}.` : "Select one option.";
|
|
298
|
-
const card = {
|
|
299
|
-
type: "AdaptiveCard",
|
|
300
|
-
version: "1.5",
|
|
301
|
-
body: [
|
|
302
|
-
{
|
|
303
|
-
type: "TextBlock",
|
|
304
|
-
text: params.question,
|
|
305
|
-
wrap: true,
|
|
306
|
-
weight: "Bolder",
|
|
307
|
-
size: "Medium"
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
type: "Input.ChoiceSet",
|
|
311
|
-
id: "choices",
|
|
312
|
-
isMultiSelect: cappedMaxSelections > 1,
|
|
313
|
-
style: "expanded",
|
|
314
|
-
choices
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
type: "TextBlock",
|
|
318
|
-
text: hint,
|
|
319
|
-
wrap: true,
|
|
320
|
-
isSubtle: true,
|
|
321
|
-
spacing: "Small"
|
|
322
|
-
}
|
|
323
|
-
],
|
|
324
|
-
actions: [{
|
|
325
|
-
type: "Action.Execute",
|
|
326
|
-
title: "Vote",
|
|
327
|
-
verb: "openclaw.poll.vote",
|
|
328
|
-
data: {
|
|
329
|
-
openclawPollId: pollId,
|
|
330
|
-
pollId
|
|
331
|
-
}
|
|
332
|
-
}]
|
|
333
|
-
};
|
|
334
|
-
const fallbackLines = [`Poll: ${params.question}`, ...params.options.map((option, index) => `${index + 1}. ${option}`)];
|
|
335
|
-
return {
|
|
336
|
-
pollId,
|
|
337
|
-
question: params.question,
|
|
338
|
-
options: params.options,
|
|
339
|
-
maxSelections: cappedMaxSelections,
|
|
340
|
-
card,
|
|
341
|
-
fallbackText: fallbackLines.join("\n")
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
function createPollStateStore(params) {
|
|
345
|
-
return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
|
|
346
|
-
namespace: MSTEAMS_POLLS_NAMESPACE,
|
|
347
|
-
maxEntries: MSTEAMS_SQLITE_MAX_POLL_ROWS,
|
|
348
|
-
env: resolveMSTeamsSqliteStateEnv(params)
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
function createPollVoteBucketStateStore(params) {
|
|
352
|
-
return require_runtime.getMSTeamsRuntime().state.openKeyedStore({
|
|
353
|
-
namespace: MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE,
|
|
354
|
-
maxEntries: MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS,
|
|
355
|
-
env: resolveMSTeamsSqliteStateEnv(params)
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
function pruneExpired(polls) {
|
|
359
|
-
const cutoff = Date.now() - MSTEAMS_POLL_TTL_MS;
|
|
360
|
-
const entries = Object.entries(polls).filter(([, poll]) => {
|
|
361
|
-
return ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(poll.updatedAt ?? poll.createdAt) ?? 0) >= cutoff;
|
|
362
|
-
});
|
|
363
|
-
return Object.fromEntries(entries);
|
|
364
|
-
}
|
|
365
|
-
function selectRetainedMSTeamsPolls(polls) {
|
|
366
|
-
const retained = Object.entries(pruneExpired(polls));
|
|
367
|
-
if (retained.length <= MSTEAMS_MAX_POLLS) return retained;
|
|
368
|
-
retained.sort((a, b) => {
|
|
369
|
-
return ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(a[1].updatedAt ?? a[1].createdAt) ?? 0) - ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(b[1].updatedAt ?? b[1].createdAt) ?? 0) || a[0].localeCompare(b[0]);
|
|
370
|
-
});
|
|
371
|
-
return retained.slice(retained.length - MSTEAMS_MAX_POLLS);
|
|
372
|
-
}
|
|
373
|
-
function normalizeMSTeamsPollSelections(poll, selections) {
|
|
374
|
-
const maxSelections = Math.max(1, poll.maxSelections);
|
|
375
|
-
const mapped = selections.map((entry) => (0, openclaw_plugin_sdk_number_runtime.parseStrictNonNegativeInteger)(entry)).filter((value) => value !== void 0).filter((value) => value >= 0 && value < poll.options.length).map((value) => String(value));
|
|
376
|
-
return (0, openclaw_plugin_sdk_string_coerce_runtime.uniqueStrings)(mapped).slice(0, maxSelections);
|
|
377
|
-
}
|
|
378
|
-
function splitMSTeamsPoll(poll) {
|
|
379
|
-
const { votes, ...metadata } = poll;
|
|
380
|
-
return {
|
|
381
|
-
metadata,
|
|
382
|
-
votes
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
function hashMSTeamsPollVote(pollId, voterId) {
|
|
386
|
-
return node_crypto.default.createHash("sha256").update(pollId).update("\0").update(voterId).digest("hex");
|
|
387
|
-
}
|
|
388
|
-
function buildMSTeamsPollStateKey(pollId) {
|
|
389
|
-
return node_crypto.default.createHash("sha256").update(pollId).digest("hex");
|
|
390
|
-
}
|
|
391
|
-
function selectMSTeamsPollVoteBucket(pollId, voterId) {
|
|
392
|
-
const bucket = Number.parseInt(hashMSTeamsPollVote(pollId, voterId).slice(0, 8), 16);
|
|
393
|
-
return String(bucket % MSTEAMS_POLL_VOTE_BUCKET_COUNT).padStart(4, "0");
|
|
394
|
-
}
|
|
395
|
-
function buildMSTeamsPollVoteBucketKey(pollId, bucket) {
|
|
396
|
-
return `${node_crypto.default.createHash("sha256").update(pollId).digest("hex")}:${bucket}`;
|
|
397
|
-
}
|
|
398
|
-
function createMSTeamsPollStoreState(params) {
|
|
399
|
-
const pollStore = createPollStateStore(params);
|
|
400
|
-
const voteBucketStore = createPollVoteBucketStateStore(params);
|
|
401
|
-
const readPollVotes = async (pollId) => {
|
|
402
|
-
const votes = {};
|
|
403
|
-
for (const row of await voteBucketStore.entries()) if (row.value.pollId === pollId) Object.assign(votes, row.value.votes);
|
|
404
|
-
return votes;
|
|
405
|
-
};
|
|
406
|
-
const deletePollVotes = async (pollId, cachedRows) => {
|
|
407
|
-
for (const row of cachedRows?.values() ?? await voteBucketStore.entries()) if (row.value.pollId === pollId) {
|
|
408
|
-
await voteBucketStore.delete(row.key);
|
|
409
|
-
cachedRows?.delete(row.key);
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
const registerPollVotes = async (pollId, votes, updatedAt) => {
|
|
413
|
-
const buckets = /* @__PURE__ */ new Map();
|
|
414
|
-
for (const [voterId, selections] of Object.entries(votes)) {
|
|
415
|
-
const bucket = selectMSTeamsPollVoteBucket(pollId, voterId);
|
|
416
|
-
const bucketVotes = buckets.get(bucket) ?? {};
|
|
417
|
-
bucketVotes[voterId] = selections;
|
|
418
|
-
buckets.set(bucket, bucketVotes);
|
|
419
|
-
}
|
|
420
|
-
for (const [bucket, bucketVotes] of buckets) {
|
|
421
|
-
const key = buildMSTeamsPollVoteBucketKey(pollId, bucket);
|
|
422
|
-
const existing = await voteBucketStore.lookup(key);
|
|
423
|
-
await voteBucketStore.register(key, toPluginJsonValue({
|
|
424
|
-
pollId,
|
|
425
|
-
bucket,
|
|
426
|
-
votes: {
|
|
427
|
-
...bucketVotes,
|
|
428
|
-
...existing?.votes
|
|
429
|
-
},
|
|
430
|
-
updatedAt
|
|
431
|
-
}));
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
const registerPollVote = async (pollId, voterId, selections, updatedAt) => {
|
|
435
|
-
const bucket = selectMSTeamsPollVoteBucket(pollId, voterId);
|
|
436
|
-
const key = buildMSTeamsPollVoteBucketKey(pollId, bucket);
|
|
437
|
-
const existing = await voteBucketStore.lookup(key);
|
|
438
|
-
await voteBucketStore.register(key, toPluginJsonValue({
|
|
439
|
-
pollId,
|
|
440
|
-
bucket,
|
|
441
|
-
votes: {
|
|
442
|
-
...existing?.votes,
|
|
443
|
-
[voterId]: selections
|
|
444
|
-
},
|
|
445
|
-
updatedAt
|
|
446
|
-
}));
|
|
447
|
-
};
|
|
448
|
-
const reconstructPoll = async (metadata) => {
|
|
449
|
-
return {
|
|
450
|
-
...metadata,
|
|
451
|
-
votes: await readPollVotes(metadata.id)
|
|
452
|
-
};
|
|
453
|
-
};
|
|
454
|
-
const prunePollStoreToLimit = async () => {
|
|
455
|
-
let voteRows;
|
|
456
|
-
const deletePrunedPollVotes = async (pollId) => {
|
|
457
|
-
voteRows ??= new Map((await voteBucketStore.entries()).map((row) => [row.key, row]));
|
|
458
|
-
await deletePollVotes(pollId, voteRows);
|
|
459
|
-
};
|
|
460
|
-
const rows = [];
|
|
461
|
-
for (const row of await pollStore.entries()) {
|
|
462
|
-
if (!pruneExpired({ [row.key]: row.value })[row.key]) {
|
|
463
|
-
await pollStore.delete(row.key);
|
|
464
|
-
await deletePrunedPollVotes(row.value.id);
|
|
465
|
-
continue;
|
|
466
|
-
}
|
|
467
|
-
rows.push(row);
|
|
468
|
-
}
|
|
469
|
-
if (rows.length <= MSTEAMS_MAX_POLLS) return;
|
|
470
|
-
const sorted = rows.toSorted((a, b) => {
|
|
471
|
-
return ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(a.value.updatedAt ?? a.value.createdAt) ?? 0) - ((0, openclaw_plugin_sdk_number_runtime.parseDateStringTimestampMs)(b.value.updatedAt ?? b.value.createdAt) ?? 0) || a.key.localeCompare(b.key);
|
|
472
|
-
});
|
|
473
|
-
for (const row of sorted.slice(0, rows.length - MSTEAMS_MAX_POLLS)) {
|
|
474
|
-
await pollStore.delete(row.key);
|
|
475
|
-
await deletePrunedPollVotes(row.value.id);
|
|
476
|
-
}
|
|
477
|
-
};
|
|
478
|
-
const createPoll = async (poll) => {
|
|
479
|
-
await withMSTeamsSqliteMutationLock(params, MSTEAMS_POLLS_NAMESPACE, async () => {
|
|
480
|
-
const { metadata, votes } = splitMSTeamsPoll(poll);
|
|
481
|
-
await pollStore.register(buildMSTeamsPollStateKey(poll.id), toPluginJsonValue(metadata));
|
|
482
|
-
await deletePollVotes(poll.id);
|
|
483
|
-
await registerPollVotes(poll.id, votes, poll.updatedAt ?? poll.createdAt);
|
|
484
|
-
await prunePollStoreToLimit();
|
|
485
|
-
});
|
|
486
|
-
};
|
|
487
|
-
const getPoll = async (pollId) => {
|
|
488
|
-
const poll = await pollStore.lookup(buildMSTeamsPollStateKey(pollId));
|
|
489
|
-
if (!poll) return null;
|
|
490
|
-
if (!pruneExpired({ [pollId]: poll })[pollId]) return null;
|
|
491
|
-
return await reconstructPoll(poll);
|
|
492
|
-
};
|
|
493
|
-
const recordVote = async (vote) => {
|
|
494
|
-
return await withMSTeamsSqliteMutationLock(params, MSTEAMS_POLLS_NAMESPACE, async () => {
|
|
495
|
-
const pollKey = buildMSTeamsPollStateKey(vote.pollId);
|
|
496
|
-
const poll = await pollStore.lookup(pollKey);
|
|
497
|
-
if (!poll) return null;
|
|
498
|
-
if (!pruneExpired({ [vote.pollId]: poll })[vote.pollId]) {
|
|
499
|
-
await pollStore.delete(pollKey);
|
|
500
|
-
await deletePollVotes(vote.pollId);
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
503
|
-
const normalized = normalizeMSTeamsPollSelections(await reconstructPoll(poll), vote.selections);
|
|
504
|
-
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
505
|
-
poll.updatedAt = updatedAt;
|
|
506
|
-
await pollStore.register(pollKey, toPluginJsonValue(poll));
|
|
507
|
-
await registerPollVote(vote.pollId, vote.voterId, normalized, updatedAt);
|
|
508
|
-
await prunePollStoreToLimit();
|
|
509
|
-
return await reconstructPoll(poll);
|
|
510
|
-
});
|
|
511
|
-
};
|
|
512
|
-
return {
|
|
513
|
-
createPoll,
|
|
514
|
-
getPoll,
|
|
515
|
-
recordVote
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
//#endregion
|
|
519
|
-
Object.defineProperty(exports, "MSTEAMS_CONVERSATIONS_LEGACY_FILENAME", {
|
|
520
|
-
enumerable: true,
|
|
521
|
-
get: function() {
|
|
522
|
-
return MSTEAMS_CONVERSATIONS_LEGACY_FILENAME;
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
Object.defineProperty(exports, "MSTEAMS_CONVERSATIONS_NAMESPACE", {
|
|
526
|
-
enumerable: true,
|
|
527
|
-
get: function() {
|
|
528
|
-
return MSTEAMS_CONVERSATIONS_NAMESPACE;
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
Object.defineProperty(exports, "MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS", {
|
|
532
|
-
enumerable: true,
|
|
533
|
-
get: function() {
|
|
534
|
-
return MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS;
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
Object.defineProperty(exports, "MSTEAMS_POLLS_LEGACY_FILENAME", {
|
|
538
|
-
enumerable: true,
|
|
539
|
-
get: function() {
|
|
540
|
-
return MSTEAMS_POLLS_LEGACY_FILENAME;
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
Object.defineProperty(exports, "MSTEAMS_POLLS_NAMESPACE", {
|
|
544
|
-
enumerable: true,
|
|
545
|
-
get: function() {
|
|
546
|
-
return MSTEAMS_POLLS_NAMESPACE;
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
Object.defineProperty(exports, "MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE", {
|
|
550
|
-
enumerable: true,
|
|
551
|
-
get: function() {
|
|
552
|
-
return MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE;
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
Object.defineProperty(exports, "MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS", {
|
|
556
|
-
enumerable: true,
|
|
557
|
-
get: function() {
|
|
558
|
-
return MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS;
|
|
559
|
-
}
|
|
560
|
-
});
|
|
561
|
-
Object.defineProperty(exports, "MSTEAMS_SQLITE_MAX_POLL_ROWS", {
|
|
562
|
-
enumerable: true,
|
|
563
|
-
get: function() {
|
|
564
|
-
return MSTEAMS_SQLITE_MAX_POLL_ROWS;
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
Object.defineProperty(exports, "buildMSTeamsConversationStateKey", {
|
|
568
|
-
enumerable: true,
|
|
569
|
-
get: function() {
|
|
570
|
-
return buildMSTeamsConversationStateKey;
|
|
571
|
-
}
|
|
572
|
-
});
|
|
573
|
-
Object.defineProperty(exports, "buildMSTeamsPollCard", {
|
|
574
|
-
enumerable: true,
|
|
575
|
-
get: function() {
|
|
576
|
-
return buildMSTeamsPollCard;
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
Object.defineProperty(exports, "buildMSTeamsPollStateKey", {
|
|
580
|
-
enumerable: true,
|
|
581
|
-
get: function() {
|
|
582
|
-
return buildMSTeamsPollStateKey;
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
|
-
Object.defineProperty(exports, "buildMSTeamsPollVoteBucketKey", {
|
|
586
|
-
enumerable: true,
|
|
587
|
-
get: function() {
|
|
588
|
-
return buildMSTeamsPollVoteBucketKey;
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
Object.defineProperty(exports, "createMSTeamsConversationStoreState", {
|
|
592
|
-
enumerable: true,
|
|
593
|
-
get: function() {
|
|
594
|
-
return createMSTeamsConversationStoreState;
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
Object.defineProperty(exports, "createMSTeamsPollStoreState", {
|
|
598
|
-
enumerable: true,
|
|
599
|
-
get: function() {
|
|
600
|
-
return createMSTeamsPollStoreState;
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
Object.defineProperty(exports, "extractMSTeamsPollVote", {
|
|
604
|
-
enumerable: true,
|
|
605
|
-
get: function() {
|
|
606
|
-
return extractMSTeamsPollVote;
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
Object.defineProperty(exports, "normalizeMSTeamsLegacyConversationStore", {
|
|
610
|
-
enumerable: true,
|
|
611
|
-
get: function() {
|
|
612
|
-
return normalizeMSTeamsLegacyConversationStore;
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
Object.defineProperty(exports, "normalizeStoredConversationId", {
|
|
616
|
-
enumerable: true,
|
|
617
|
-
get: function() {
|
|
618
|
-
return normalizeStoredConversationId;
|
|
619
|
-
}
|
|
620
|
-
});
|
|
621
|
-
Object.defineProperty(exports, "prepareMSTeamsConversationReferenceForStorage", {
|
|
622
|
-
enumerable: true,
|
|
623
|
-
get: function() {
|
|
624
|
-
return prepareMSTeamsConversationReferenceForStorage;
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
Object.defineProperty(exports, "resolveMSTeamsSqliteStateEnv", {
|
|
628
|
-
enumerable: true,
|
|
629
|
-
get: function() {
|
|
630
|
-
return resolveMSTeamsSqliteStateEnv;
|
|
631
|
-
}
|
|
632
|
-
});
|
|
633
|
-
Object.defineProperty(exports, "selectMSTeamsPollVoteBucket", {
|
|
634
|
-
enumerable: true,
|
|
635
|
-
get: function() {
|
|
636
|
-
return selectMSTeamsPollVoteBucket;
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
Object.defineProperty(exports, "selectRetainedMSTeamsConversations", {
|
|
640
|
-
enumerable: true,
|
|
641
|
-
get: function() {
|
|
642
|
-
return selectRetainedMSTeamsConversations;
|
|
643
|
-
}
|
|
644
|
-
});
|
|
645
|
-
Object.defineProperty(exports, "selectRetainedMSTeamsPolls", {
|
|
646
|
-
enumerable: true,
|
|
647
|
-
get: function() {
|
|
648
|
-
return selectRetainedMSTeamsPolls;
|
|
649
|
-
}
|
|
650
|
-
});
|
|
651
|
-
Object.defineProperty(exports, "splitMSTeamsPoll", {
|
|
652
|
-
enumerable: true,
|
|
653
|
-
get: function() {
|
|
654
|
-
return splitMSTeamsPoll;
|
|
655
|
-
}
|
|
656
|
-
});
|
|
657
|
-
Object.defineProperty(exports, "toPluginJsonValue", {
|
|
658
|
-
enumerable: true,
|
|
659
|
-
get: function() {
|
|
660
|
-
return toPluginJsonValue;
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
Object.defineProperty(exports, "withMSTeamsSqliteMutationLock", {
|
|
664
|
-
enumerable: true,
|
|
665
|
-
get: function() {
|
|
666
|
-
return withMSTeamsSqliteMutationLock;
|
|
667
|
-
}
|
|
668
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require("openclaw/plugin-sdk/secret-input");
|