@xmanrui/dsh-im 0.15.0 → 0.17.0
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/lib/client.js +233 -43
- package/lib/index.js +138 -131
- package/package.json +1 -1
- package/plugin-src/client/channels/feishu/api.js +23 -1
- package/plugin-src/client/channels/feishu/index.js +235 -46
- package/plugin-src/client/channels/feishu/styles.js +2 -0
- package/plugin-src/client/i18n.js +31 -0
- package/plugin-src/host/channels/feishu/production.mjs +3 -1
- package/plugin-src/host/channels/feishu/rpc.mjs +146 -12
- package/src/channels/discord/discord-api.mjs +1 -1
- package/src/channels/feishu/bridge.mjs +1080 -1
- package/src/channels/feishu/feishu-cards.mjs +230 -0
- package/src/channels/feishu/feishu-runtime.mjs +198 -0
- package/src/channels/feishu/multi-bot-controller.mjs +357 -2
- package/src/channels/feishu/plugin-controller.mjs +1 -0
- package/src/channels/feishu/repair-manager.mjs +109 -0
- package/src/channels/feishu/state-store.mjs +85 -1
- package/src/channels/shared/harness-client.mjs +119 -0
- package/src/channels/shared/workspace-command.mjs +2 -2
- package/src/channels/weixin/weixin-api.mjs +1 -1
package/lib/client.js
CHANGED
|
@@ -587,6 +587,27 @@ var EN = Object.freeze({
|
|
|
587
587
|
"\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA": "Keep this page open until the bot connection is ready",
|
|
588
588
|
"\u5728\u98DE\u4E66\u4E2D\u6253\u5F00": "Open in Feishu",
|
|
589
589
|
"\u53D6\u6D88\u6DFB\u52A0": "Cancel",
|
|
590
|
+
"\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Scan with Feishu to repair card buttons",
|
|
591
|
+
"\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the card-button callback. It does not create a new app. This bot reconnects briefly after confirmation; other bots are not affected.",
|
|
592
|
+
"\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03": "Review the existing app name and confirm that only the card callback is added",
|
|
593
|
+
"\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210": "Keep this page open until card-button repair finishes",
|
|
594
|
+
"\u53D6\u6D88\u4FEE\u590D": "Cancel repair",
|
|
595
|
+
"\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D": "Confirmed. Finishing card-button repair",
|
|
596
|
+
"\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801": "Preparing the repair QR code",
|
|
597
|
+
"\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The update was submitted. Verifying the card callback and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
|
|
598
|
+
"\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a one-time update QR code for the existing Feishu app\u2026",
|
|
599
|
+
"\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210": "Card-button repair did not finish",
|
|
600
|
+
"\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Repair card buttons",
|
|
601
|
+
"\u7B49\u5F85\u626B\u7801\u2026": "Waiting for scan\u2026",
|
|
602
|
+
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801": "Feishu returned a repair QR code for a different bot",
|
|
603
|
+
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu repair status is missing the bot ID",
|
|
604
|
+
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6": "Feishu returned registration progress for a different operation",
|
|
605
|
+
"\u6B64\u673A\u5668\u4EBA": "this bot",
|
|
606
|
+
'${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002': 'Repair QR code generated for ${botName ?? "bot"}. Scan it with Feishu.',
|
|
607
|
+
"${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002": "${targetBot.bot.name} is connected and ready to chat in Feishu.",
|
|
608
|
+
"\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002": "Card-button repair was cancelled.",
|
|
609
|
+
"\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The card callback was updated, but the bot connection could not be confirmed yet",
|
|
610
|
+
"\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25": "Could not repair the Feishu card buttons",
|
|
590
611
|
"\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA": "Confirmed. Connecting the new bot",
|
|
591
612
|
"\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "Saving credentials and checking the new bot connection. Existing bots will not be interrupted.",
|
|
592
613
|
"\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a one-time authorization QR code from Feishu\u2026",
|
|
@@ -865,6 +886,16 @@ function translateDynamic(text5) {
|
|
|
865
886
|
if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
|
|
866
887
|
match = /^从 DeepSeek Harness 移除(.+)$/.exec(text5);
|
|
867
888
|
if (match) return `Remove ${match[1]} from DeepSeek Harness`;
|
|
889
|
+
match = /^用于修复(.+)卡片按钮的一次性授权二维码$/.exec(text5);
|
|
890
|
+
if (match) return `One-time QR code for repairing card buttons for ${match[1]}`;
|
|
891
|
+
match = /^正在修复「(.+)」$/.exec(text5);
|
|
892
|
+
if (match) return `Repairing \u201C${match[1]}\u201D`;
|
|
893
|
+
match = /^修复(.+)的卡片按钮$/.exec(text5);
|
|
894
|
+
if (match) return `Repair card buttons for ${match[1]}`;
|
|
895
|
+
match = /^(.+)的修复二维码已生成,请使用飞书扫码。$/.exec(text5);
|
|
896
|
+
if (match) return `Repair QR code generated for ${match[1]}. Scan it with Feishu.`;
|
|
897
|
+
match = /^(.+)的卡片按钮已修复。$/.exec(text5);
|
|
898
|
+
if (match) return `Card buttons repaired for ${match[1]}.`;
|
|
868
899
|
match = /^(检查连接|重试连接)(.+)$/.exec(text5);
|
|
869
900
|
if (match) return `${localizeText(match[1])} ${match[2]}`;
|
|
870
901
|
match = /^移除(.+)$/.exec(text5);
|
|
@@ -3039,6 +3070,7 @@ var FEISHU_RPC_CHANNEL = "/feishu";
|
|
|
3039
3070
|
var FEISHU_ENDPOINTS = Object.freeze({
|
|
3040
3071
|
status: "connection.status",
|
|
3041
3072
|
beginProvisioning: "provision.begin",
|
|
3073
|
+
beginCallbackRepair: "bot.callback-repair.begin",
|
|
3042
3074
|
pollProvisioning: "provision.poll",
|
|
3043
3075
|
cancelProvisioning: "provision.cancel",
|
|
3044
3076
|
bindCredentials: "bot.bind-credentials",
|
|
@@ -3050,6 +3082,10 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
3050
3082
|
testConnection: "connection.test",
|
|
3051
3083
|
disconnect: "connection.disconnect"
|
|
3052
3084
|
});
|
|
3085
|
+
var FEISHU_REGISTRATION_OPERATIONS = Object.freeze({
|
|
3086
|
+
PROVISION: "provision",
|
|
3087
|
+
CALLBACK_REPAIR: "callback_repair"
|
|
3088
|
+
});
|
|
3053
3089
|
var CONNECTION_STATES = /* @__PURE__ */ new Set([
|
|
3054
3090
|
"disconnected",
|
|
3055
3091
|
"offline",
|
|
@@ -3084,6 +3120,9 @@ function optionalTimestamp(value) {
|
|
|
3084
3120
|
function clamp2(value, min, max, fallback) {
|
|
3085
3121
|
return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
|
|
3086
3122
|
}
|
|
3123
|
+
function normalizeRegistrationOperation(value) {
|
|
3124
|
+
return value === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR ? FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR : FEISHU_REGISTRATION_OPERATIONS.PROVISION;
|
|
3125
|
+
}
|
|
3087
3126
|
function unwrapRpcResult3(result) {
|
|
3088
3127
|
if (!isRecord3(result) || typeof result.ok !== "boolean") {
|
|
3089
3128
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
@@ -3102,15 +3141,24 @@ function normalizeProvisioning2(value, now = Date.now()) {
|
|
|
3102
3141
|
const attemptId = optionalString2(source.attemptId) ?? optionalString2(source.provisioningId);
|
|
3103
3142
|
const verificationUrl = optionalString2(source.verificationUrl);
|
|
3104
3143
|
const qrCodeDataUrl = optionalString2(source.qrCodeDataUrl);
|
|
3105
|
-
|
|
3144
|
+
const submitted = source.submitted === true;
|
|
3145
|
+
if (!attemptId || !verificationUrl && !qrCodeDataUrl && !submitted) {
|
|
3106
3146
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u4FE1\u606F\u4E0D\u5B8C\u6574");
|
|
3107
3147
|
}
|
|
3108
3148
|
const explicitExpiry = optionalTimestamp(source.expiresAt);
|
|
3109
3149
|
const expireIn = clamp2(source.expireIn, 1, 60 * 60, 5 * 60);
|
|
3150
|
+
const operation = normalizeRegistrationOperation(source.operation);
|
|
3151
|
+
const botId = optionalString2(source.botId);
|
|
3152
|
+
if (operation === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR && !botId) {
|
|
3153
|
+
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId");
|
|
3154
|
+
}
|
|
3110
3155
|
return {
|
|
3111
3156
|
attemptId,
|
|
3157
|
+
operation,
|
|
3158
|
+
botId,
|
|
3112
3159
|
verificationUrl,
|
|
3113
3160
|
qrCodeDataUrl,
|
|
3161
|
+
submitted,
|
|
3114
3162
|
expiresAt: explicitExpiry ?? now + expireIn * 1e3,
|
|
3115
3163
|
pollIntervalMs: clamp2(source.pollIntervalMs, 800, 1e4, 1800)
|
|
3116
3164
|
};
|
|
@@ -3228,6 +3276,7 @@ function normalizePollResult(value) {
|
|
|
3228
3276
|
if (!status) throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u672A\u77E5\u7684\u521B\u5EFA\u72B6\u6001");
|
|
3229
3277
|
const normalized = {
|
|
3230
3278
|
status,
|
|
3279
|
+
operation: normalizeRegistrationOperation(value.operation),
|
|
3231
3280
|
botId: optionalString2(value.botId),
|
|
3232
3281
|
message: optionalString2(value.error?.message) ?? optionalString2(value.message),
|
|
3233
3282
|
connection: void 0,
|
|
@@ -3746,6 +3795,8 @@ var CSS3 = String.raw`
|
|
|
3746
3795
|
.bxf-healthSummary[data-error="true"] { color: var(--bxf-error); }
|
|
3747
3796
|
.bxf-botActions { flex: none; flex-wrap: nowrap; gap: 8px; margin-top: 0; justify-content: flex-end; }
|
|
3748
3797
|
.bxf-botActions .bxf-button { flex: none; white-space: nowrap; }
|
|
3798
|
+
.bxf-botActions .bxf-repairButton { color: var(--bxf-accent); border-color: color-mix(in srgb, var(--bxf-accent) 35%, var(--dsw-alias-border-l2, #dee0e3)); }
|
|
3799
|
+
.bxf-botActions .bxf-repairButton:hover:not(:disabled) { background: color-mix(in srgb, var(--bxf-accent) 7%, transparent); }
|
|
3749
3800
|
|
|
3750
3801
|
.bxf-confirm {
|
|
3751
3802
|
border-top: 1px solid var(--dsw-alias-border-l2, #dee0e3);
|
|
@@ -3837,6 +3888,10 @@ function installFeishuStyles() {
|
|
|
3837
3888
|
}
|
|
3838
3889
|
|
|
3839
3890
|
// plugin-src/client/channels/feishu/index.js
|
|
3891
|
+
var CALLBACK_REPAIR_OPERATION = FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
|
|
3892
|
+
function isCallbackRepair(value) {
|
|
3893
|
+
return value?.operation === CALLBACK_REPAIR_OPERATION;
|
|
3894
|
+
}
|
|
3840
3895
|
function SvgIcon({ children, size = 18, className, viewBox = "0 0 24 24" }) {
|
|
3841
3896
|
return h2("svg", {
|
|
3842
3897
|
width: size,
|
|
@@ -3996,7 +4051,12 @@ function safeVerificationHref(value) {
|
|
|
3996
4051
|
if (!value) return void 0;
|
|
3997
4052
|
try {
|
|
3998
4053
|
const url = new URL(value);
|
|
3999
|
-
return url.protocol === "https:"
|
|
4054
|
+
return url.protocol === "https:" && [
|
|
4055
|
+
"accounts.feishu.cn",
|
|
4056
|
+
"accounts.larksuite.com",
|
|
4057
|
+
"open.feishu.cn",
|
|
4058
|
+
"open.larksuite.com"
|
|
4059
|
+
].includes(url.hostname) && !url.port && !url.username && !url.password ? url.toString() : void 0;
|
|
4000
4060
|
} catch {
|
|
4001
4061
|
return void 0;
|
|
4002
4062
|
}
|
|
@@ -4012,6 +4072,8 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4012
4072
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
4013
4073
|
const expired = provision.expired === true || remaining === 0;
|
|
4014
4074
|
const progress = Math.min(1, remaining / Math.max(1, provision.durationMs ?? remaining));
|
|
4075
|
+
const repairing = isCallbackRepair(provision);
|
|
4076
|
+
const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
|
|
4015
4077
|
React10.useEffect(() => setImageFailed(false), [qrSource]);
|
|
4016
4078
|
return h2(
|
|
4017
4079
|
"div",
|
|
@@ -4027,7 +4089,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4027
4089
|
{ className: "bxf-qrFrame dim-qrFrame" },
|
|
4028
4090
|
qrSource && !imageFailed ? h2("img", {
|
|
4029
4091
|
src: qrSource,
|
|
4030
|
-
alt: "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
|
|
4092
|
+
alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
|
|
4031
4093
|
onError: () => setImageFailed(true)
|
|
4032
4094
|
}) : h2(
|
|
4033
4095
|
"div",
|
|
@@ -4066,16 +4128,16 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4066
4128
|
"div",
|
|
4067
4129
|
{ className: "bxf-stateLabel dim-stateLabel" },
|
|
4068
4130
|
h2("span", { className: "bxf-dot dim-stateDot", "data-tone": "warning" }),
|
|
4069
|
-
h2("span", null, "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
|
|
4131
|
+
h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
|
|
4070
4132
|
),
|
|
4071
|
-
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
4072
|
-
h2("p", null, "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
|
|
4133
|
+
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
4134
|
+
h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
|
|
4073
4135
|
h2(
|
|
4074
4136
|
"ol",
|
|
4075
4137
|
{ className: "bxf-steps dim-steps" },
|
|
4076
4138
|
h2("li", null, "\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801"),
|
|
4077
|
-
h2("li", null, "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
|
|
4078
|
-
h2("li", null, "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
|
|
4139
|
+
h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
|
|
4140
|
+
h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
|
|
4079
4141
|
),
|
|
4080
4142
|
h2(
|
|
4081
4143
|
"div",
|
|
@@ -4092,14 +4154,15 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4092
4154
|
rel: "noopener noreferrer"
|
|
4093
4155
|
}, h2("span", null, "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00")) : null,
|
|
4094
4156
|
!expired ? h2(Button5, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
|
|
4095
|
-
h2(Button5, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88\u6DFB\u52A0")
|
|
4157
|
+
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4096
4158
|
)
|
|
4097
4159
|
)
|
|
4098
4160
|
)
|
|
4099
4161
|
);
|
|
4100
4162
|
}
|
|
4101
|
-
function ProvisionProgress({ phase, onCancel, busy }) {
|
|
4163
|
+
function ProvisionProgress({ phase, provision, onCancel, busy }) {
|
|
4102
4164
|
const connecting = phase === "connecting";
|
|
4165
|
+
const repairing = isCallbackRepair(provision);
|
|
4103
4166
|
return h2(
|
|
4104
4167
|
"div",
|
|
4105
4168
|
{
|
|
@@ -4107,16 +4170,17 @@ function ProvisionProgress({ phase, onCancel, busy }) {
|
|
|
4107
4170
|
"aria-busy": "true"
|
|
4108
4171
|
},
|
|
4109
4172
|
h2("div", { className: "dim-spinner", "aria-hidden": "true" }),
|
|
4110
|
-
h2("h3", null, connecting ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
|
|
4111
|
-
h2("p", null, connecting ? "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
|
|
4112
|
-
connecting ? h2(
|
|
4173
|
+
h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
|
|
4174
|
+
h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
|
|
4175
|
+
connecting && onCancel ? h2(
|
|
4113
4176
|
"div",
|
|
4114
4177
|
{ className: "bxf-actions dim-viewActions", style: { justifyContent: "center" } },
|
|
4115
|
-
h2(Button5, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88\u6DFB\u52A0")
|
|
4178
|
+
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4116
4179
|
) : null
|
|
4117
4180
|
);
|
|
4118
4181
|
}
|
|
4119
|
-
function ProvisionError2({ error, onRetry, onCancel, busy }) {
|
|
4182
|
+
function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
|
|
4183
|
+
const repairing = isCallbackRepair(provision);
|
|
4120
4184
|
return h2(
|
|
4121
4185
|
"div",
|
|
4122
4186
|
{ className: "bxf-card bxf-provisionCard dim-surfaceCard" },
|
|
@@ -4126,7 +4190,7 @@ function ProvisionError2({ error, onRetry, onCancel, busy }) {
|
|
|
4126
4190
|
h2(
|
|
4127
4191
|
"div",
|
|
4128
4192
|
null,
|
|
4129
|
-
h2("h3", null, "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
|
|
4193
|
+
h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
|
|
4130
4194
|
h2("p", null, error.message),
|
|
4131
4195
|
error.code ? h2("span", { className: "bxf-errorCode" }, error.code) : null,
|
|
4132
4196
|
h2(
|
|
@@ -4211,10 +4275,12 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
|
4211
4275
|
function BotCard({
|
|
4212
4276
|
connection,
|
|
4213
4277
|
busy,
|
|
4278
|
+
repairDisabled,
|
|
4214
4279
|
actionError,
|
|
4215
4280
|
testNotice,
|
|
4216
4281
|
removing,
|
|
4217
4282
|
onReconnect,
|
|
4283
|
+
onRepairCallback,
|
|
4218
4284
|
onWorkspaceSave,
|
|
4219
4285
|
onRequestRemove,
|
|
4220
4286
|
onConfirmRemove,
|
|
@@ -4307,6 +4373,13 @@ function BotCard({
|
|
|
4307
4373
|
"aria-busy": busy === "reconnect" ? "true" : void 0,
|
|
4308
4374
|
"aria-label": `${connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"}${bot.name}`
|
|
4309
4375
|
}, busy === "reconnect" ? connected ? "\u68C0\u67E5\u4E2D\u2026" : "\u6B63\u5728\u8FDE\u63A5\u2026" : connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
|
|
4376
|
+
h2(Button5, {
|
|
4377
|
+
className: "bxf-repairButton dim-cardAction",
|
|
4378
|
+
onClick: onRepairCallback,
|
|
4379
|
+
disabled: Boolean(busy) || repairDisabled,
|
|
4380
|
+
"aria-busy": busy === "callback-repair" ? "true" : void 0,
|
|
4381
|
+
"aria-label": `\u4FEE\u590D${bot.name}\u7684\u5361\u7247\u6309\u94AE`
|
|
4382
|
+
}, busy === "callback-repair" ? "\u7B49\u5F85\u626B\u7801\u2026" : "\u4FEE\u590D\u5361\u7247\u6309\u94AE"),
|
|
4310
4383
|
h2(Button5, {
|
|
4311
4384
|
className: "dim-cardAction",
|
|
4312
4385
|
kind: "danger",
|
|
@@ -4343,11 +4416,13 @@ function BotList(props) {
|
|
|
4343
4416
|
{ key: bot.botId },
|
|
4344
4417
|
h2(BotCard, {
|
|
4345
4418
|
connection: bot,
|
|
4346
|
-
busy: props.busyByBot[bot.botId],
|
|
4419
|
+
busy: props.busyByBot[bot.botId] ?? (isCallbackRepair(props.provisioning) && props.provisioning.botId === bot.botId ? "callback-repair" : void 0),
|
|
4420
|
+
repairDisabled: Boolean(props.provisioning),
|
|
4347
4421
|
actionError: props.errorsByBot[bot.botId],
|
|
4348
4422
|
testNotice: props.testNoticesByBot[bot.botId],
|
|
4349
4423
|
removing: props.removeTargetId === bot.botId,
|
|
4350
4424
|
onReconnect: () => props.onReconnect(bot),
|
|
4425
|
+
onRepairCallback: () => props.onRepairCallback(bot),
|
|
4351
4426
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
|
|
4352
4427
|
onRequestRemove: () => props.onRequestRemove(bot),
|
|
4353
4428
|
onConfirmRemove: () => props.onConfirmRemove(bot),
|
|
@@ -4390,11 +4465,12 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
|
|
|
4390
4465
|
if (snapshot.revision > 0 && current.revision > snapshot.revision) return current;
|
|
4391
4466
|
let provisioning = current.provisioning;
|
|
4392
4467
|
if (!provisioning && restoreProvisioning && snapshot.provisioning) {
|
|
4468
|
+
const submitted = snapshot.provisioning.submitted === true;
|
|
4393
4469
|
provisioning = {
|
|
4394
|
-
phase: snapshot.state === "connecting" ? "connecting" : "qr",
|
|
4470
|
+
phase: submitted || snapshot.state === "connecting" ? "connecting" : "qr",
|
|
4395
4471
|
...snapshot.provisioning,
|
|
4396
4472
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - now),
|
|
4397
|
-
expired: snapshot.provisioning.expiresAt <= now
|
|
4473
|
+
expired: !submitted && snapshot.provisioning.expiresAt <= now
|
|
4398
4474
|
};
|
|
4399
4475
|
}
|
|
4400
4476
|
return {
|
|
@@ -4509,7 +4585,15 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4509
4585
|
node.focus({ preventScroll: true });
|
|
4510
4586
|
setFocusBotId(null);
|
|
4511
4587
|
}, [focusBotId, model.bots]);
|
|
4512
|
-
const startProvisioning = React10.useCallback(async ({
|
|
4588
|
+
const startProvisioning = React10.useCallback(async ({
|
|
4589
|
+
replace = false,
|
|
4590
|
+
operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
|
|
4591
|
+
bot
|
|
4592
|
+
} = {}) => {
|
|
4593
|
+
const repairing = operation === CALLBACK_REPAIR_OPERATION;
|
|
4594
|
+
const botId = repairing ? bot?.botId ?? model.provisioning?.botId : void 0;
|
|
4595
|
+
const botName = repairing ? bot?.bot?.name ?? model.provisioning?.botName : void 0;
|
|
4596
|
+
if (repairing && !botId) return;
|
|
4513
4597
|
setCredentialOpen(false);
|
|
4514
4598
|
setCredentialError(null);
|
|
4515
4599
|
setProvisionBusy(true);
|
|
@@ -4518,16 +4602,27 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4518
4602
|
setModel((current) => ({
|
|
4519
4603
|
...current,
|
|
4520
4604
|
phase: current.phase === "loading" ? "ready" : current.phase,
|
|
4521
|
-
provisioning: {
|
|
4605
|
+
provisioning: {
|
|
4606
|
+
phase: "creating",
|
|
4607
|
+
operation,
|
|
4608
|
+
...botId ? { botId } : {},
|
|
4609
|
+
...botName ? { botName } : {}
|
|
4610
|
+
}
|
|
4522
4611
|
}));
|
|
4523
4612
|
try {
|
|
4524
4613
|
if (replace && previousAttemptId) {
|
|
4525
|
-
|
|
4614
|
+
try {
|
|
4615
|
+
await invoke(FEISHU_ENDPOINTS.cancelProvisioning, { attemptId: previousAttemptId });
|
|
4616
|
+
} catch {
|
|
4617
|
+
}
|
|
4526
4618
|
}
|
|
4527
4619
|
const provision2 = normalizeProvisioning2(await invoke(
|
|
4528
|
-
FEISHU_ENDPOINTS.beginProvisioning,
|
|
4529
|
-
{ locale: "zh-CN" }
|
|
4620
|
+
repairing ? FEISHU_ENDPOINTS.beginCallbackRepair : FEISHU_ENDPOINTS.beginProvisioning,
|
|
4621
|
+
repairing ? { botId } : { locale: "zh-CN" }
|
|
4530
4622
|
));
|
|
4623
|
+
if (repairing && (provision2.operation !== CALLBACK_REPAIR_OPERATION || provision2.botId !== botId)) {
|
|
4624
|
+
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
|
|
4625
|
+
}
|
|
4531
4626
|
const timestamp7 = Date.now();
|
|
4532
4627
|
setNow(timestamp7);
|
|
4533
4628
|
setModel((current) => ({
|
|
@@ -4535,20 +4630,34 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4535
4630
|
provisioning: {
|
|
4536
4631
|
phase: "qr",
|
|
4537
4632
|
...provision2,
|
|
4633
|
+
...botName ? { botName } : {},
|
|
4538
4634
|
durationMs: Math.max(1, provision2.expiresAt - timestamp7),
|
|
4539
4635
|
expired: false
|
|
4540
4636
|
}
|
|
4541
4637
|
}));
|
|
4542
|
-
announce("\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
|
|
4638
|
+
announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
|
|
4543
4639
|
} catch (error) {
|
|
4544
4640
|
setModel((current) => ({
|
|
4545
4641
|
...current,
|
|
4546
|
-
provisioning: {
|
|
4642
|
+
provisioning: {
|
|
4643
|
+
phase: "error",
|
|
4644
|
+
operation,
|
|
4645
|
+
...botId ? { botId } : {},
|
|
4646
|
+
...botName ? { botName } : {},
|
|
4647
|
+
...replace && previousAttemptId ? { attemptId: previousAttemptId } : {},
|
|
4648
|
+
error: presentError3(error)
|
|
4649
|
+
}
|
|
4547
4650
|
}));
|
|
4548
4651
|
} finally {
|
|
4549
4652
|
setProvisionBusy(false);
|
|
4550
4653
|
}
|
|
4551
|
-
}, [
|
|
4654
|
+
}, [
|
|
4655
|
+
announce,
|
|
4656
|
+
invoke,
|
|
4657
|
+
model.provisioning?.attemptId,
|
|
4658
|
+
model.provisioning?.botId,
|
|
4659
|
+
model.provisioning?.botName
|
|
4660
|
+
]);
|
|
4552
4661
|
const bindCredentials = React10.useCallback(async ({ identity, secret }) => {
|
|
4553
4662
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4554
4663
|
setCredentialBusy(true);
|
|
@@ -4572,23 +4681,64 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4572
4681
|
}
|
|
4573
4682
|
}, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
|
|
4574
4683
|
const cancelProvisioning = React10.useCallback(async () => {
|
|
4575
|
-
const
|
|
4684
|
+
const activeProvision = model.provisioning;
|
|
4685
|
+
const attemptId = activeProvision?.attemptId;
|
|
4686
|
+
const repairing = isCallbackRepair(activeProvision);
|
|
4687
|
+
const targetBot = repairing ? model.bots.find((bot) => bot.botId === activeProvision?.botId) : void 0;
|
|
4576
4688
|
setProvisionBusy(true);
|
|
4577
4689
|
try {
|
|
4578
|
-
|
|
4690
|
+
const result = attemptId ? normalizePollResult(await invoke(FEISHU_ENDPOINTS.cancelProvisioning, { attemptId })) : null;
|
|
4691
|
+
if (repairing && result) {
|
|
4692
|
+
if (result.operation !== CALLBACK_REPAIR_OPERATION || result.botId !== activeProvision.botId) {
|
|
4693
|
+
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
|
|
4694
|
+
}
|
|
4695
|
+
if (result.status === "connecting") {
|
|
4696
|
+
setModel((current) => current.provisioning?.attemptId === attemptId ? {
|
|
4697
|
+
...current,
|
|
4698
|
+
provisioning: {
|
|
4699
|
+
...current.provisioning,
|
|
4700
|
+
...result.provisioning ?? {},
|
|
4701
|
+
phase: "connecting",
|
|
4702
|
+
submitted: true,
|
|
4703
|
+
expired: false
|
|
4704
|
+
}
|
|
4705
|
+
} : current);
|
|
4706
|
+
announce("\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
|
|
4707
|
+
return;
|
|
4708
|
+
}
|
|
4709
|
+
if (result.status === "connected") {
|
|
4710
|
+
const targetBotName = targetBot?.bot.name ?? activeProvision.botName ?? "\u673A\u5668\u4EBA";
|
|
4711
|
+
setModel((current) => ({ ...current, provisioning: null }));
|
|
4712
|
+
announce(`${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
|
|
4713
|
+
if (activeProvision.botId) setFocusBotId(activeProvision.botId);
|
|
4714
|
+
await loadStatus({ silent: true, restoreProvisioning: false });
|
|
4715
|
+
return;
|
|
4716
|
+
}
|
|
4717
|
+
}
|
|
4579
4718
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4580
|
-
announce("\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
|
|
4719
|
+
announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
|
|
4581
4720
|
await loadStatus({ silent: true, restoreProvisioning: false });
|
|
4582
|
-
scheduleAnimationFrame(() =>
|
|
4721
|
+
scheduleAnimationFrame(() => {
|
|
4722
|
+
if (repairing && activeProvision.botId) {
|
|
4723
|
+
cardRefs.current.get(activeProvision.botId)?.focus();
|
|
4724
|
+
} else {
|
|
4725
|
+
addButtonRef.current?.focus();
|
|
4726
|
+
}
|
|
4727
|
+
}, "focus");
|
|
4583
4728
|
} catch (error) {
|
|
4584
4729
|
setModel((current) => ({
|
|
4585
4730
|
...current,
|
|
4586
|
-
provisioning: {
|
|
4731
|
+
provisioning: {
|
|
4732
|
+
...activeProvision,
|
|
4733
|
+
phase: "error",
|
|
4734
|
+
attemptId,
|
|
4735
|
+
error: presentError3(error)
|
|
4736
|
+
}
|
|
4587
4737
|
}));
|
|
4588
4738
|
} finally {
|
|
4589
4739
|
setProvisionBusy(false);
|
|
4590
4740
|
}
|
|
4591
|
-
}, [announce, invoke, loadStatus, model.provisioning
|
|
4741
|
+
}, [announce, invoke, loadStatus, model.bots, model.provisioning, scheduleAnimationFrame]);
|
|
4592
4742
|
const countdownAttemptId = model.provisioning?.attemptId;
|
|
4593
4743
|
const countdownPhase = model.provisioning?.phase;
|
|
4594
4744
|
const countdownExpiresAt = model.provisioning?.expiresAt;
|
|
@@ -4617,23 +4767,26 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4617
4767
|
{ attemptId: provision2.attemptId },
|
|
4618
4768
|
controller.signal
|
|
4619
4769
|
));
|
|
4770
|
+
if (result.operation !== provision2.operation || isCallbackRepair(provision2) && result.botId !== provision2.botId) {
|
|
4771
|
+
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
|
|
4772
|
+
}
|
|
4620
4773
|
if (result.status === "connected") {
|
|
4621
4774
|
const snapshot = await loadStatus({ signal: controller.signal, silent: true, restoreProvisioning: false });
|
|
4622
|
-
const
|
|
4775
|
+
const targetBot = snapshot?.bots.find((bot) => bot.botId === result.botId);
|
|
4623
4776
|
if (!snapshot) {
|
|
4624
|
-
throw new Error("\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
|
|
4777
|
+
throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
|
|
4625
4778
|
}
|
|
4626
|
-
if (!
|
|
4779
|
+
if (!targetBot?.connected) {
|
|
4627
4780
|
setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? { ...current, provisioning: { ...current.provisioning, phase: "connecting" } } : current);
|
|
4628
4781
|
return;
|
|
4629
4782
|
}
|
|
4630
4783
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4631
|
-
announce(
|
|
4784
|
+
announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
|
|
4632
4785
|
if (result.botId) setFocusBotId(result.botId);
|
|
4633
4786
|
return;
|
|
4634
4787
|
}
|
|
4635
4788
|
if (result.status === "failed") {
|
|
4636
|
-
const error = new Error(result.message ?? "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25");
|
|
4789
|
+
const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
|
|
4637
4790
|
error.code = "FEISHU_PROVISION_FAILED";
|
|
4638
4791
|
throw error;
|
|
4639
4792
|
}
|
|
@@ -4658,6 +4811,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4658
4811
|
setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? {
|
|
4659
4812
|
...current,
|
|
4660
4813
|
provisioning: {
|
|
4814
|
+
...current.provisioning,
|
|
4661
4815
|
phase: "error",
|
|
4662
4816
|
attemptId: provision2.attemptId,
|
|
4663
4817
|
error: presentError3(error)
|
|
@@ -4686,6 +4840,20 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4686
4840
|
return next;
|
|
4687
4841
|
});
|
|
4688
4842
|
}, []);
|
|
4843
|
+
const repairCallback = React10.useCallback((connection) => {
|
|
4844
|
+
if (model.provisioning) return;
|
|
4845
|
+
setRemoveTargetId(null);
|
|
4846
|
+
setBotError(connection.botId, null);
|
|
4847
|
+
setTestNoticesByBot((current) => {
|
|
4848
|
+
const next = { ...current };
|
|
4849
|
+
delete next[connection.botId];
|
|
4850
|
+
return next;
|
|
4851
|
+
});
|
|
4852
|
+
void startProvisioning({
|
|
4853
|
+
operation: CALLBACK_REPAIR_OPERATION,
|
|
4854
|
+
bot: connection
|
|
4855
|
+
});
|
|
4856
|
+
}, [model.provisioning, setBotError, startProvisioning]);
|
|
4689
4857
|
const reconnectOneBot = React10.useCallback(async (connection) => {
|
|
4690
4858
|
const { botId, bot } = connection;
|
|
4691
4859
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
@@ -4779,28 +4947,48 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4779
4947
|
}
|
|
4780
4948
|
}, [announce, invoke, loadStatus, mergeSnapshot, scheduleAnimationFrame, setBotBusy, setBotError, workspaceFence]);
|
|
4781
4949
|
const provision = model.provisioning;
|
|
4950
|
+
const provisionBot = provision?.botId ? model.bots.find((bot) => bot.botId === provision.botId) ?? { botId: provision.botId, bot: { name: provision.botName ?? "\u6B64\u673A\u5668\u4EBA" } } : void 0;
|
|
4951
|
+
const restartProvisioning = ({ replace = false } = {}) => startProvisioning({
|
|
4952
|
+
replace,
|
|
4953
|
+
operation: provision?.operation ?? FEISHU_REGISTRATION_OPERATIONS.PROVISION,
|
|
4954
|
+
bot: provisionBot
|
|
4955
|
+
});
|
|
4782
4956
|
let provisionContent = null;
|
|
4783
4957
|
if (provision?.phase === "creating") {
|
|
4784
|
-
provisionContent = h2(ProvisionProgress, {
|
|
4958
|
+
provisionContent = h2(ProvisionProgress, {
|
|
4959
|
+
phase: "creating",
|
|
4960
|
+
provision,
|
|
4961
|
+
busy: provisionBusy
|
|
4962
|
+
});
|
|
4785
4963
|
} else if (provision?.phase === "qr") {
|
|
4786
4964
|
provisionContent = h2(QrPane, {
|
|
4787
4965
|
provision,
|
|
4788
4966
|
now,
|
|
4789
|
-
onRefresh: () => void
|
|
4967
|
+
onRefresh: () => void restartProvisioning({ replace: true }),
|
|
4790
4968
|
onCancel: () => void cancelProvisioning(),
|
|
4791
4969
|
busy: provisionBusy || model.phase !== "ready"
|
|
4792
4970
|
});
|
|
4793
4971
|
} else if (provision?.phase === "connecting") {
|
|
4794
4972
|
provisionContent = h2(ProvisionProgress, {
|
|
4795
4973
|
phase: "connecting",
|
|
4796
|
-
|
|
4974
|
+
provision,
|
|
4975
|
+
onCancel: isCallbackRepair(provision) ? void 0 : () => void cancelProvisioning(),
|
|
4797
4976
|
busy: provisionBusy
|
|
4798
4977
|
});
|
|
4799
4978
|
} else if (provision?.phase === "error") {
|
|
4800
4979
|
provisionContent = h2(ProvisionError2, {
|
|
4801
4980
|
error: provision.error,
|
|
4802
|
-
|
|
4803
|
-
|
|
4981
|
+
provision,
|
|
4982
|
+
onRetry: () => void restartProvisioning({ replace: Boolean(provision.attemptId) }),
|
|
4983
|
+
onCancel: () => {
|
|
4984
|
+
const targetBotId = provision.botId;
|
|
4985
|
+
setModel((current) => ({ ...current, provisioning: null }));
|
|
4986
|
+
void loadStatus({ silent: true, restoreProvisioning: false });
|
|
4987
|
+
scheduleAnimationFrame(() => {
|
|
4988
|
+
if (targetBotId) cardRefs.current.get(targetBotId)?.focus();
|
|
4989
|
+
else addButtonRef.current?.focus();
|
|
4990
|
+
}, "focus");
|
|
4991
|
+
},
|
|
4804
4992
|
busy: provisionBusy
|
|
4805
4993
|
});
|
|
4806
4994
|
}
|
|
@@ -4870,7 +5058,9 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4870
5058
|
errorsByBot,
|
|
4871
5059
|
testNoticesByBot,
|
|
4872
5060
|
removeTargetId,
|
|
5061
|
+
provisioning: provision,
|
|
4873
5062
|
onReconnect: (bot) => void reconnectOneBot(bot),
|
|
5063
|
+
onRepairCallback: repairCallback,
|
|
4874
5064
|
onWorkspaceSave: saveWorkspace,
|
|
4875
5065
|
onRequestRemove: requestRemove,
|
|
4876
5066
|
onConfirmRemove: (bot) => void confirmRemove(bot),
|