@openclaw/msteams 2026.6.2-beta.1 → 2026.6.5-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +2 -2
- package/dist/{channel-BwNnuHbh.js → channel--oT3fyD5.js} +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-JR5pBsop.js → channel.runtime-KNuY2Oaw.js} +5 -4
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +254 -44
- package/dist/{oauth-CJj-b_Kn.js → oauth-CDUB5xPY.js} +1 -1
- package/dist/polls-C1VgSvKE.js +548 -0
- package/dist/{probe-bq_Uev4c.js → probe-C-rWMb-m.js} +10 -742
- package/dist/{resolve-allowlist-C6VVTfbj.js → resolve-allowlist-BzIUWmMm.js} +3 -2
- package/dist/runtime-BS5AZrKK.js +8 -0
- package/dist/runtime-api.js +19 -1
- package/dist/setup-plugin-api.js +2 -2
- package/dist/{setup-surface-DdyMxq-W.js → setup-surface-Dik4VU7f.js} +2 -2
- package/dist/{src-_wVYF1sz.js → src-CLsoqMj1.js} +9 -124
- package/dist/sso-token-store-BYZaKr82.js +70 -0
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +3 -0
- package/package.json +4 -4
- package/dist/runtime-api-BlvMnDKz.js +0 -26
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as msteamsPlugin } from "./channel
|
|
2
|
-
import { c as msteamsSetupAdapter, n as openDelegatedOAuthUrl, s as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-
|
|
1
|
+
import { t as msteamsPlugin } from "./channel--oT3fyD5.js";
|
|
2
|
+
import { c as msteamsSetupAdapter, n as openDelegatedOAuthUrl, s as createMSTeamsSetupWizardBase, t as msteamsSetupWizard } from "./setup-surface-Dik4VU7f.js";
|
|
3
3
|
export { createMSTeamsSetupWizardBase, msteamsPlugin, msteamsSetupAdapter, msteamsSetupWizard, openDelegatedOAuthUrl };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { C as resolveMSTeamsCredentials, a as parseMSTeamsTeamChannelInput, c as resolveMSTeamsUserAllowlist, i as parseMSTeamsConversationId, n as normalizeMSTeamsMessagingTarget, r as normalizeMSTeamsUserInput, s as resolveMSTeamsChannelAllowlist, t as looksLikeMSTeamsTargetId } from "./resolve-allowlist-
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelKeyCandidates, buildProbeChannelStatusSummary, chunkTextForOutbound, createDefaultChannelRuntimeState, isDangerousNameMatchingEnabled, normalizeChannelSlug, resolveAllowlistMatchSimple, resolveChannelEntryMatchWithFallback, resolveNestedAllowlistDecision, resolveToolsBySender } from "./runtime-api.js";
|
|
2
|
+
import { C as resolveMSTeamsCredentials, a as parseMSTeamsTeamChannelInput, c as resolveMSTeamsUserAllowlist, i as parseMSTeamsConversationId, n as normalizeMSTeamsMessagingTarget, r as normalizeMSTeamsUserInput, s as resolveMSTeamsChannelAllowlist, t as looksLikeMSTeamsTargetId } from "./resolve-allowlist-BzIUWmMm.js";
|
|
3
3
|
import { t as MSTeamsChannelConfigSchema } from "./config-schema-BL4qQZiA.js";
|
|
4
|
-
import { c as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-
|
|
4
|
+
import { c as msteamsSetupAdapter, t as msteamsSetupWizard } from "./setup-surface-Dik4VU7f.js";
|
|
5
5
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
6
6
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
7
7
|
import { createTopLevelChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -331,7 +331,7 @@ const collectMSTeamsSecurityWarnings = createAllowlistProviderGroupPolicyWarning
|
|
|
331
331
|
resolveGroupPolicy: ({ cfg }) => cfg.channels?.msteams?.groupPolicy,
|
|
332
332
|
collect: ({ groupPolicy }) => groupPolicy === "open" ? ["- MS Teams groups: groupPolicy=\"open\" allows any member to trigger (mention-gated). Set channels.msteams.groupPolicy=\"allowlist\" + channels.msteams.groupAllowFrom to restrict senders."] : []
|
|
333
333
|
});
|
|
334
|
-
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
334
|
+
const loadMSTeamsChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-KNuY2Oaw.js"), "msTeamsChannelRuntime");
|
|
335
335
|
const resolveMSTeamsChannelConfig = (cfg) => ({
|
|
336
336
|
allowFrom: cfg.channels?.msteams?.allowFrom,
|
|
337
337
|
defaultTo: cfg.channels?.msteams?.defaultTo
|
|
@@ -1117,7 +1117,7 @@ const msteamsPlugin = createChatChannelPlugin({
|
|
|
1117
1117
|
})
|
|
1118
1118
|
}),
|
|
1119
1119
|
gateway: { startAccount: async (ctx) => {
|
|
1120
|
-
const { monitorMSTeamsProvider } = await import("./src-
|
|
1120
|
+
const { monitorMSTeamsProvider } = await import("./src-CLsoqMj1.js");
|
|
1121
1121
|
const port = ctx.cfg.channels?.msteams?.webhook?.port ?? 3978;
|
|
1122
1122
|
ctx.setStatus({
|
|
1123
1123
|
accountId: ctx.accountId,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as msteamsPlugin } from "./channel
|
|
1
|
+
import { t as msteamsPlugin } from "./channel--oT3fyD5.js";
|
|
2
2
|
export { msteamsPlugin };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as patchGraphJson, b as resolveGraphToken, d as escapeOData, f as fetchGraphAbsoluteUrl, g as normalizeQuery, h as listTeamsByName, l as searchGraphUsers, m as listChannelsForTeam, p as fetchGraphJson, u as deleteGraphRequest, v as postGraphBetaJson, y as postGraphJson } from "./resolve-allowlist-
|
|
3
|
-
import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel
|
|
4
|
-
import {
|
|
1
|
+
import { chunkTextForOutbound, normalizeStringEntries as normalizeStringEntries$1 } from "./runtime-api.js";
|
|
2
|
+
import { _ as patchGraphJson, b as resolveGraphToken, d as escapeOData, f as fetchGraphAbsoluteUrl, g as normalizeQuery, h as listTeamsByName, l as searchGraphUsers, m as listChannelsForTeam, p as fetchGraphJson, u as deleteGraphRequest, v as postGraphBetaJson, y as postGraphJson } from "./resolve-allowlist-BzIUWmMm.js";
|
|
3
|
+
import { n as MSTEAMS_PRESENTATION_CAPABILITIES, r as buildMSTeamsPresentationCard } from "./channel--oT3fyD5.js";
|
|
4
|
+
import { l as createMSTeamsPollStoreState, v as createMSTeamsConversationStoreState } from "./polls-C1VgSvKE.js";
|
|
5
|
+
import { a as sendMessageMSTeams, i as sendAdaptiveCardMSTeams, n as deleteMessageMSTeams, o as sendPollMSTeams, r as editMessageMSTeams, t as probeMSTeams } from "./probe-C-rWMb-m.js";
|
|
5
6
|
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound";
|
|
6
7
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
8
|
import { resolvePayloadMediaUrls, resolveTextChunksWithFallback, sendPayloadMediaSequence } from "openclaw/plugin-sdk/reply-payload";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as resolveMSTeamsCredentials, n as normalizeMSTeamsMessagingTarget } from "./resolve-allowlist-
|
|
1
|
+
import { C as resolveMSTeamsCredentials, n as normalizeMSTeamsMessagingTarget } from "./resolve-allowlist-BzIUWmMm.js";
|
|
2
2
|
import { listDirectoryEntriesFromSources } from "openclaw/plugin-sdk/directory-runtime";
|
|
3
3
|
const msteamsDirectoryContractPlugin = {
|
|
4
4
|
id: "msteams",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { T as normalizeStoredConversationId, _ as buildMSTeamsConversationStateKey, a as MSTEAMS_SQLITE_MAX_POLL_ROWS, b as prepareMSTeamsConversationReferenceForStorage, c as buildMSTeamsPollVoteBucketKey, d as selectMSTeamsPollVoteBucket, f as selectRetainedMSTeamsPolls, g as MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS, h as MSTEAMS_CONVERSATIONS_NAMESPACE, i as MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE, m as MSTEAMS_CONVERSATIONS_LEGACY_FILENAME, n as MSTEAMS_POLLS_LEGACY_FILENAME, p as splitMSTeamsPoll, r as MSTEAMS_POLLS_NAMESPACE, s as buildMSTeamsPollStateKey, t as MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS, x as selectRetainedMSTeamsConversations, y as normalizeMSTeamsLegacyConversationStore } from "./polls-C1VgSvKE.js";
|
|
2
|
+
import { a as isMSTeamsSsoStoreData, n as MSTEAMS_SSO_TOKENS_LEGACY_FILENAME, o as makeMSTeamsSsoTokenStoreKey, r as MSTEAMS_SSO_TOKENS_NAMESPACE, s as normalizeMSTeamsSsoStoredToken, t as MSTEAMS_MAX_SSO_TOKENS } from "./sso-token-store-BYZaKr82.js";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import crypto from "node:crypto";
|
|
3
5
|
import fs from "node:fs/promises";
|
|
@@ -5,6 +7,7 @@ import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
|
5
7
|
//#region extensions/msteams/doctor-contract-api.ts
|
|
6
8
|
const LEARNINGS_NAMESPACE = "feedback-learnings";
|
|
7
9
|
const MAX_LEARNING_ENTRIES = 1e4;
|
|
10
|
+
const MSTEAMS_PLUGIN_ID = "Microsoft Teams";
|
|
8
11
|
function encodeSessionKey(sessionKey) {
|
|
9
12
|
return Buffer.from(sessionKey, "utf8").toString("base64url");
|
|
10
13
|
}
|
|
@@ -60,6 +63,59 @@ async function fileExists(filePath) {
|
|
|
60
63
|
return false;
|
|
61
64
|
}
|
|
62
65
|
}
|
|
66
|
+
function resolveStateFilePath(stateDir, filename) {
|
|
67
|
+
return path.join(stateDir, filename);
|
|
68
|
+
}
|
|
69
|
+
async function readLegacyJsonFile(filePath, parse) {
|
|
70
|
+
try {
|
|
71
|
+
return parse(JSON.parse(await fs.readFile(filePath, "utf8")));
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function isRecord(value) {
|
|
77
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
78
|
+
}
|
|
79
|
+
function isStringArray(value) {
|
|
80
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
81
|
+
}
|
|
82
|
+
function parseLegacyConversationStore(value) {
|
|
83
|
+
if (!isRecord(value) || value.version !== 1 || !isRecord(value.conversations)) return null;
|
|
84
|
+
return normalizeMSTeamsLegacyConversationStore({
|
|
85
|
+
version: 1,
|
|
86
|
+
conversations: value.conversations
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function parseLegacyPoll(value) {
|
|
90
|
+
if (!isRecord(value)) return null;
|
|
91
|
+
const votes = isRecord(value.votes) ? value.votes : null;
|
|
92
|
+
if (typeof value.id !== "string" || !value.id || typeof value.question !== "string" || !value.question || !isStringArray(value.options) || typeof value.maxSelections !== "number" || !Number.isFinite(value.maxSelections) || typeof value.createdAt !== "string" || !votes) return null;
|
|
93
|
+
const normalizedVotes = {};
|
|
94
|
+
for (const [voterId, selections] of Object.entries(votes)) if (typeof voterId === "string" && isStringArray(selections)) normalizedVotes[voterId] = selections;
|
|
95
|
+
return {
|
|
96
|
+
id: value.id,
|
|
97
|
+
question: value.question,
|
|
98
|
+
options: value.options,
|
|
99
|
+
maxSelections: value.maxSelections,
|
|
100
|
+
createdAt: value.createdAt,
|
|
101
|
+
...typeof value.updatedAt === "string" ? { updatedAt: value.updatedAt } : {},
|
|
102
|
+
...typeof value.conversationId === "string" ? { conversationId: value.conversationId } : {},
|
|
103
|
+
...typeof value.messageId === "string" ? { messageId: value.messageId } : {},
|
|
104
|
+
votes: normalizedVotes
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function parseLegacyPollStore(value) {
|
|
108
|
+
if (!isRecord(value) || value.version !== 1 || !isRecord(value.polls)) return null;
|
|
109
|
+
const polls = {};
|
|
110
|
+
for (const [pollId, poll] of Object.entries(value.polls)) {
|
|
111
|
+
const parsed = parseLegacyPoll(poll);
|
|
112
|
+
if (parsed) polls[pollId] = parsed;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
version: 1,
|
|
116
|
+
polls
|
|
117
|
+
};
|
|
118
|
+
}
|
|
63
119
|
async function listLegacyLearningFiles(storePath) {
|
|
64
120
|
let entries;
|
|
65
121
|
try {
|
|
@@ -92,15 +148,16 @@ async function listLegacyLearningFiles(storePath) {
|
|
|
92
148
|
}
|
|
93
149
|
async function archiveLegacySource(params) {
|
|
94
150
|
const archivedPath = `${params.filePath}.migrated`;
|
|
151
|
+
const label = params.label ?? "Microsoft Teams feedback-learning";
|
|
95
152
|
if (await fileExists(archivedPath)) {
|
|
96
|
-
params.warnings.push(`Left migrated
|
|
153
|
+
params.warnings.push(`Left migrated ${label} source in place because ${archivedPath} already exists`);
|
|
97
154
|
return;
|
|
98
155
|
}
|
|
99
156
|
try {
|
|
100
157
|
await fs.rename(params.filePath, archivedPath);
|
|
101
|
-
params.changes.push(`Archived
|
|
158
|
+
params.changes.push(`Archived ${label} legacy source -> ${archivedPath}`);
|
|
102
159
|
} catch (err) {
|
|
103
|
-
params.warnings.push(`Failed archiving
|
|
160
|
+
params.warnings.push(`Failed archiving ${label} legacy source: ${String(err)}`);
|
|
104
161
|
}
|
|
105
162
|
}
|
|
106
163
|
function mergeLearnings(legacy, existing) {
|
|
@@ -113,59 +170,212 @@ function mergeLearnings(legacy, existing) {
|
|
|
113
170
|
}
|
|
114
171
|
return merged.slice(-10);
|
|
115
172
|
}
|
|
116
|
-
const stateMigrations = [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
173
|
+
const stateMigrations = [
|
|
174
|
+
{
|
|
175
|
+
id: "msteams-conversations-json-to-plugin-state",
|
|
176
|
+
label: "Microsoft Teams conversations",
|
|
177
|
+
async detectLegacyState(params) {
|
|
178
|
+
const state = await readLegacyJsonFile(resolveStateFilePath(params.stateDir, MSTEAMS_CONVERSATIONS_LEGACY_FILENAME), parseLegacyConversationStore);
|
|
179
|
+
if (!state || Object.keys(state.conversations).length === 0) return null;
|
|
180
|
+
return { preview: [`- ${MSTEAMS_PLUGIN_ID} conversations: ${Object.keys(state.conversations).length} entries -> plugin state (${MSTEAMS_CONVERSATIONS_NAMESPACE})`] };
|
|
181
|
+
},
|
|
182
|
+
async migrateLegacyState(params) {
|
|
183
|
+
const changes = [];
|
|
184
|
+
const warnings = [];
|
|
185
|
+
const filePath = resolveStateFilePath(params.stateDir, MSTEAMS_CONVERSATIONS_LEGACY_FILENAME);
|
|
186
|
+
const state = await readLegacyJsonFile(filePath, parseLegacyConversationStore);
|
|
187
|
+
if (!state) return {
|
|
188
|
+
changes,
|
|
189
|
+
warnings
|
|
190
|
+
};
|
|
191
|
+
const store = params.context.openPluginStateKeyedStore({
|
|
192
|
+
namespace: MSTEAMS_CONVERSATIONS_NAMESPACE,
|
|
193
|
+
maxEntries: MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS
|
|
194
|
+
});
|
|
195
|
+
let imported = 0;
|
|
196
|
+
for (const [rawConversationId, reference] of selectRetainedMSTeamsConversations(state.conversations)) {
|
|
197
|
+
const conversationId = normalizeStoredConversationId(rawConversationId);
|
|
198
|
+
if (!conversationId) continue;
|
|
199
|
+
if (await store.registerIfAbsent(buildMSTeamsConversationStateKey(conversationId), prepareMSTeamsConversationReferenceForStorage(conversationId, reference))) imported++;
|
|
200
|
+
}
|
|
201
|
+
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} conversation ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
202
|
+
await archiveLegacySource({
|
|
203
|
+
filePath,
|
|
204
|
+
label: `${MSTEAMS_PLUGIN_ID} conversation`,
|
|
205
|
+
changes,
|
|
206
|
+
warnings
|
|
207
|
+
});
|
|
138
208
|
return {
|
|
139
209
|
changes,
|
|
140
210
|
warnings
|
|
141
211
|
};
|
|
142
212
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
id: "msteams-polls-json-to-plugin-state",
|
|
216
|
+
label: "Microsoft Teams polls",
|
|
217
|
+
async detectLegacyState(params) {
|
|
218
|
+
const state = await readLegacyJsonFile(resolveStateFilePath(params.stateDir, MSTEAMS_POLLS_LEGACY_FILENAME), parseLegacyPollStore);
|
|
219
|
+
if (!state || Object.keys(state.polls).length === 0) return null;
|
|
220
|
+
return { preview: [`- ${MSTEAMS_PLUGIN_ID} polls: ${Object.keys(state.polls).length} entries -> plugin state (${MSTEAMS_POLLS_NAMESPACE})`] };
|
|
221
|
+
},
|
|
222
|
+
async migrateLegacyState(params) {
|
|
223
|
+
const changes = [];
|
|
224
|
+
const warnings = [];
|
|
225
|
+
const filePath = resolveStateFilePath(params.stateDir, MSTEAMS_POLLS_LEGACY_FILENAME);
|
|
226
|
+
const state = await readLegacyJsonFile(filePath, parseLegacyPollStore);
|
|
227
|
+
if (!state) return {
|
|
228
|
+
changes,
|
|
229
|
+
warnings
|
|
230
|
+
};
|
|
231
|
+
const pollStore = params.context.openPluginStateKeyedStore({
|
|
232
|
+
namespace: MSTEAMS_POLLS_NAMESPACE,
|
|
233
|
+
maxEntries: MSTEAMS_SQLITE_MAX_POLL_ROWS
|
|
234
|
+
});
|
|
235
|
+
const voteBucketStore = params.context.openPluginStateKeyedStore({
|
|
236
|
+
namespace: MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE,
|
|
237
|
+
maxEntries: MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS
|
|
238
|
+
});
|
|
239
|
+
let imported = 0;
|
|
240
|
+
for (const [pollId, poll] of selectRetainedMSTeamsPolls(state.polls)) {
|
|
241
|
+
const { metadata, votes } = splitMSTeamsPoll(poll);
|
|
242
|
+
const didImportPoll = await pollStore.registerIfAbsent(buildMSTeamsPollStateKey(pollId), metadata);
|
|
243
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
244
|
+
for (const [voterId, selections] of Object.entries(votes)) {
|
|
245
|
+
const bucket = selectMSTeamsPollVoteBucket(pollId, voterId);
|
|
246
|
+
const bucketVotes = buckets.get(bucket) ?? {};
|
|
247
|
+
bucketVotes[voterId] = selections;
|
|
248
|
+
buckets.set(bucket, bucketVotes);
|
|
249
|
+
}
|
|
250
|
+
let importedVoteBucket = false;
|
|
251
|
+
for (const [bucket, bucketVotes] of buckets) {
|
|
252
|
+
const key = buildMSTeamsPollVoteBucketKey(pollId, bucket);
|
|
253
|
+
const existing = await voteBucketStore.lookup(key);
|
|
254
|
+
await voteBucketStore.register(key, {
|
|
255
|
+
pollId,
|
|
256
|
+
bucket,
|
|
257
|
+
votes: {
|
|
258
|
+
...bucketVotes,
|
|
259
|
+
...existing?.votes
|
|
260
|
+
},
|
|
261
|
+
updatedAt: poll.updatedAt ?? poll.createdAt
|
|
262
|
+
});
|
|
263
|
+
importedVoteBucket = true;
|
|
264
|
+
}
|
|
265
|
+
if (didImportPoll || importedVoteBucket) imported++;
|
|
148
266
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
267
|
+
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} poll ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
268
|
+
await archiveLegacySource({
|
|
269
|
+
filePath,
|
|
270
|
+
label: `${MSTEAMS_PLUGIN_ID} poll`,
|
|
271
|
+
changes,
|
|
272
|
+
warnings
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
changes,
|
|
276
|
+
warnings
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: "msteams-sso-tokens-json-to-plugin-state",
|
|
282
|
+
label: "Microsoft Teams SSO tokens",
|
|
283
|
+
async detectLegacyState(params) {
|
|
284
|
+
const state = await readLegacyJsonFile(resolveStateFilePath(params.stateDir, MSTEAMS_SSO_TOKENS_LEGACY_FILENAME), (value) => isMSTeamsSsoStoreData(value) ? value : null);
|
|
285
|
+
if (!state || Object.keys(state.tokens).length === 0) return null;
|
|
286
|
+
return { preview: [`- ${MSTEAMS_PLUGIN_ID} SSO tokens: ${Object.keys(state.tokens).length} entries -> plugin state (${MSTEAMS_SSO_TOKENS_NAMESPACE})`] };
|
|
287
|
+
},
|
|
288
|
+
async migrateLegacyState(params) {
|
|
289
|
+
const changes = [];
|
|
290
|
+
const warnings = [];
|
|
291
|
+
const filePath = resolveStateFilePath(params.stateDir, MSTEAMS_SSO_TOKENS_LEGACY_FILENAME);
|
|
292
|
+
const state = await readLegacyJsonFile(filePath, (value) => isMSTeamsSsoStoreData(value) ? value : null);
|
|
293
|
+
if (!state) return {
|
|
294
|
+
changes,
|
|
295
|
+
warnings
|
|
296
|
+
};
|
|
297
|
+
const store = params.context.openPluginStateKeyedStore({
|
|
298
|
+
namespace: MSTEAMS_SSO_TOKENS_NAMESPACE,
|
|
299
|
+
maxEntries: MSTEAMS_MAX_SSO_TOKENS
|
|
155
300
|
});
|
|
156
|
-
imported
|
|
301
|
+
let imported = 0;
|
|
302
|
+
let skipped = 0;
|
|
303
|
+
for (const token of Object.values(state.tokens)) {
|
|
304
|
+
const normalized = normalizeMSTeamsSsoStoredToken(token);
|
|
305
|
+
if (!normalized) {
|
|
306
|
+
skipped++;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (await store.registerIfAbsent(makeMSTeamsSsoTokenStoreKey(normalized.connectionName, normalized.userId), normalized)) imported++;
|
|
310
|
+
}
|
|
311
|
+
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} SSO token ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
312
|
+
if (skipped > 0) warnings.push(`Skipped ${skipped} malformed ${MSTEAMS_PLUGIN_ID} SSO token ${skipped === 1 ? "entry" : "entries"} during migration`);
|
|
157
313
|
await archiveLegacySource({
|
|
158
|
-
filePath
|
|
314
|
+
filePath,
|
|
315
|
+
label: `${MSTEAMS_PLUGIN_ID} SSO-token`,
|
|
316
|
+
changes,
|
|
317
|
+
warnings
|
|
318
|
+
});
|
|
319
|
+
return {
|
|
159
320
|
changes,
|
|
160
321
|
warnings
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: "msteams-feedback-learnings-json-to-plugin-state",
|
|
327
|
+
label: "Microsoft Teams feedback learnings",
|
|
328
|
+
async detectLegacyState(params) {
|
|
329
|
+
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
330
|
+
if (files.length === 0) return null;
|
|
331
|
+
return { preview: [`- Microsoft Teams feedback learnings: ${files.length} ${files.length === 1 ? "file" : "files"} -> plugin state (${LEARNINGS_NAMESPACE})`] };
|
|
332
|
+
},
|
|
333
|
+
async migrateLegacyState(params) {
|
|
334
|
+
const changes = [];
|
|
335
|
+
const warnings = [];
|
|
336
|
+
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
337
|
+
const store = params.context.openPluginStateKeyedStore({
|
|
338
|
+
namespace: LEARNINGS_NAMESPACE,
|
|
339
|
+
maxEntries: MAX_LEARNING_ENTRIES
|
|
161
340
|
});
|
|
341
|
+
const existingEntries = await store.entries();
|
|
342
|
+
const existingKeys = new Set(existingEntries.map((entry) => entry.key));
|
|
343
|
+
const importableFiles = files.filter((file) => file.sessionKey);
|
|
344
|
+
const missingKeys = new Set(importableFiles.map((file) => learningStoreKey(file.storePath, file.sessionKey ?? "")).filter((key) => !existingKeys.has(key)));
|
|
345
|
+
if (missingKeys.size > MAX_LEARNING_ENTRIES - existingKeys.size) {
|
|
346
|
+
warnings.push(`Skipped Microsoft Teams feedback-learning migration because plugin state has room for ${MAX_LEARNING_ENTRIES - existingKeys.size} of ${missingKeys.size} missing entries; left legacy sources in place`);
|
|
347
|
+
return {
|
|
348
|
+
changes,
|
|
349
|
+
warnings
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
let imported = 0;
|
|
353
|
+
for (const file of files) {
|
|
354
|
+
if (!file.sessionKey) {
|
|
355
|
+
warnings.push(`Left Microsoft Teams feedback-learning source in place because its legacy filename cannot be mapped to a session key: ${file.filePath}`);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const key = learningStoreKey(file.storePath, file.sessionKey);
|
|
359
|
+
const existing = await store.lookup(key);
|
|
360
|
+
await store.register(key, {
|
|
361
|
+
sessionKey: existing?.sessionKey ?? file.sessionKey,
|
|
362
|
+
learnings: mergeLearnings(file.learnings, existing),
|
|
363
|
+
updatedAt: Date.now()
|
|
364
|
+
});
|
|
365
|
+
imported++;
|
|
366
|
+
await archiveLegacySource({
|
|
367
|
+
filePath: file.filePath,
|
|
368
|
+
changes,
|
|
369
|
+
warnings
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
if (imported > 0) changes.unshift(`Migrated ${imported} Microsoft Teams feedback-learning ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
373
|
+
return {
|
|
374
|
+
changes,
|
|
375
|
+
warnings
|
|
376
|
+
};
|
|
162
377
|
}
|
|
163
|
-
if (imported > 0) changes.unshift(`Migrated ${imported} Microsoft Teams feedback-learning ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
164
|
-
return {
|
|
165
|
-
changes,
|
|
166
|
-
warnings
|
|
167
|
-
};
|
|
168
378
|
}
|
|
169
|
-
|
|
379
|
+
];
|
|
170
380
|
//#endregion
|
|
171
381
|
export { stateMigrations };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as MSTEAMS_OAUTH_REDIRECT_URI, D as MSTEAMS_DEFAULT_DELEGATED_SCOPES, E as exchangeMSTeamsCodeForTokens, O as MSTEAMS_OAUTH_CALLBACK_PATH, j as buildMSTeamsAuthEndpoint, k as MSTEAMS_OAUTH_CALLBACK_PORT } from "./resolve-allowlist-BzIUWmMm.js";
|
|
2
2
|
import { generateHexPkceVerifierChallenge } from "openclaw/plugin-sdk/provider-auth";
|
|
3
3
|
import { generateOAuthState, parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
4
4
|
import { isWSL2Sync } from "openclaw/plugin-sdk/runtime-env";
|