@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
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
1
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CWbvAW4v.cjs");
|
|
2
|
+
require("./secret-input-C65t6kjM.cjs");
|
|
3
|
+
const require_config_schema = require("./config-schema-MyN2lamA.cjs");
|
|
2
4
|
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
3
|
-
let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
|
|
4
5
|
let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
|
|
6
|
+
let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
|
|
7
|
+
let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
|
|
5
8
|
let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
|
|
6
9
|
let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
|
|
10
|
+
let openclaw_plugin_sdk_secret_file_runtime = require("openclaw/plugin-sdk/secret-file-runtime");
|
|
7
11
|
let openclaw_plugin_sdk_channel_setup = require("openclaw/plugin-sdk/channel-setup");
|
|
8
12
|
let openclaw_plugin_sdk_setup = require("openclaw/plugin-sdk/setup");
|
|
9
13
|
let openclaw_plugin_sdk_setup_tools = require("openclaw/plugin-sdk/setup-tools");
|
|
@@ -20,13 +24,23 @@ const msteamsMeta = {
|
|
|
20
24
|
aliases: ["teams"],
|
|
21
25
|
order: 60
|
|
22
26
|
};
|
|
27
|
+
function resolveMSTeamsAccount(cfg) {
|
|
28
|
+
const config = cfg.channels?.msteams;
|
|
29
|
+
const credentials = require_resolve_allowlist.resolveMSTeamsCredentials(config);
|
|
30
|
+
const certificatePath = credentials?.type === "federated" && !credentials.useManagedIdentity ? credentials.certificatePath : void 0;
|
|
31
|
+
const certificate = certificatePath ? (0, openclaw_plugin_sdk_secret_file_runtime.tryReadSecretFileSync)(certificatePath, "Microsoft Teams certificate", void 0, { configPath: config?.certificatePath?.trim() ? "channels.msteams.certificatePath" : "env.MSTEAMS_CERTIFICATE_PATH" }) : void 0;
|
|
32
|
+
const unavailable = certificate?.status === "configured_unavailable";
|
|
33
|
+
return {
|
|
34
|
+
accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
|
|
35
|
+
enabled: config?.enabled !== false,
|
|
36
|
+
configured: Boolean(credentials),
|
|
37
|
+
tokenStatus: !credentials ? "missing" : unavailable ? "configured_unavailable" : "available",
|
|
38
|
+
...unavailable ? { credentialDiagnostics: [certificate.diagnostic] } : {}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
23
41
|
const msteamsConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createTopLevelChannelConfigAdapter)({
|
|
24
42
|
sectionKey: "msteams",
|
|
25
|
-
resolveAccount:
|
|
26
|
-
accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
|
|
27
|
-
enabled: cfg.channels?.msteams?.enabled !== false,
|
|
28
|
-
configured: Boolean(require_resolve_allowlist.resolveMSTeamsCredentials(cfg.channels?.msteams))
|
|
29
|
-
}),
|
|
43
|
+
resolveAccount: resolveMSTeamsAccount,
|
|
30
44
|
resolveAccessorAccount: ({ cfg }) => ({
|
|
31
45
|
allowFrom: cfg.channels?.msteams?.allowFrom,
|
|
32
46
|
defaultTo: cfg.channels?.msteams?.defaultTo
|
|
@@ -220,12 +234,8 @@ function parseNonNegativeRetryAfterSeconds(raw) {
|
|
|
220
234
|
});
|
|
221
235
|
}
|
|
222
236
|
/**
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* Important: We only mark errors as retryable when we have an explicit HTTP
|
|
226
|
-
* status code that indicates the message was not accepted (e.g. 429, 5xx).
|
|
227
|
-
* For transport-level errors where delivery is ambiguous, we prefer to avoid
|
|
228
|
-
* retries to reduce the chance of duplicate posts.
|
|
237
|
+
* Owns retry safety and delivery ambiguity for Teams send failures.
|
|
238
|
+
* Only Teams rate-limit rejection proves this unkeyed POST safe to replay.
|
|
229
239
|
*/
|
|
230
240
|
function classifyMSTeamsSendError(err) {
|
|
231
241
|
const statusCode = extractStatusCode(err);
|
|
@@ -249,15 +259,15 @@ function classifyMSTeamsSendError(err) {
|
|
|
249
259
|
};
|
|
250
260
|
}
|
|
251
261
|
if (statusCode === 429) return {
|
|
252
|
-
kind: "
|
|
262
|
+
kind: "replay-safe",
|
|
253
263
|
statusCode,
|
|
254
264
|
retryAfterMs: retryAfterMs ?? void 0,
|
|
255
265
|
errorCode
|
|
256
266
|
};
|
|
257
267
|
if (statusCode === 408 || statusCode != null && statusCode >= 500) return {
|
|
258
|
-
kind: "
|
|
268
|
+
kind: "ambiguous",
|
|
269
|
+
source: "http",
|
|
259
270
|
statusCode,
|
|
260
|
-
retryAfterMs: retryAfterMs ?? void 0,
|
|
261
271
|
errorCode
|
|
262
272
|
};
|
|
263
273
|
if (statusCode != null && statusCode >= 400) return {
|
|
@@ -265,17 +275,14 @@ function classifyMSTeamsSendError(err) {
|
|
|
265
275
|
statusCode,
|
|
266
276
|
errorCode
|
|
267
277
|
};
|
|
268
|
-
if (statusCode == null) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
};
|
|
274
|
-
}
|
|
278
|
+
if (statusCode == null && (0, openclaw_plugin_sdk_retry_runtime.isTransientNetworkError)(err)) return {
|
|
279
|
+
kind: "ambiguous",
|
|
280
|
+
source: "transport",
|
|
281
|
+
errorCode
|
|
282
|
+
};
|
|
275
283
|
return {
|
|
276
284
|
kind: "unknown",
|
|
277
285
|
statusCode: statusCode ?? void 0,
|
|
278
|
-
retryAfterMs: retryAfterMs ?? void 0,
|
|
279
286
|
errorCode
|
|
280
287
|
};
|
|
281
288
|
}
|
|
@@ -294,9 +301,15 @@ function isRevokedProxyError(err) {
|
|
|
294
301
|
function formatMSTeamsSendErrorHint(classification) {
|
|
295
302
|
if (classification.kind === "auth") return "check msteams appId/appPassword/tenantId (or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID)";
|
|
296
303
|
if (classification.errorCode === "ContentStreamNotAllowed") return "Teams expired the content stream; stop streaming earlier and fall back to normal message delivery";
|
|
297
|
-
if (classification.kind === "
|
|
298
|
-
if (classification.kind === "
|
|
299
|
-
|
|
304
|
+
if (classification.kind === "replay-safe") return "Teams throttled the bot; backing off may help";
|
|
305
|
+
if (classification.kind === "ambiguous") {
|
|
306
|
+
if (classification.source === "transport") return "transport-level failure sending to Teams Bot Connector (smba.trafficmanager.net); the outcome is unknown, so check egress and conversation history before taking further action";
|
|
307
|
+
return "Teams/Bot Framework delivery outcome is unknown; inspect the conversation history before taking further action";
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function formatMSTeamsDeliveryFailureGuidance(classification) {
|
|
311
|
+
if (classification.kind === "replay-safe") return "The request was rate-limited before delivery; retrying later may succeed.";
|
|
312
|
+
if (classification.kind === "ambiguous") return "Delivery may already have succeeded; do not send the same content again without checking the conversation.";
|
|
300
313
|
}
|
|
301
314
|
//#endregion
|
|
302
315
|
//#region extensions/msteams/src/setup-surface.ts
|
|
@@ -466,7 +479,7 @@ const msteamsSetupWizard = {
|
|
|
466
479
|
};
|
|
467
480
|
let oauthModule;
|
|
468
481
|
try {
|
|
469
|
-
oauthModule = await Promise.resolve().then(() => require("./oauth-
|
|
482
|
+
oauthModule = await Promise.resolve().then(() => require("./oauth-BV7HWGe0.cjs"));
|
|
470
483
|
} catch (err) {
|
|
471
484
|
await noteDelegatedAuthFailure(err);
|
|
472
485
|
return {
|
|
@@ -520,6 +533,40 @@ const msteamsSetupWizard = {
|
|
|
520
533
|
disable: (cfg) => (0, openclaw_plugin_sdk_setup.setSetupChannelEnabled)(cfg, channel, false)
|
|
521
534
|
};
|
|
522
535
|
//#endregion
|
|
536
|
+
//#region extensions/msteams/src/channel.setup.ts
|
|
537
|
+
const msteamsSetupPlugin = {
|
|
538
|
+
id: "msteams",
|
|
539
|
+
meta: {
|
|
540
|
+
...msteamsMeta,
|
|
541
|
+
aliases: [...msteamsMeta.aliases]
|
|
542
|
+
},
|
|
543
|
+
capabilities: {
|
|
544
|
+
chatTypes: [
|
|
545
|
+
"direct",
|
|
546
|
+
"channel",
|
|
547
|
+
"group",
|
|
548
|
+
"thread"
|
|
549
|
+
],
|
|
550
|
+
polls: true,
|
|
551
|
+
threads: true,
|
|
552
|
+
media: true,
|
|
553
|
+
reactions: true
|
|
554
|
+
},
|
|
555
|
+
reload: { configPrefixes: ["channels.msteams"] },
|
|
556
|
+
configSchema: require_config_schema.MSTeamsChannelConfigSchema,
|
|
557
|
+
config: {
|
|
558
|
+
...msteamsConfigAdapter,
|
|
559
|
+
isConfigured: (account) => account.configured,
|
|
560
|
+
describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
|
|
561
|
+
account,
|
|
562
|
+
configured: account.configured,
|
|
563
|
+
extra: { tokenStatus: account.tokenStatus }
|
|
564
|
+
})
|
|
565
|
+
},
|
|
566
|
+
setupWizard: msteamsSetupWizard,
|
|
567
|
+
setupContract: msteamsSetupContract
|
|
568
|
+
};
|
|
569
|
+
//#endregion
|
|
523
570
|
Object.defineProperty(exports, "classifyMSTeamsSendError", {
|
|
524
571
|
enumerable: true,
|
|
525
572
|
get: function() {
|
|
@@ -532,6 +579,12 @@ Object.defineProperty(exports, "createMSTeamsSetupWizardBase", {
|
|
|
532
579
|
return createMSTeamsSetupWizardBase;
|
|
533
580
|
}
|
|
534
581
|
});
|
|
582
|
+
Object.defineProperty(exports, "formatMSTeamsDeliveryFailureGuidance", {
|
|
583
|
+
enumerable: true,
|
|
584
|
+
get: function() {
|
|
585
|
+
return formatMSTeamsDeliveryFailureGuidance;
|
|
586
|
+
}
|
|
587
|
+
});
|
|
535
588
|
Object.defineProperty(exports, "formatMSTeamsSendErrorHint", {
|
|
536
589
|
enumerable: true,
|
|
537
590
|
get: function() {
|
|
@@ -556,22 +609,16 @@ Object.defineProperty(exports, "msteamsConfigAdapter", {
|
|
|
556
609
|
return msteamsConfigAdapter;
|
|
557
610
|
}
|
|
558
611
|
});
|
|
559
|
-
Object.defineProperty(exports, "msteamsMeta", {
|
|
560
|
-
enumerable: true,
|
|
561
|
-
get: function() {
|
|
562
|
-
return msteamsMeta;
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
612
|
Object.defineProperty(exports, "msteamsSetupAdapter", {
|
|
566
613
|
enumerable: true,
|
|
567
614
|
get: function() {
|
|
568
615
|
return msteamsSetupAdapter;
|
|
569
616
|
}
|
|
570
617
|
});
|
|
571
|
-
Object.defineProperty(exports, "
|
|
618
|
+
Object.defineProperty(exports, "msteamsSetupPlugin", {
|
|
572
619
|
enumerable: true,
|
|
573
620
|
get: function() {
|
|
574
|
-
return
|
|
621
|
+
return msteamsSetupPlugin;
|
|
575
622
|
}
|
|
576
623
|
});
|
|
577
624
|
Object.defineProperty(exports, "msteamsSetupWizard", {
|
|
@@ -586,3 +633,9 @@ Object.defineProperty(exports, "openDelegatedOAuthUrl", {
|
|
|
586
633
|
return openDelegatedOAuthUrl;
|
|
587
634
|
}
|
|
588
635
|
});
|
|
636
|
+
Object.defineProperty(exports, "resolveMSTeamsAccount", {
|
|
637
|
+
enumerable: true,
|
|
638
|
+
get: function() {
|
|
639
|
+
return resolveMSTeamsAccount;
|
|
640
|
+
}
|
|
641
|
+
});
|
|
@@ -80,18 +80,19 @@ function isAzureChinaBotFrameworkServiceUrl(value) {
|
|
|
80
80
|
return false;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
+
const { accountShape, rootPolicyShape } = (0, openclaw_plugin_sdk_channel_config_schema.buildChannelAccountSchemaParts)({
|
|
84
|
+
omit: [
|
|
85
|
+
"name",
|
|
86
|
+
"mentionPatterns",
|
|
87
|
+
"replyToMode"
|
|
88
|
+
],
|
|
89
|
+
allowFrom: zod.z.array(zod.z.string()).optional(),
|
|
90
|
+
groupAllowFrom: zod.z.array(zod.z.string()).optional(),
|
|
91
|
+
streaming: openclaw_plugin_sdk_channel_config_schema.ChannelPreviewStreamingConfigSchema.optional()
|
|
92
|
+
});
|
|
83
93
|
const MSTeamsConfigSchema = zod.z.object({
|
|
84
|
-
...
|
|
85
|
-
|
|
86
|
-
omit: [
|
|
87
|
-
"name",
|
|
88
|
-
"mentionPatterns",
|
|
89
|
-
"replyToMode"
|
|
90
|
-
],
|
|
91
|
-
allowFrom: zod.z.array(zod.z.string()).optional(),
|
|
92
|
-
groupAllowFrom: zod.z.array(zod.z.string()).optional(),
|
|
93
|
-
streaming: openclaw_plugin_sdk_channel_config_schema.ChannelPreviewStreamingConfigSchema.optional()
|
|
94
|
-
}),
|
|
94
|
+
...accountShape,
|
|
95
|
+
...rootPolicyShape,
|
|
95
96
|
dangerouslyAllowNameMatching: openclaw_plugin_sdk_channel_config_schema.ChannelDangerouslyAllowNameMatchingSchema,
|
|
96
97
|
appId: zod.z.string().optional(),
|
|
97
98
|
appPassword: (0, openclaw_plugin_sdk_secret_input.registerSensitiveConfigSchema)(SecretInputSchema.optional()),
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./secret-input-C65t6kjM.cjs");
|
|
3
|
+
let openclaw_plugin_sdk_secret_input = require("openclaw/plugin-sdk/secret-input");
|
|
4
|
+
//#region extensions/msteams/configured-state.ts
|
|
5
|
+
/** Mirror Teams auth-mode requirements without loading the Azure SDK or full channel. */
|
|
6
|
+
function hasConfiguredMSTeamsChannelState(params) {
|
|
7
|
+
const config = params.cfg.channels?.msteams;
|
|
8
|
+
if (config?.enabled === false) return false;
|
|
9
|
+
const env = params.env ?? process.env;
|
|
10
|
+
const appId = (0, openclaw_plugin_sdk_secret_input.normalizeSecretInputString)(config && Object.hasOwn(config, "appId") ? config.appId : env.MSTEAMS_APP_ID);
|
|
11
|
+
const tenantId = (0, openclaw_plugin_sdk_secret_input.normalizeSecretInputString)(config && Object.hasOwn(config, "tenantId") ? config.tenantId : env.MSTEAMS_TENANT_ID);
|
|
12
|
+
if (!appId || !tenantId) return false;
|
|
13
|
+
if ((config?.authType ?? env.MSTEAMS_AUTH_TYPE ?? "secret") === "federated") {
|
|
14
|
+
const certificatePath = (0, openclaw_plugin_sdk_secret_input.normalizeSecretInputString)(config && Object.hasOwn(config, "certificatePath") ? config.certificatePath : env.MSTEAMS_CERTIFICATE_PATH);
|
|
15
|
+
return Boolean(certificatePath || (config?.useManagedIdentity ?? env.MSTEAMS_USE_MANAGED_IDENTITY === "true"));
|
|
16
|
+
}
|
|
17
|
+
return config && Object.hasOwn(config, "appPassword") ? (0, openclaw_plugin_sdk_secret_input.hasConfiguredSecretInput)(config.appPassword) : Boolean((0, openclaw_plugin_sdk_secret_input.normalizeSecretInputString)(env.MSTEAMS_APP_PASSWORD));
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
exports.hasConfiguredMSTeamsChannelState = hasConfiguredMSTeamsChannelState;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
2
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CWbvAW4v.cjs");
|
|
3
3
|
let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
|
|
4
4
|
const msteamsDirectoryContractPlugin = {
|
|
5
5
|
id: "msteams",
|
|
@@ -11,7 +11,7 @@ node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises, 1);
|
|
|
11
11
|
let node_path = require("node:path");
|
|
12
12
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
13
13
|
let openclaw_plugin_sdk_runtime_doctor_migrations = require("openclaw/plugin-sdk/runtime-doctor-migrations");
|
|
14
|
-
//#region extensions/msteams/doctor-
|
|
14
|
+
//#region extensions/msteams/config-doctor-api.ts
|
|
15
15
|
const streamingAliasMigration = (0, openclaw_plugin_sdk_runtime_doctor_migrations.defineChannelAliasMigration)({
|
|
16
16
|
channelId: "msteams",
|
|
17
17
|
streaming: { defaultMode: "partial" }
|
|
@@ -20,6 +20,8 @@ const legacyConfigRules = streamingAliasMigration.legacyConfigRules;
|
|
|
20
20
|
function normalizeCompatibilityConfig({ cfg }) {
|
|
21
21
|
return streamingAliasMigration.normalizeChannelConfig({ cfg });
|
|
22
22
|
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region extensions/msteams/doctor-contract-api.ts
|
|
23
25
|
const LEARNINGS_NAMESPACE = "feedback-learnings";
|
|
24
26
|
const MAX_LEARNING_ENTRIES = 1e4;
|
|
25
27
|
const MSTEAMS_PLUGIN_ID = "Microsoft Teams";
|
|
@@ -165,6 +167,33 @@ function mergeLearnings(legacy, existing) {
|
|
|
165
167
|
}
|
|
166
168
|
return merged.slice(-10);
|
|
167
169
|
}
|
|
170
|
+
async function completeLegacyKeyedImport(params) {
|
|
171
|
+
const { filePath, label, imported, warnings } = params;
|
|
172
|
+
const changes = [];
|
|
173
|
+
let missing = 0;
|
|
174
|
+
for (const { store, requiredKeys } of params.stores) {
|
|
175
|
+
const retainedKeys = new Set((await store.entries()).map((entry) => entry.key));
|
|
176
|
+
missing += [...requiredKeys].filter((key) => !retainedKeys.has(key)).length;
|
|
177
|
+
}
|
|
178
|
+
if (missing > 0) {
|
|
179
|
+
warnings.push(`Incomplete ${label} migration: plugin state failed to retain every required entry (${missing} missing); left legacy source in place`);
|
|
180
|
+
return {
|
|
181
|
+
changes,
|
|
182
|
+
warnings
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
changes.push(`Migrated ${imported} ${label} ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
186
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
187
|
+
filePath,
|
|
188
|
+
label: params.archiveLabel ?? label,
|
|
189
|
+
changes,
|
|
190
|
+
warnings
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
changes,
|
|
194
|
+
warnings
|
|
195
|
+
};
|
|
196
|
+
}
|
|
168
197
|
const stateMigrations = [
|
|
169
198
|
{
|
|
170
199
|
id: "msteams-conversations-json-to-plugin-state",
|
|
@@ -175,35 +204,36 @@ const stateMigrations = [
|
|
|
175
204
|
return { preview: [`- ${MSTEAMS_PLUGIN_ID} conversations: ${Object.keys(state.conversations).length} entries -> plugin state (${require_polls.MSTEAMS_CONVERSATIONS_NAMESPACE})`] };
|
|
176
205
|
},
|
|
177
206
|
async migrateLegacyState(params) {
|
|
178
|
-
const changes = [];
|
|
179
|
-
const warnings = [];
|
|
180
207
|
const filePath = resolveStateFilePath(params.stateDir, require_polls.MSTEAMS_CONVERSATIONS_LEGACY_FILENAME);
|
|
181
208
|
const state = await readLegacyJsonFile(filePath, parseLegacyConversationStore);
|
|
182
209
|
if (!state) return {
|
|
183
|
-
changes,
|
|
184
|
-
warnings
|
|
210
|
+
changes: [],
|
|
211
|
+
warnings: []
|
|
185
212
|
};
|
|
186
213
|
const store = params.context.openPluginStateKeyedStore({
|
|
187
214
|
namespace: require_polls.MSTEAMS_CONVERSATIONS_NAMESPACE,
|
|
188
215
|
maxEntries: require_polls.MSTEAMS_SQLITE_MAX_CONVERSATION_ROWS
|
|
189
216
|
});
|
|
217
|
+
const requiredKeys = new Set((await store.entries()).map((entry) => entry.key));
|
|
190
218
|
let imported = 0;
|
|
191
219
|
for (const [rawConversationId, reference] of require_polls.selectRetainedMSTeamsConversations(state.conversations)) {
|
|
192
220
|
const conversationId = require_polls.normalizeStoredConversationId(rawConversationId);
|
|
193
221
|
if (!conversationId) continue;
|
|
194
|
-
|
|
222
|
+
const key = require_polls.buildMSTeamsConversationStateKey(conversationId);
|
|
223
|
+
requiredKeys.add(key);
|
|
224
|
+
const storedReference = require_polls.prepareMSTeamsConversationReferenceForStorage(conversationId, reference);
|
|
225
|
+
if (await store.registerIfAbsent(key, storedReference)) imported++;
|
|
195
226
|
}
|
|
196
|
-
|
|
197
|
-
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
227
|
+
return completeLegacyKeyedImport({
|
|
198
228
|
filePath,
|
|
199
229
|
label: `${MSTEAMS_PLUGIN_ID} conversation`,
|
|
200
|
-
|
|
201
|
-
warnings
|
|
230
|
+
imported,
|
|
231
|
+
warnings: [],
|
|
232
|
+
stores: [{
|
|
233
|
+
store,
|
|
234
|
+
requiredKeys
|
|
235
|
+
}]
|
|
202
236
|
});
|
|
203
|
-
return {
|
|
204
|
-
changes,
|
|
205
|
-
warnings
|
|
206
|
-
};
|
|
207
237
|
}
|
|
208
238
|
},
|
|
209
239
|
{
|
|
@@ -215,13 +245,11 @@ const stateMigrations = [
|
|
|
215
245
|
return { preview: [`- ${MSTEAMS_PLUGIN_ID} polls: ${Object.keys(state.polls).length} entries -> plugin state (${require_polls.MSTEAMS_POLLS_NAMESPACE})`] };
|
|
216
246
|
},
|
|
217
247
|
async migrateLegacyState(params) {
|
|
218
|
-
const changes = [];
|
|
219
|
-
const warnings = [];
|
|
220
248
|
const filePath = resolveStateFilePath(params.stateDir, require_polls.MSTEAMS_POLLS_LEGACY_FILENAME);
|
|
221
249
|
const state = await readLegacyJsonFile(filePath, parseLegacyPollStore);
|
|
222
250
|
if (!state) return {
|
|
223
|
-
changes,
|
|
224
|
-
warnings
|
|
251
|
+
changes: [],
|
|
252
|
+
warnings: []
|
|
225
253
|
};
|
|
226
254
|
const pollStore = params.context.openPluginStateKeyedStore({
|
|
227
255
|
namespace: require_polls.MSTEAMS_POLLS_NAMESPACE,
|
|
@@ -231,10 +259,14 @@ const stateMigrations = [
|
|
|
231
259
|
namespace: require_polls.MSTEAMS_POLL_VOTE_BUCKETS_NAMESPACE,
|
|
232
260
|
maxEntries: require_polls.MSTEAMS_MAX_POLL_VOTE_BUCKET_ROWS
|
|
233
261
|
});
|
|
262
|
+
const requiredPollKeys = new Set((await pollStore.entries()).map((entry) => entry.key));
|
|
263
|
+
const requiredVoteKeys = new Set((await voteBucketStore.entries()).map((entry) => entry.key));
|
|
234
264
|
let imported = 0;
|
|
235
265
|
for (const [pollId, poll] of require_polls.selectRetainedMSTeamsPolls(state.polls)) {
|
|
236
266
|
const { metadata, votes } = require_polls.splitMSTeamsPoll(poll);
|
|
237
|
-
const
|
|
267
|
+
const pollKey = require_polls.buildMSTeamsPollStateKey(pollId);
|
|
268
|
+
requiredPollKeys.add(pollKey);
|
|
269
|
+
const didImportPoll = await pollStore.registerIfAbsent(pollKey, metadata);
|
|
238
270
|
const buckets = /* @__PURE__ */ new Map();
|
|
239
271
|
for (const [voterId, selections] of Object.entries(votes)) {
|
|
240
272
|
const bucket = require_polls.selectMSTeamsPollVoteBucket(pollId, voterId);
|
|
@@ -245,6 +277,7 @@ const stateMigrations = [
|
|
|
245
277
|
let importedVoteBucket = false;
|
|
246
278
|
for (const [bucket, bucketVotes] of buckets) {
|
|
247
279
|
const key = require_polls.buildMSTeamsPollVoteBucketKey(pollId, bucket);
|
|
280
|
+
requiredVoteKeys.add(key);
|
|
248
281
|
const existing = await voteBucketStore.lookup(key);
|
|
249
282
|
await voteBucketStore.register(key, {
|
|
250
283
|
pollId,
|
|
@@ -259,17 +292,19 @@ const stateMigrations = [
|
|
|
259
292
|
}
|
|
260
293
|
if (didImportPoll || importedVoteBucket) imported++;
|
|
261
294
|
}
|
|
262
|
-
|
|
263
|
-
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
295
|
+
return completeLegacyKeyedImport({
|
|
264
296
|
filePath,
|
|
265
297
|
label: `${MSTEAMS_PLUGIN_ID} poll`,
|
|
266
|
-
|
|
267
|
-
warnings
|
|
298
|
+
imported,
|
|
299
|
+
warnings: [],
|
|
300
|
+
stores: [{
|
|
301
|
+
store: pollStore,
|
|
302
|
+
requiredKeys: requiredPollKeys
|
|
303
|
+
}, {
|
|
304
|
+
store: voteBucketStore,
|
|
305
|
+
requiredKeys: requiredVoteKeys
|
|
306
|
+
}]
|
|
268
307
|
});
|
|
269
|
-
return {
|
|
270
|
-
changes,
|
|
271
|
-
warnings
|
|
272
|
-
};
|
|
273
308
|
}
|
|
274
309
|
},
|
|
275
310
|
{
|
|
@@ -281,18 +316,18 @@ const stateMigrations = [
|
|
|
281
316
|
return { preview: [`- ${MSTEAMS_PLUGIN_ID} SSO tokens: ${Object.keys(state.tokens).length} entries -> plugin state (${require_sso_token_store.MSTEAMS_SSO_TOKENS_NAMESPACE})`] };
|
|
282
317
|
},
|
|
283
318
|
async migrateLegacyState(params) {
|
|
284
|
-
const changes = [];
|
|
285
319
|
const warnings = [];
|
|
286
320
|
const filePath = resolveStateFilePath(params.stateDir, require_sso_token_store.MSTEAMS_SSO_TOKENS_LEGACY_FILENAME);
|
|
287
321
|
const state = await readLegacyJsonFile(filePath, (value) => require_sso_token_store.isMSTeamsSsoStoreData(value) ? value : null);
|
|
288
322
|
if (!state) return {
|
|
289
|
-
changes,
|
|
323
|
+
changes: [],
|
|
290
324
|
warnings
|
|
291
325
|
};
|
|
292
326
|
const store = params.context.openPluginStateKeyedStore({
|
|
293
327
|
namespace: require_sso_token_store.MSTEAMS_SSO_TOKENS_NAMESPACE,
|
|
294
328
|
maxEntries: require_sso_token_store.MSTEAMS_MAX_SSO_TOKENS
|
|
295
329
|
});
|
|
330
|
+
const requiredKeys = new Set((await store.entries()).map((entry) => entry.key));
|
|
296
331
|
let imported = 0;
|
|
297
332
|
let skipped = 0;
|
|
298
333
|
for (const token of Object.values(state.tokens)) {
|
|
@@ -301,20 +336,22 @@ const stateMigrations = [
|
|
|
301
336
|
skipped++;
|
|
302
337
|
continue;
|
|
303
338
|
}
|
|
304
|
-
|
|
339
|
+
const key = require_sso_token_store.makeMSTeamsSsoTokenStoreKey(normalized.connectionName, normalized.userId);
|
|
340
|
+
requiredKeys.add(key);
|
|
341
|
+
if (await store.registerIfAbsent(key, normalized)) imported++;
|
|
305
342
|
}
|
|
306
|
-
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} SSO token ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
307
343
|
if (skipped > 0) warnings.push(`Skipped ${skipped} malformed ${MSTEAMS_PLUGIN_ID} SSO token ${skipped === 1 ? "entry" : "entries"} during migration`);
|
|
308
|
-
|
|
344
|
+
return completeLegacyKeyedImport({
|
|
309
345
|
filePath,
|
|
310
|
-
label: `${MSTEAMS_PLUGIN_ID} SSO
|
|
311
|
-
|
|
312
|
-
|
|
346
|
+
label: `${MSTEAMS_PLUGIN_ID} SSO token`,
|
|
347
|
+
archiveLabel: `${MSTEAMS_PLUGIN_ID} SSO-token`,
|
|
348
|
+
imported,
|
|
349
|
+
warnings,
|
|
350
|
+
stores: [{
|
|
351
|
+
store,
|
|
352
|
+
requiredKeys
|
|
353
|
+
}]
|
|
313
354
|
});
|
|
314
|
-
return {
|
|
315
|
-
changes,
|
|
316
|
-
warnings
|
|
317
|
-
};
|
|
318
355
|
}
|
|
319
356
|
},
|
|
320
357
|
{
|