@openclaw/msteams 2026.7.2-beta.7 → 2026.8.1-beta.3
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-8g-MOPfb.cjs +311 -0
- package/dist/api.cjs +6 -6
- package/dist/{channel-C7QxRjBW.cjs → channel-KpWENcgK.cjs} +222 -265
- package/dist/channel-plugin-api.cjs +1 -1
- package/dist/{channel.runtime-DjY6d_hd.cjs → channel.runtime-Bkzj8jZ0.cjs} +131 -88
- package/dist/{setup-surface-ByWjaXEn.cjs → channel.setup-mOFtsfYz.cjs} +91 -50
- package/dist/directory-contract-api.cjs +1 -1
- package/dist/doctor-contract-api.cjs +18 -17
- package/dist/{messenger-DTiaLTDO.cjs → messenger-IISPSOvj.cjs} +61 -46
- package/dist/{oauth-CW6jVGp8.cjs → oauth-C9So7uld.cjs} +13 -26
- package/dist/{polls-BWKNpBSg.cjs → polls-DvuJvaDG.cjs} +6 -39
- package/dist/qa-runner-api.cjs +36 -0
- package/dist/{resolve-allowlist-CEj9sABO.cjs → resolve-allowlist-CIfWUwuc.cjs} +182 -118
- package/dist/rolldown-runtime-D6vf50IK.cjs +28 -0
- package/dist/runtime-api.cjs +1 -1
- package/dist/secret-contract-api.cjs +6 -30
- package/dist/setup-plugin-api.cjs +2 -37
- package/dist/{src-B_BdEvcr.cjs → src-C127-DcQ.cjs} +439 -269
- package/dist/{sso-token-store-TKYk_Ms7.cjs → sso-token-store-ChhO1f4i.cjs} +1 -1
- package/openclaw.plugin.json +34 -8
- package/package.json +4 -5
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
1
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
|
|
2
|
+
const require_config_schema = require("./config-schema-C4CszdDi.cjs");
|
|
2
3
|
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
4
|
let openclaw_plugin_sdk_allow_from = require("openclaw/plugin-sdk/allow-from");
|
|
5
|
+
let openclaw_plugin_sdk_account_id = require("openclaw/plugin-sdk/account-id");
|
|
5
6
|
let openclaw_plugin_sdk_number_runtime = require("openclaw/plugin-sdk/number-runtime");
|
|
6
7
|
let openclaw_plugin_sdk_channel_config_helpers = require("openclaw/plugin-sdk/channel-config-helpers");
|
|
8
|
+
let openclaw_plugin_sdk_secret_file_runtime = require("openclaw/plugin-sdk/secret-file-runtime");
|
|
9
|
+
let openclaw_plugin_sdk_account_helpers = require("openclaw/plugin-sdk/account-helpers");
|
|
7
10
|
let openclaw_plugin_sdk_channel_setup = require("openclaw/plugin-sdk/channel-setup");
|
|
8
11
|
let openclaw_plugin_sdk_setup = require("openclaw/plugin-sdk/setup");
|
|
9
12
|
let openclaw_plugin_sdk_setup_tools = require("openclaw/plugin-sdk/setup-tools");
|
|
@@ -20,13 +23,23 @@ const msteamsMeta = {
|
|
|
20
23
|
aliases: ["teams"],
|
|
21
24
|
order: 60
|
|
22
25
|
};
|
|
26
|
+
function resolveMSTeamsAccount(cfg) {
|
|
27
|
+
const config = cfg.channels?.msteams;
|
|
28
|
+
const credentials = require_resolve_allowlist.resolveMSTeamsCredentials(config);
|
|
29
|
+
const certificatePath = credentials?.type === "federated" && !credentials.useManagedIdentity ? credentials.certificatePath : void 0;
|
|
30
|
+
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;
|
|
31
|
+
const unavailable = certificate?.status === "configured_unavailable";
|
|
32
|
+
return {
|
|
33
|
+
accountId: openclaw_plugin_sdk_account_id.DEFAULT_ACCOUNT_ID,
|
|
34
|
+
enabled: config?.enabled !== false,
|
|
35
|
+
configured: Boolean(credentials),
|
|
36
|
+
tokenStatus: !credentials ? "missing" : unavailable ? "configured_unavailable" : "available",
|
|
37
|
+
...unavailable ? { credentialDiagnostics: [certificate.diagnostic] } : {}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
23
40
|
const msteamsConfigAdapter = (0, openclaw_plugin_sdk_channel_config_helpers.createTopLevelChannelConfigAdapter)({
|
|
24
41
|
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
|
-
}),
|
|
42
|
+
resolveAccount: resolveMSTeamsAccount,
|
|
30
43
|
resolveAccessorAccount: ({ cfg }) => ({
|
|
31
44
|
allowFrom: cfg.channels?.msteams?.allowFrom,
|
|
32
45
|
defaultTo: cfg.channels?.msteams?.defaultTo
|
|
@@ -93,8 +106,8 @@ function createMSTeamsSetupWizardBase() {
|
|
|
93
106
|
let appPassword = null;
|
|
94
107
|
let tenantId = null;
|
|
95
108
|
if (!resolved && !hasConfigCreds) await noteMSTeamsCredentialHelp(prompter);
|
|
96
|
-
if (canUseEnv) if (await prompter.confirm({
|
|
97
|
-
message: t$1("wizard.msteams.envPrompt"),
|
|
109
|
+
if (canUseEnv || hasConfigCreds) if (await prompter.confirm({
|
|
110
|
+
message: t$1(canUseEnv ? "wizard.msteams.envPrompt" : "wizard.msteams.credentialsKeep"),
|
|
98
111
|
initialValue: true
|
|
99
112
|
})) next = msteamsSetupAdapter.applyAccountConfig({
|
|
100
113
|
cfg: next,
|
|
@@ -102,12 +115,7 @@ function createMSTeamsSetupWizardBase() {
|
|
|
102
115
|
input: {}
|
|
103
116
|
});
|
|
104
117
|
else ({appId, appPassword, tenantId} = await promptMSTeamsCredentials(prompter));
|
|
105
|
-
else
|
|
106
|
-
if (!await prompter.confirm({
|
|
107
|
-
message: t$1("wizard.msteams.credentialsKeep"),
|
|
108
|
-
initialValue: true
|
|
109
|
-
})) ({appId, appPassword, tenantId} = await promptMSTeamsCredentials(prompter));
|
|
110
|
-
} else ({appId, appPassword, tenantId} = await promptMSTeamsCredentials(prompter));
|
|
118
|
+
else ({appId, appPassword, tenantId} = await promptMSTeamsCredentials(prompter));
|
|
111
119
|
if (appId && appPassword && tenantId) next = {
|
|
112
120
|
...next,
|
|
113
121
|
channels: {
|
|
@@ -225,12 +233,8 @@ function parseNonNegativeRetryAfterSeconds(raw) {
|
|
|
225
233
|
});
|
|
226
234
|
}
|
|
227
235
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* Important: We only mark errors as retryable when we have an explicit HTTP
|
|
231
|
-
* status code that indicates the message was not accepted (e.g. 429, 5xx).
|
|
232
|
-
* For transport-level errors where delivery is ambiguous, we prefer to avoid
|
|
233
|
-
* retries to reduce the chance of duplicate posts.
|
|
236
|
+
* Owns retry safety and delivery ambiguity for Teams send failures.
|
|
237
|
+
* Only Teams rate-limit rejection proves this unkeyed POST safe to replay.
|
|
234
238
|
*/
|
|
235
239
|
function classifyMSTeamsSendError(err) {
|
|
236
240
|
const statusCode = extractStatusCode(err);
|
|
@@ -254,15 +258,15 @@ function classifyMSTeamsSendError(err) {
|
|
|
254
258
|
};
|
|
255
259
|
}
|
|
256
260
|
if (statusCode === 429) return {
|
|
257
|
-
kind: "
|
|
261
|
+
kind: "replay-safe",
|
|
258
262
|
statusCode,
|
|
259
263
|
retryAfterMs: retryAfterMs ?? void 0,
|
|
260
264
|
errorCode
|
|
261
265
|
};
|
|
262
266
|
if (statusCode === 408 || statusCode != null && statusCode >= 500) return {
|
|
263
|
-
kind: "
|
|
267
|
+
kind: "ambiguous",
|
|
268
|
+
source: "http",
|
|
264
269
|
statusCode,
|
|
265
|
-
retryAfterMs: retryAfterMs ?? void 0,
|
|
266
270
|
errorCode
|
|
267
271
|
};
|
|
268
272
|
if (statusCode != null && statusCode >= 400) return {
|
|
@@ -270,17 +274,14 @@ function classifyMSTeamsSendError(err) {
|
|
|
270
274
|
statusCode,
|
|
271
275
|
errorCode
|
|
272
276
|
};
|
|
273
|
-
if (statusCode == null) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
279
|
-
}
|
|
277
|
+
if (statusCode == null && (0, openclaw_plugin_sdk_retry_runtime.isTransientNetworkError)(err)) return {
|
|
278
|
+
kind: "ambiguous",
|
|
279
|
+
source: "transport",
|
|
280
|
+
errorCode
|
|
281
|
+
};
|
|
280
282
|
return {
|
|
281
283
|
kind: "unknown",
|
|
282
284
|
statusCode: statusCode ?? void 0,
|
|
283
|
-
retryAfterMs: retryAfterMs ?? void 0,
|
|
284
285
|
errorCode
|
|
285
286
|
};
|
|
286
287
|
}
|
|
@@ -299,9 +300,15 @@ function isRevokedProxyError(err) {
|
|
|
299
300
|
function formatMSTeamsSendErrorHint(classification) {
|
|
300
301
|
if (classification.kind === "auth") return "check msteams appId/appPassword/tenantId (or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID)";
|
|
301
302
|
if (classification.errorCode === "ContentStreamNotAllowed") return "Teams expired the content stream; stop streaming earlier and fall back to normal message delivery";
|
|
302
|
-
if (classification.kind === "
|
|
303
|
-
if (classification.kind === "
|
|
304
|
-
|
|
303
|
+
if (classification.kind === "replay-safe") return "Teams throttled the bot; backing off may help";
|
|
304
|
+
if (classification.kind === "ambiguous") {
|
|
305
|
+
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";
|
|
306
|
+
return "Teams/Bot Framework delivery outcome is unknown; inspect the conversation history before taking further action";
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function formatMSTeamsDeliveryFailureGuidance(classification) {
|
|
310
|
+
if (classification.kind === "replay-safe") return "The request was rate-limited before delivery; retrying later may succeed.";
|
|
311
|
+
if (classification.kind === "ambiguous") return "Delivery may already have succeeded; do not send the same content again without checking the conversation.";
|
|
305
312
|
}
|
|
306
313
|
//#endregion
|
|
307
314
|
//#region extensions/msteams/src/setup-surface.ts
|
|
@@ -471,7 +478,7 @@ const msteamsSetupWizard = {
|
|
|
471
478
|
};
|
|
472
479
|
let oauthModule;
|
|
473
480
|
try {
|
|
474
|
-
oauthModule = await Promise.resolve().then(() => require("./oauth-
|
|
481
|
+
oauthModule = await Promise.resolve().then(() => require("./oauth-C9So7uld.cjs"));
|
|
475
482
|
} catch (err) {
|
|
476
483
|
await noteDelegatedAuthFailure(err);
|
|
477
484
|
return {
|
|
@@ -525,6 +532,40 @@ const msteamsSetupWizard = {
|
|
|
525
532
|
disable: (cfg) => (0, openclaw_plugin_sdk_setup.setSetupChannelEnabled)(cfg, channel, false)
|
|
526
533
|
};
|
|
527
534
|
//#endregion
|
|
535
|
+
//#region extensions/msteams/src/channel.setup.ts
|
|
536
|
+
const msteamsSetupPlugin = {
|
|
537
|
+
id: "msteams",
|
|
538
|
+
meta: {
|
|
539
|
+
...msteamsMeta,
|
|
540
|
+
aliases: [...msteamsMeta.aliases]
|
|
541
|
+
},
|
|
542
|
+
capabilities: {
|
|
543
|
+
chatTypes: [
|
|
544
|
+
"direct",
|
|
545
|
+
"channel",
|
|
546
|
+
"group",
|
|
547
|
+
"thread"
|
|
548
|
+
],
|
|
549
|
+
polls: true,
|
|
550
|
+
threads: true,
|
|
551
|
+
media: true,
|
|
552
|
+
reactions: true
|
|
553
|
+
},
|
|
554
|
+
reload: { configPrefixes: ["channels.msteams"] },
|
|
555
|
+
configSchema: require_config_schema.MSTeamsChannelConfigSchema,
|
|
556
|
+
config: {
|
|
557
|
+
...msteamsConfigAdapter,
|
|
558
|
+
isConfigured: (account) => account.configured,
|
|
559
|
+
describeAccount: (account) => (0, openclaw_plugin_sdk_account_helpers.describeAccountSnapshot)({
|
|
560
|
+
account,
|
|
561
|
+
configured: account.configured,
|
|
562
|
+
extra: { tokenStatus: account.tokenStatus }
|
|
563
|
+
})
|
|
564
|
+
},
|
|
565
|
+
setupWizard: msteamsSetupWizard,
|
|
566
|
+
setupContract: msteamsSetupContract
|
|
567
|
+
};
|
|
568
|
+
//#endregion
|
|
528
569
|
Object.defineProperty(exports, "classifyMSTeamsSendError", {
|
|
529
570
|
enumerable: true,
|
|
530
571
|
get: function() {
|
|
@@ -537,6 +578,12 @@ Object.defineProperty(exports, "createMSTeamsSetupWizardBase", {
|
|
|
537
578
|
return createMSTeamsSetupWizardBase;
|
|
538
579
|
}
|
|
539
580
|
});
|
|
581
|
+
Object.defineProperty(exports, "formatMSTeamsDeliveryFailureGuidance", {
|
|
582
|
+
enumerable: true,
|
|
583
|
+
get: function() {
|
|
584
|
+
return formatMSTeamsDeliveryFailureGuidance;
|
|
585
|
+
}
|
|
586
|
+
});
|
|
540
587
|
Object.defineProperty(exports, "formatMSTeamsSendErrorHint", {
|
|
541
588
|
enumerable: true,
|
|
542
589
|
get: function() {
|
|
@@ -555,28 +602,16 @@ Object.defineProperty(exports, "isRevokedProxyError", {
|
|
|
555
602
|
return isRevokedProxyError;
|
|
556
603
|
}
|
|
557
604
|
});
|
|
558
|
-
Object.defineProperty(exports, "msteamsConfigAdapter", {
|
|
559
|
-
enumerable: true,
|
|
560
|
-
get: function() {
|
|
561
|
-
return msteamsConfigAdapter;
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
Object.defineProperty(exports, "msteamsMeta", {
|
|
565
|
-
enumerable: true,
|
|
566
|
-
get: function() {
|
|
567
|
-
return msteamsMeta;
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
605
|
Object.defineProperty(exports, "msteamsSetupAdapter", {
|
|
571
606
|
enumerable: true,
|
|
572
607
|
get: function() {
|
|
573
608
|
return msteamsSetupAdapter;
|
|
574
609
|
}
|
|
575
610
|
});
|
|
576
|
-
Object.defineProperty(exports, "
|
|
611
|
+
Object.defineProperty(exports, "msteamsSetupPlugin", {
|
|
577
612
|
enumerable: true,
|
|
578
613
|
get: function() {
|
|
579
|
-
return
|
|
614
|
+
return msteamsSetupPlugin;
|
|
580
615
|
}
|
|
581
616
|
});
|
|
582
617
|
Object.defineProperty(exports, "msteamsSetupWizard", {
|
|
@@ -591,3 +626,9 @@ Object.defineProperty(exports, "openDelegatedOAuthUrl", {
|
|
|
591
626
|
return openDelegatedOAuthUrl;
|
|
592
627
|
}
|
|
593
628
|
});
|
|
629
|
+
Object.defineProperty(exports, "resolveMSTeamsAccount", {
|
|
630
|
+
enumerable: true,
|
|
631
|
+
get: function() {
|
|
632
|
+
return resolveMSTeamsAccount;
|
|
633
|
+
}
|
|
634
|
+
});
|
|
@@ -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-CIfWUwuc.cjs");
|
|
3
3
|
let openclaw_plugin_sdk_directory_runtime = require("openclaw/plugin-sdk/directory-runtime");
|
|
4
4
|
const msteamsDirectoryContractPlugin = {
|
|
5
5
|
id: "msteams",
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
|
|
3
3
|
const require_delegated_state = require("./delegated-state-DiEz9JIa.cjs");
|
|
4
|
-
const
|
|
4
|
+
const require_polls = require("./polls-DvuJvaDG.cjs");
|
|
5
|
+
const require_sso_token_store = require("./sso-token-store-ChhO1f4i.cjs");
|
|
5
6
|
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
6
7
|
let node_crypto = require("node:crypto");
|
|
7
|
-
node_crypto =
|
|
8
|
+
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
8
9
|
let node_fs_promises = require("node:fs/promises");
|
|
9
|
-
node_fs_promises =
|
|
10
|
+
node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises, 1);
|
|
10
11
|
let node_path = require("node:path");
|
|
11
|
-
node_path =
|
|
12
|
-
let
|
|
13
|
-
let openclaw_plugin_sdk_session_store_runtime = require("openclaw/plugin-sdk/session-store-runtime");
|
|
12
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
13
|
+
let openclaw_plugin_sdk_runtime_doctor_migrations = require("openclaw/plugin-sdk/runtime-doctor-migrations");
|
|
14
14
|
//#region extensions/msteams/doctor-contract-api.ts
|
|
15
|
-
const streamingAliasMigration = (0,
|
|
15
|
+
const streamingAliasMigration = (0, openclaw_plugin_sdk_runtime_doctor_migrations.defineChannelAliasMigration)({
|
|
16
16
|
channelId: "msteams",
|
|
17
17
|
streaming: { defaultMode: "partial" }
|
|
18
18
|
});
|
|
@@ -66,9 +66,10 @@ function listAgentIds(config) {
|
|
|
66
66
|
for (const agent of config.agents?.list ?? []) if (typeof agent.id === "string" && agent.id.trim()) ids.add(agent.id.trim());
|
|
67
67
|
return [...ids];
|
|
68
68
|
}
|
|
69
|
-
function listCandidateStorePaths(params) {
|
|
69
|
+
async function listCandidateStorePaths(params) {
|
|
70
|
+
const { resolveStorePath } = await import("openclaw/plugin-sdk/session-store-runtime");
|
|
70
71
|
const paths = /* @__PURE__ */ new Set();
|
|
71
|
-
for (const agentId of listAgentIds(params.config)) paths.add(
|
|
72
|
+
for (const agentId of listAgentIds(params.config)) paths.add(resolveStorePath(params.config.session?.store, {
|
|
72
73
|
agentId,
|
|
73
74
|
env: params.env
|
|
74
75
|
}));
|
|
@@ -193,7 +194,7 @@ const stateMigrations = [
|
|
|
193
194
|
if (await store.registerIfAbsent(require_polls.buildMSTeamsConversationStateKey(conversationId), require_polls.prepareMSTeamsConversationReferenceForStorage(conversationId, reference))) imported++;
|
|
194
195
|
}
|
|
195
196
|
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} conversation ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
196
|
-
await (0,
|
|
197
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
197
198
|
filePath,
|
|
198
199
|
label: `${MSTEAMS_PLUGIN_ID} conversation`,
|
|
199
200
|
changes,
|
|
@@ -259,7 +260,7 @@ const stateMigrations = [
|
|
|
259
260
|
if (didImportPoll || importedVoteBucket) imported++;
|
|
260
261
|
}
|
|
261
262
|
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} poll ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
262
|
-
await (0,
|
|
263
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
263
264
|
filePath,
|
|
264
265
|
label: `${MSTEAMS_PLUGIN_ID} poll`,
|
|
265
266
|
changes,
|
|
@@ -304,7 +305,7 @@ const stateMigrations = [
|
|
|
304
305
|
}
|
|
305
306
|
changes.push(`Migrated ${imported} ${MSTEAMS_PLUGIN_ID} SSO token ${imported === 1 ? "entry" : "entries"} -> plugin state`);
|
|
306
307
|
if (skipped > 0) warnings.push(`Skipped ${skipped} malformed ${MSTEAMS_PLUGIN_ID} SSO token ${skipped === 1 ? "entry" : "entries"} during migration`);
|
|
307
|
-
await (0,
|
|
308
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
308
309
|
filePath,
|
|
309
310
|
label: `${MSTEAMS_PLUGIN_ID} SSO-token`,
|
|
310
311
|
changes,
|
|
@@ -383,7 +384,7 @@ const stateMigrations = [
|
|
|
383
384
|
};
|
|
384
385
|
}
|
|
385
386
|
changes.push(`Migrated ${MSTEAMS_PLUGIN_ID} delegated OAuth token -> plugin state`);
|
|
386
|
-
await (0,
|
|
387
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
387
388
|
filePath,
|
|
388
389
|
label: `${MSTEAMS_PLUGIN_ID} delegated OAuth token`,
|
|
389
390
|
changes,
|
|
@@ -399,14 +400,14 @@ const stateMigrations = [
|
|
|
399
400
|
id: "msteams-feedback-learnings-json-to-plugin-state",
|
|
400
401
|
label: "Microsoft Teams feedback learnings",
|
|
401
402
|
async detectLegacyState(params) {
|
|
402
|
-
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
403
|
+
const files = (await Promise.all((await listCandidateStorePaths(params)).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
403
404
|
if (files.length === 0) return null;
|
|
404
405
|
return { preview: [`- Microsoft Teams feedback learnings: ${files.length} ${files.length === 1 ? "file" : "files"} -> plugin state (${LEARNINGS_NAMESPACE})`] };
|
|
405
406
|
},
|
|
406
407
|
async migrateLegacyState(params) {
|
|
407
408
|
const changes = [];
|
|
408
409
|
const warnings = [];
|
|
409
|
-
const files = (await Promise.all(listCandidateStorePaths(params).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
410
|
+
const files = (await Promise.all((await listCandidateStorePaths(params)).map((storePath) => listLegacyLearningFiles(storePath)))).flat();
|
|
410
411
|
const store = params.context.openPluginStateKeyedStore({
|
|
411
412
|
namespace: LEARNINGS_NAMESPACE,
|
|
412
413
|
maxEntries: MAX_LEARNING_ENTRIES
|
|
@@ -436,7 +437,7 @@ const stateMigrations = [
|
|
|
436
437
|
updatedAt: Date.now()
|
|
437
438
|
});
|
|
438
439
|
imported++;
|
|
439
|
-
await (0,
|
|
440
|
+
await (0, openclaw_plugin_sdk_runtime_doctor_migrations.archiveLegacyStateSource)({
|
|
440
441
|
filePath: file.filePath,
|
|
441
442
|
label: "Microsoft Teams feedback-learning",
|
|
442
443
|
changes,
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_rolldown_runtime = require("./rolldown-runtime-D6vf50IK.cjs");
|
|
2
2
|
const require_runtime = require("./runtime-gZTAuFux.cjs");
|
|
3
3
|
require("./runtime-api.cjs");
|
|
4
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
5
|
-
const
|
|
4
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
|
|
5
|
+
const require_channel_setup = require("./channel.setup-mOFtsfYz.cjs");
|
|
6
|
+
const require_polls = require("./polls-DvuJvaDG.cjs");
|
|
6
7
|
let openclaw_plugin_sdk_lazy_runtime = require("openclaw/plugin-sdk/lazy-runtime");
|
|
7
8
|
let openclaw_plugin_sdk_string_coerce_runtime = require("openclaw/plugin-sdk/string-coerce-runtime");
|
|
9
|
+
let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
|
|
8
10
|
let openclaw_plugin_sdk_reply_payload = require("openclaw/plugin-sdk/reply-payload");
|
|
9
11
|
let openclaw_plugin_sdk_text_chunking = require("openclaw/plugin-sdk/text-chunking");
|
|
10
|
-
let openclaw_plugin_sdk_provider_http = require("openclaw/plugin-sdk/provider-http");
|
|
11
12
|
let node_dns_promises = require("node:dns/promises");
|
|
12
13
|
let openclaw_plugin_sdk_ssrf_policy = require("openclaw/plugin-sdk/ssrf-policy");
|
|
13
14
|
let openclaw_plugin_sdk_text_utility_runtime = require("openclaw/plugin-sdk/text-utility-runtime");
|
|
14
15
|
let openclaw_plugin_sdk_html_entity_runtime = require("openclaw/plugin-sdk/html-entity-runtime");
|
|
16
|
+
let openclaw_plugin_sdk_retry_runtime = require("openclaw/plugin-sdk/retry-runtime");
|
|
15
17
|
let node_crypto = require("node:crypto");
|
|
16
|
-
node_crypto =
|
|
18
|
+
node_crypto = require_rolldown_runtime.__toESM(node_crypto, 1);
|
|
17
19
|
let node_path = require("node:path");
|
|
18
|
-
node_path =
|
|
20
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
21
|
+
let openclaw_plugin_sdk_global_singleton = require("openclaw/plugin-sdk/global-singleton");
|
|
19
22
|
let openclaw_plugin_sdk_error_runtime = require("openclaw/plugin-sdk/error-runtime");
|
|
20
23
|
let openclaw_plugin_sdk_reply_chunking = require("openclaw/plugin-sdk/reply-chunking");
|
|
24
|
+
let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
|
|
21
25
|
let openclaw_plugin_sdk_web_media = require("openclaw/plugin-sdk/web-media");
|
|
22
26
|
let openclaw_plugin_sdk_media_runtime = require("openclaw/plugin-sdk/media-runtime");
|
|
23
27
|
//#region extensions/msteams/src/graph-thread.ts
|
|
@@ -449,9 +453,15 @@ async function setPendingUploadActivityIdFs(id, activityId, options) {
|
|
|
449
453
|
* before upload. This module stores the file data temporarily until the user
|
|
450
454
|
* accepts or declines, or until the TTL expires.
|
|
451
455
|
*/
|
|
452
|
-
const pendingUploads =
|
|
453
|
-
|
|
454
|
-
|
|
456
|
+
const { pendingUploads, pendingUploadTimers } = (0, openclaw_plugin_sdk_global_singleton.resolveGlobalSingleton)(Symbol.for("openclaw.msteams.pendingUploadState"), () => ({
|
|
457
|
+
pendingUploads: /* @__PURE__ */ new Map(),
|
|
458
|
+
/** Timer handles keyed by upload ID, cleared on explicit removal to prevent ghost cleanup. */
|
|
459
|
+
pendingUploadTimers: /* @__PURE__ */ new Map()
|
|
460
|
+
}), (state) => {
|
|
461
|
+
for (const timer of state.pendingUploadTimers.values()) clearTimeout(timer);
|
|
462
|
+
state.pendingUploadTimers.clear();
|
|
463
|
+
state.pendingUploads.clear();
|
|
464
|
+
});
|
|
455
465
|
/** TTL for pending uploads: 5 minutes */
|
|
456
466
|
const PENDING_UPLOAD_TTL_MS = 300 * 1e3;
|
|
457
467
|
/**
|
|
@@ -1088,13 +1098,14 @@ async function getGraphAccessToken(tokenProvider) {
|
|
|
1088
1098
|
async function uploadToSharePoint(params) {
|
|
1089
1099
|
const fetchFn = params.fetchFn ?? fetch;
|
|
1090
1100
|
const uploadPath = `/OpenClawShared/${encodeURIComponent(params.filename)}`;
|
|
1101
|
+
const uploadUrl = `${GRAPH_ROOT}/sites/${params.siteId}/drive/root:${uploadPath}:/content?@microsoft.graph.conflictBehavior=rename`;
|
|
1091
1102
|
const timeoutMs = require_resolve_allowlist.resolveMSTeamsSharePointUploadTimeoutMs(params.buffer.length);
|
|
1092
1103
|
const data = await require_resolve_allowlist.withMSTeamsAbortableRequestTimeout({
|
|
1093
1104
|
label: SHAREPOINT_UPLOAD_TIMEOUT_LABEL,
|
|
1094
1105
|
timeoutMs,
|
|
1095
1106
|
work: async (signal) => {
|
|
1096
1107
|
const token = await getGraphAccessToken(params.tokenProvider);
|
|
1097
|
-
const res = await fetchFn(
|
|
1108
|
+
const res = await fetchFn(uploadUrl, {
|
|
1098
1109
|
method: "PUT",
|
|
1099
1110
|
headers: {
|
|
1100
1111
|
"User-Agent": require_resolve_allowlist.buildUserAgent(),
|
|
@@ -1297,7 +1308,7 @@ async function extractFilename(url) {
|
|
|
1297
1308
|
* Check if a URL refers to a local file path.
|
|
1298
1309
|
*/
|
|
1299
1310
|
function isLocalPath(url) {
|
|
1300
|
-
if (
|
|
1311
|
+
if (/^file:\/\//iu.test(url) || url.startsWith("/") || url.startsWith("~")) return true;
|
|
1301
1312
|
if (url.startsWith("\\") && !url.startsWith("\\\\")) return true;
|
|
1302
1313
|
if (/^[a-zA-Z]:[\\/]/.test(url)) return true;
|
|
1303
1314
|
if (url.startsWith("\\\\")) return true;
|
|
@@ -1314,6 +1325,15 @@ function extractMessageId(response) {
|
|
|
1314
1325
|
return id;
|
|
1315
1326
|
}
|
|
1316
1327
|
//#endregion
|
|
1328
|
+
//#region extensions/msteams/src/ai-entity.ts
|
|
1329
|
+
/** AI-generated content entity added to every outbound AI message. */
|
|
1330
|
+
const AI_GENERATED_ENTITY = {
|
|
1331
|
+
type: "https://schema.org/Message",
|
|
1332
|
+
"@type": "Message",
|
|
1333
|
+
"@id": "",
|
|
1334
|
+
additionalType: ["AIGeneratedContent"]
|
|
1335
|
+
};
|
|
1336
|
+
//#endregion
|
|
1317
1337
|
//#region extensions/msteams/src/mentions.ts
|
|
1318
1338
|
/**
|
|
1319
1339
|
* Check whether an ID looks like a valid Teams user/bot identifier.
|
|
@@ -1367,14 +1387,21 @@ async function withRevokedProxyFallback(params) {
|
|
|
1367
1387
|
try {
|
|
1368
1388
|
return await params.run();
|
|
1369
1389
|
} catch (err) {
|
|
1370
|
-
if (!
|
|
1390
|
+
if (!require_channel_setup.isRevokedProxyError(err)) throw err;
|
|
1371
1391
|
params.onRevokedLog?.();
|
|
1372
1392
|
return await params.onRevoked();
|
|
1373
1393
|
}
|
|
1374
1394
|
}
|
|
1375
1395
|
//#endregion
|
|
1376
1396
|
//#region extensions/msteams/src/sdk-proactive.ts
|
|
1377
|
-
const
|
|
1397
|
+
const loadMSTeamsApiClient = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api").then((api) => ({ Client: api.Client })));
|
|
1398
|
+
const loadMSTeamsQuoteModule = (0, openclaw_plugin_sdk_lazy_runtime.createLazyRuntimeModule)(() => import("@microsoft/teams.api/dist/activities/message/message.js").then((message) => ({ MessageActivityInput: message.MessageActivityInput })));
|
|
1399
|
+
async function quoteMSTeamsActivity(activity, messageId) {
|
|
1400
|
+
const { MessageActivityInput } = await loadMSTeamsQuoteModule();
|
|
1401
|
+
if (typeof activity === "string") return new MessageActivityInput(activity).prependQuote(messageId);
|
|
1402
|
+
if (activity.type !== "message") return activity;
|
|
1403
|
+
return MessageActivityInput.from(activity).prependQuote(messageId);
|
|
1404
|
+
}
|
|
1378
1405
|
function resolveThreadedConversationId(conversationId, threadActivityId) {
|
|
1379
1406
|
if (!threadActivityId) return conversationId.split(";")[0] ?? conversationId;
|
|
1380
1407
|
return `${conversationId.split(";")[0] ?? conversationId};messageid=${threadActivityId}`;
|
|
@@ -1439,7 +1466,7 @@ async function getApiClientForReference(app, ref) {
|
|
|
1439
1466
|
const appInternals = app;
|
|
1440
1467
|
const httpClient = appInternals.api?.http ?? appInternals.client;
|
|
1441
1468
|
if (!httpClient) return api;
|
|
1442
|
-
const { Client } = await
|
|
1469
|
+
const { Client } = await loadMSTeamsApiClient();
|
|
1443
1470
|
return new Client(ref.serviceUrl, httpClient);
|
|
1444
1471
|
}
|
|
1445
1472
|
function mergeReferenceIntoActivity(activity, ref) {
|
|
@@ -1472,7 +1499,7 @@ function mergeReferenceIntoActivity(activity, ref) {
|
|
|
1472
1499
|
async function sendMSTeamsActivityWithReference(app, source, activity, options) {
|
|
1473
1500
|
const ref = buildSdkConversationReference(source, options);
|
|
1474
1501
|
const activities = (await getApiClientForReference(app, ref)).conversations.activities(ref.conversation.id);
|
|
1475
|
-
const activityWithRef = mergeReferenceIntoActivity(activity, ref);
|
|
1502
|
+
const activityWithRef = mergeReferenceIntoActivity(options?.quoteActivityId ? await quoteMSTeamsActivity(activity, options.quoteActivityId) : activity, ref);
|
|
1476
1503
|
const isTargeted = activityWithRef.recipient?.isTargeted === true;
|
|
1477
1504
|
if (isTargeted && ref.conversation.conversationType === "personal") throw new Error("Targeted messages are not supported in 1:1 (personal) chats.");
|
|
1478
1505
|
const activityId = typeof activityWithRef.id === "string" ? activityWithRef.id : void 0;
|
|
@@ -1498,15 +1525,6 @@ async function deleteMSTeamsActivityWithReference(app, source, activityId, optio
|
|
|
1498
1525
|
return (await getApiClientForReference(app, ref)).conversations.activities(ref.conversation.id).delete(activityId);
|
|
1499
1526
|
}
|
|
1500
1527
|
//#endregion
|
|
1501
|
-
//#region extensions/msteams/src/ai-entity.ts
|
|
1502
|
-
/** AI-generated content entity added to every outbound AI message. */
|
|
1503
|
-
const AI_GENERATED_ENTITY = {
|
|
1504
|
-
type: "https://schema.org/Message",
|
|
1505
|
-
"@type": "Message",
|
|
1506
|
-
"@id": "",
|
|
1507
|
-
additionalType: ["AIGeneratedContent"]
|
|
1508
|
-
};
|
|
1509
|
-
//#endregion
|
|
1510
1528
|
//#region extensions/msteams/src/messenger.ts
|
|
1511
1529
|
/**
|
|
1512
1530
|
* MSTeams-specific media size limit (100MB).
|
|
@@ -1582,12 +1600,9 @@ function resolveRetryOptions(retry) {
|
|
|
1582
1600
|
};
|
|
1583
1601
|
}
|
|
1584
1602
|
function computeRetryDelayMs(attempt, classification, opts) {
|
|
1585
|
-
if (classification.retryAfterMs != null) return clampMs(classification.retryAfterMs, opts.maxDelayMs);
|
|
1603
|
+
if (classification.kind === "replay-safe" && classification.retryAfterMs != null) return clampMs(classification.retryAfterMs, opts.maxDelayMs);
|
|
1586
1604
|
return clampMs(opts.baseDelayMs * 2 ** Math.max(0, attempt - 1), opts.maxDelayMs);
|
|
1587
1605
|
}
|
|
1588
|
-
function shouldRetry(classification) {
|
|
1589
|
-
return classification.kind === "throttled" || classification.kind === "transient";
|
|
1590
|
-
}
|
|
1591
1606
|
function renderReplyPayloadsToMessages(replies, options) {
|
|
1592
1607
|
const out = [];
|
|
1593
1608
|
const chunkLimit = Math.min(options.textChunkLimit, 4e3);
|
|
@@ -1711,24 +1726,24 @@ async function sendMSTeamsMessages(params) {
|
|
|
1711
1726
|
const retryOptions = resolveRetryOptions(params.retry);
|
|
1712
1727
|
const sendWithRetry = async (sendOnce, meta) => {
|
|
1713
1728
|
if (!retryOptions.enabled) return await sendOnce();
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1729
|
+
return await (0, openclaw_plugin_sdk_retry_runtime.retryAsync)(sendOnce, {
|
|
1730
|
+
attempts: retryOptions.maxAttempts,
|
|
1731
|
+
minDelayMs: 0,
|
|
1732
|
+
maxDelayMs: retryOptions.maxDelayMs,
|
|
1733
|
+
shouldRetry: (err) => require_channel_setup.classifyMSTeamsSendError(err).kind === "replay-safe",
|
|
1734
|
+
delayMs: ({ attempt, err }) => computeRetryDelayMs(attempt, require_channel_setup.classifyMSTeamsSendError(err), retryOptions),
|
|
1735
|
+
onRetry: ({ attempt, err, delayMs }) => {
|
|
1736
|
+
params.onRetry?.({
|
|
1737
|
+
messageIndex: meta.messageIndex,
|
|
1738
|
+
messageCount: meta.messageCount,
|
|
1739
|
+
nextAttempt: attempt + 1,
|
|
1740
|
+
maxAttempts: retryOptions.maxAttempts,
|
|
1741
|
+
delayMs,
|
|
1742
|
+
classification: require_channel_setup.classifyMSTeamsSendError(err)
|
|
1743
|
+
});
|
|
1744
|
+
},
|
|
1745
|
+
sleep: (delayMs) => (0, openclaw_plugin_sdk_runtime_env.sleepWithAbort)(delayMs)
|
|
1746
|
+
});
|
|
1732
1747
|
};
|
|
1733
1748
|
let providerDispatchStarted = false;
|
|
1734
1749
|
const sendMessageInContext = async (sendFn, message, messageIndex) => {
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
const require_resolve_allowlist = require("./resolve-allowlist-
|
|
1
|
+
const require_resolve_allowlist = require("./resolve-allowlist-CIfWUwuc.cjs");
|
|
2
|
+
let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
|
|
2
3
|
let openclaw_plugin_sdk_provider_auth = require("openclaw/plugin-sdk/provider-auth");
|
|
3
4
|
let openclaw_plugin_sdk_provider_auth_runtime = require("openclaw/plugin-sdk/provider-auth-runtime");
|
|
4
|
-
let openclaw_plugin_sdk_runtime_env = require("openclaw/plugin-sdk/runtime-env");
|
|
5
5
|
//#region extensions/msteams/src/oauth.flow.ts
|
|
6
6
|
function shouldUseManualOAuthFlow(isRemote) {
|
|
7
7
|
return isRemote || (0, openclaw_plugin_sdk_runtime_env.isWSL2Sync)();
|
|
8
8
|
}
|
|
9
|
-
function generatePkce() {
|
|
10
|
-
return (0, openclaw_plugin_sdk_provider_auth.generateHexPkceVerifierChallenge)();
|
|
11
|
-
}
|
|
12
9
|
function buildMSTeamsAuthUrl(params) {
|
|
13
10
|
const scopes = params.scopes ?? require_resolve_allowlist.MSTEAMS_DEFAULT_DELEGATED_SCOPES;
|
|
14
11
|
return `${require_resolve_allowlist.buildMSTeamsAuthEndpoint(params.tenantId)}?${new URLSearchParams({
|
|
@@ -22,24 +19,6 @@ function buildMSTeamsAuthUrl(params) {
|
|
|
22
19
|
prompt: "consent"
|
|
23
20
|
}).toString()}`;
|
|
24
21
|
}
|
|
25
|
-
function parseCallbackInput(input, _expectedState) {
|
|
26
|
-
return (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(input, {
|
|
27
|
-
missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
|
|
28
|
-
invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
async function waitForLocalCallback(params) {
|
|
32
|
-
return await (0, openclaw_plugin_sdk_provider_auth_runtime.waitForLocalOAuthCallback)({
|
|
33
|
-
expectedState: params.expectedState,
|
|
34
|
-
timeoutMs: params.timeoutMs,
|
|
35
|
-
port: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT,
|
|
36
|
-
callbackPath: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PATH,
|
|
37
|
-
redirectUri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
|
|
38
|
-
successTitle: "MSTeams Delegated OAuth complete",
|
|
39
|
-
progressMessage: `Waiting for OAuth callback on ${require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI}...`,
|
|
40
|
-
onProgress: params.onProgress
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
22
|
//#endregion
|
|
44
23
|
//#region extensions/msteams/src/oauth.ts
|
|
45
24
|
async function loginMSTeamsDelegated(ctx, params) {
|
|
@@ -54,7 +33,7 @@ async function loginMSTeamsDelegated(ctx, params) {
|
|
|
54
33
|
`Sign in to grant delegated permissions for MSTeams.`,
|
|
55
34
|
`The callback will be captured automatically on localhost:${require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT}.`
|
|
56
35
|
].join("\n"), "MSTeams Delegated OAuth");
|
|
57
|
-
const { verifier, challenge } =
|
|
36
|
+
const { verifier, challenge } = (0, openclaw_plugin_sdk_provider_auth.generateHexPkceVerifierChallenge)();
|
|
58
37
|
const state = (0, openclaw_plugin_sdk_provider_auth_runtime.generateOAuthState)();
|
|
59
38
|
const authUrl = buildMSTeamsAuthUrl({
|
|
60
39
|
tenantId: params.tenantId,
|
|
@@ -71,9 +50,14 @@ async function loginMSTeamsDelegated(ctx, params) {
|
|
|
71
50
|
ctx.log(`\nOpen this URL in your browser:\n\n${authUrl}\n`);
|
|
72
51
|
}
|
|
73
52
|
try {
|
|
74
|
-
const { code } = await
|
|
53
|
+
const { code } = await (0, openclaw_plugin_sdk_provider_auth_runtime.waitForLocalOAuthCallback)({
|
|
75
54
|
expectedState: state,
|
|
76
55
|
timeoutMs: 300 * 1e3,
|
|
56
|
+
port: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PORT,
|
|
57
|
+
callbackPath: require_resolve_allowlist.MSTEAMS_OAUTH_CALLBACK_PATH,
|
|
58
|
+
redirectUri: require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI,
|
|
59
|
+
successTitle: "MSTeams Delegated OAuth complete",
|
|
60
|
+
progressMessage: `Waiting for OAuth callback on ${require_resolve_allowlist.MSTEAMS_OAUTH_REDIRECT_URI}...`,
|
|
77
61
|
onProgress: (msg) => ctx.progress.update(msg)
|
|
78
62
|
});
|
|
79
63
|
ctx.progress.update("Exchanging authorization code for tokens...");
|
|
@@ -97,7 +81,10 @@ async function manualFlow(ctx, authUrl, state, verifier, params, cause) {
|
|
|
97
81
|
ctx.progress.update("OAuth URL ready");
|
|
98
82
|
ctx.log(`\nOpen this URL in your LOCAL browser:\n\n${authUrl}\n`);
|
|
99
83
|
ctx.progress.update("Waiting for you to paste the callback URL...");
|
|
100
|
-
const parsed =
|
|
84
|
+
const parsed = (0, openclaw_plugin_sdk_provider_auth_runtime.parseOAuthCallbackInput)(await ctx.prompt("Paste the redirect URL here: "), {
|
|
85
|
+
missingState: "Missing 'state' parameter in URL. Paste the full redirect URL.",
|
|
86
|
+
invalidInput: "Paste the full redirect URL (including code and state parameters), not just the authorization code."
|
|
87
|
+
});
|
|
101
88
|
if ("error" in parsed) throw new Error(parsed.error, cause ? { cause } : void 0);
|
|
102
89
|
if (parsed.state !== state) throw new Error("OAuth state mismatch - please try again", cause ? { cause } : void 0);
|
|
103
90
|
ctx.progress.update("Exchanging authorization code for tokens...");
|