@xmanrui/dsh-im 0.14.0 → 0.16.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 +246 -46
- package/lib/index.js +137 -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 +39 -0
- package/plugin-src/client/index.js +2 -1
- package/plugin-src/client/styles.js +2 -1
- 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 +723 -1
- package/src/channels/feishu/feishu-cards.mjs +155 -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/shared/workspace-command.mjs +2 -2
- package/src/channels/weixin/weixin-api.mjs +1 -1
- package/src/channels/weixin/weixin-controller.mjs +56 -12
- package/src/channels/weixin/weixin-runtime.mjs +12 -1
package/lib/client.js
CHANGED
|
@@ -399,6 +399,7 @@ var EN = Object.freeze({
|
|
|
399
399
|
"IM \u6E20\u9053": "IM channels",
|
|
400
400
|
"\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA": "DeepSeek Harness, always within reach",
|
|
401
401
|
"AI Office": "AI Office",
|
|
402
|
+
"\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09": "(Experimental)",
|
|
402
403
|
"AI Office \u8BBE\u7F6E": "AI Office settings",
|
|
403
404
|
"AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5": "AI Office settings are missing an RPC connection",
|
|
404
405
|
"\u6B63\u5728\u8BFB\u53D6 AI Office Connector\u2026": "Loading AI Office Connector\u2026",
|
|
@@ -586,6 +587,27 @@ var EN = Object.freeze({
|
|
|
586
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",
|
|
587
588
|
"\u5728\u98DE\u4E66\u4E2D\u6253\u5F00": "Open in Feishu",
|
|
588
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",
|
|
589
611
|
"\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA": "Confirmed. Connecting the new bot",
|
|
590
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.",
|
|
591
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",
|
|
@@ -620,6 +642,13 @@ var EN = Object.freeze({
|
|
|
620
642
|
"\u8FD9\u662F\u5FAE\u4FE1\u9644\u52A0\u7684\u5B89\u5168\u786E\u8BA4\u6B65\u9AA4\u3002\u914D\u5BF9\u7801\u53EA\u7528\u4E8E\u672C\u6B21\u626B\u7801\u8F6E\u8BE2\uFF0C\u4E0D\u4F1A\u5199\u5165\u914D\u7F6E\u6216\u65E5\u5FD7\u3002": "This is an additional WeChat confirmation step. The pairing code is used only for this connection and is never stored.",
|
|
621
643
|
"\u6B63\u5728\u4FDD\u5B58\u51ED\u636E\u5E76\u9A8C\u8BC1 Harness \u4E0E\u5FAE\u4FE1\u957F\u8F6E\u8BE2\u3002": "Saving credentials and verifying the WeChat connection.",
|
|
622
644
|
"\u5FAE\u4FE1\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u52A8\u6D88\u606F\u8FDE\u63A5": "Confirmed in WeChat. Starting the message connection",
|
|
645
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u8BFB\u53D6\u73B0\u6709\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u68C0\u67E5 DSH \u51ED\u636E\u5B58\u50A8\u3002": "WeChat was authorized, but the existing login credential could not be read. Check the DSH credential store.",
|
|
646
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u767B\u5F55\u51ED\u636E\u65E0\u6CD5\u5199\u5165 DSH \u51ED\u636E\u5B58\u50A8\u3002\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u662F\u5426\u53EF\u5199\u3002": "WeChat was authorized, but the login credential could not be written to the DSH credential store. Check that the store is writable.",
|
|
647
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u8D26\u53F7\u914D\u7F6E\u65E0\u6CD5\u5199\u5165\u672C\u673A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u76EE\u5F55\u6743\u9650\u3002": "WeChat was authorized, but the account configuration could not be saved locally. Check the DSH_HOME directory permissions.",
|
|
648
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u521D\u59CB\u5316\u8D26\u53F7\u72B6\u6001\u6216\u5DE5\u4F5C\u533A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u548C\u5DE5\u4F5C\u533A\u76EE\u5F55\u3002": "WeChat was authorized, but the account state or workspace could not be initialized. Check DSH_HOME and the workspace directory.",
|
|
649
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u63D2\u4EF6\u65E0\u6CD5\u8FDE\u63A5\u672C\u673A Harness\u3002\u8BF7\u786E\u8BA4 dsh web \u5DF2\u6B63\u5E38\u542F\u52A8\u3002": "WeChat was authorized, but the plugin could not reach the local Harness. Confirm that dsh web is running normally.",
|
|
650
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6D88\u606F\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u540E\u91CD\u8BD5\u3002": "WeChat was authorized, but the message connection could not be initialized. Check the dsh web logs and try again.",
|
|
651
|
+
"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6FC0\u6D3B\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002": "WeChat was authorized, but an unknown error occurred during activation. Check the dsh web logs.",
|
|
623
652
|
"\u5FAE\u4FE1\u5DF2\u7ED1\u5B9A\uFF0C\u53EF\u4EE5\u5F00\u59CB\u5411\u5DF2\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u53D1\u6D88\u606F\u3002": "WeChat is connected and ready for messages.",
|
|
624
653
|
"\u8FD9\u4E2A\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ECF\u7ED1\u5B9A\u5E76\u4FDD\u6301\u5728\u7EBF\u3002": "This WeChat account is connected and online.",
|
|
625
654
|
"\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002": "The WeChat account and local credentials were removed.",
|
|
@@ -857,6 +886,16 @@ function translateDynamic(text5) {
|
|
|
857
886
|
if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
|
|
858
887
|
match = /^从 DeepSeek Harness 移除(.+)$/.exec(text5);
|
|
859
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]}.`;
|
|
860
899
|
match = /^(检查连接|重试连接)(.+)$/.exec(text5);
|
|
861
900
|
if (match) return `${localizeText(match[1])} ${match[2]}`;
|
|
862
901
|
match = /^移除(.+)$/.exec(text5);
|
|
@@ -3031,6 +3070,7 @@ var FEISHU_RPC_CHANNEL = "/feishu";
|
|
|
3031
3070
|
var FEISHU_ENDPOINTS = Object.freeze({
|
|
3032
3071
|
status: "connection.status",
|
|
3033
3072
|
beginProvisioning: "provision.begin",
|
|
3073
|
+
beginCallbackRepair: "bot.callback-repair.begin",
|
|
3034
3074
|
pollProvisioning: "provision.poll",
|
|
3035
3075
|
cancelProvisioning: "provision.cancel",
|
|
3036
3076
|
bindCredentials: "bot.bind-credentials",
|
|
@@ -3042,6 +3082,10 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
3042
3082
|
testConnection: "connection.test",
|
|
3043
3083
|
disconnect: "connection.disconnect"
|
|
3044
3084
|
});
|
|
3085
|
+
var FEISHU_REGISTRATION_OPERATIONS = Object.freeze({
|
|
3086
|
+
PROVISION: "provision",
|
|
3087
|
+
CALLBACK_REPAIR: "callback_repair"
|
|
3088
|
+
});
|
|
3045
3089
|
var CONNECTION_STATES = /* @__PURE__ */ new Set([
|
|
3046
3090
|
"disconnected",
|
|
3047
3091
|
"offline",
|
|
@@ -3076,6 +3120,9 @@ function optionalTimestamp(value) {
|
|
|
3076
3120
|
function clamp2(value, min, max, fallback) {
|
|
3077
3121
|
return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
|
|
3078
3122
|
}
|
|
3123
|
+
function normalizeRegistrationOperation(value) {
|
|
3124
|
+
return value === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR ? FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR : FEISHU_REGISTRATION_OPERATIONS.PROVISION;
|
|
3125
|
+
}
|
|
3079
3126
|
function unwrapRpcResult3(result) {
|
|
3080
3127
|
if (!isRecord3(result) || typeof result.ok !== "boolean") {
|
|
3081
3128
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
@@ -3094,15 +3141,24 @@ function normalizeProvisioning2(value, now = Date.now()) {
|
|
|
3094
3141
|
const attemptId = optionalString2(source.attemptId) ?? optionalString2(source.provisioningId);
|
|
3095
3142
|
const verificationUrl = optionalString2(source.verificationUrl);
|
|
3096
3143
|
const qrCodeDataUrl = optionalString2(source.qrCodeDataUrl);
|
|
3097
|
-
|
|
3144
|
+
const submitted = source.submitted === true;
|
|
3145
|
+
if (!attemptId || !verificationUrl && !qrCodeDataUrl && !submitted) {
|
|
3098
3146
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u4FE1\u606F\u4E0D\u5B8C\u6574");
|
|
3099
3147
|
}
|
|
3100
3148
|
const explicitExpiry = optionalTimestamp(source.expiresAt);
|
|
3101
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
|
+
}
|
|
3102
3155
|
return {
|
|
3103
3156
|
attemptId,
|
|
3157
|
+
operation,
|
|
3158
|
+
botId,
|
|
3104
3159
|
verificationUrl,
|
|
3105
3160
|
qrCodeDataUrl,
|
|
3161
|
+
submitted,
|
|
3106
3162
|
expiresAt: explicitExpiry ?? now + expireIn * 1e3,
|
|
3107
3163
|
pollIntervalMs: clamp2(source.pollIntervalMs, 800, 1e4, 1800)
|
|
3108
3164
|
};
|
|
@@ -3220,6 +3276,7 @@ function normalizePollResult(value) {
|
|
|
3220
3276
|
if (!status) throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u672A\u77E5\u7684\u521B\u5EFA\u72B6\u6001");
|
|
3221
3277
|
const normalized = {
|
|
3222
3278
|
status,
|
|
3279
|
+
operation: normalizeRegistrationOperation(value.operation),
|
|
3223
3280
|
botId: optionalString2(value.botId),
|
|
3224
3281
|
message: optionalString2(value.error?.message) ?? optionalString2(value.message),
|
|
3225
3282
|
connection: void 0,
|
|
@@ -3738,6 +3795,8 @@ var CSS3 = String.raw`
|
|
|
3738
3795
|
.bxf-healthSummary[data-error="true"] { color: var(--bxf-error); }
|
|
3739
3796
|
.bxf-botActions { flex: none; flex-wrap: nowrap; gap: 8px; margin-top: 0; justify-content: flex-end; }
|
|
3740
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); }
|
|
3741
3800
|
|
|
3742
3801
|
.bxf-confirm {
|
|
3743
3802
|
border-top: 1px solid var(--dsw-alias-border-l2, #dee0e3);
|
|
@@ -3829,6 +3888,10 @@ function installFeishuStyles() {
|
|
|
3829
3888
|
}
|
|
3830
3889
|
|
|
3831
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
|
+
}
|
|
3832
3895
|
function SvgIcon({ children, size = 18, className, viewBox = "0 0 24 24" }) {
|
|
3833
3896
|
return h2("svg", {
|
|
3834
3897
|
width: size,
|
|
@@ -3988,7 +4051,12 @@ function safeVerificationHref(value) {
|
|
|
3988
4051
|
if (!value) return void 0;
|
|
3989
4052
|
try {
|
|
3990
4053
|
const url = new URL(value);
|
|
3991
|
-
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;
|
|
3992
4060
|
} catch {
|
|
3993
4061
|
return void 0;
|
|
3994
4062
|
}
|
|
@@ -4004,6 +4072,8 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4004
4072
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
4005
4073
|
const expired = provision.expired === true || remaining === 0;
|
|
4006
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";
|
|
4007
4077
|
React10.useEffect(() => setImageFailed(false), [qrSource]);
|
|
4008
4078
|
return h2(
|
|
4009
4079
|
"div",
|
|
@@ -4019,7 +4089,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4019
4089
|
{ className: "bxf-qrFrame dim-qrFrame" },
|
|
4020
4090
|
qrSource && !imageFailed ? h2("img", {
|
|
4021
4091
|
src: qrSource,
|
|
4022
|
-
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",
|
|
4023
4093
|
onError: () => setImageFailed(true)
|
|
4024
4094
|
}) : h2(
|
|
4025
4095
|
"div",
|
|
@@ -4058,16 +4128,16 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4058
4128
|
"div",
|
|
4059
4129
|
{ className: "bxf-stateLabel dim-stateLabel" },
|
|
4060
4130
|
h2("span", { className: "bxf-dot dim-stateDot", "data-tone": "warning" }),
|
|
4061
|
-
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")
|
|
4062
4132
|
),
|
|
4063
|
-
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
4064
|
-
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"),
|
|
4065
4135
|
h2(
|
|
4066
4136
|
"ol",
|
|
4067
4137
|
{ className: "bxf-steps dim-steps" },
|
|
4068
4138
|
h2("li", null, "\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801"),
|
|
4069
|
-
h2("li", null, "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
|
|
4070
|
-
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")
|
|
4071
4141
|
),
|
|
4072
4142
|
h2(
|
|
4073
4143
|
"div",
|
|
@@ -4084,14 +4154,15 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4084
4154
|
rel: "noopener noreferrer"
|
|
4085
4155
|
}, h2("span", null, "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00")) : null,
|
|
4086
4156
|
!expired ? h2(Button5, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
|
|
4087
|
-
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")
|
|
4088
4158
|
)
|
|
4089
4159
|
)
|
|
4090
4160
|
)
|
|
4091
4161
|
);
|
|
4092
4162
|
}
|
|
4093
|
-
function ProvisionProgress({ phase, onCancel, busy }) {
|
|
4163
|
+
function ProvisionProgress({ phase, provision, onCancel, busy }) {
|
|
4094
4164
|
const connecting = phase === "connecting";
|
|
4165
|
+
const repairing = isCallbackRepair(provision);
|
|
4095
4166
|
return h2(
|
|
4096
4167
|
"div",
|
|
4097
4168
|
{
|
|
@@ -4099,16 +4170,17 @@ function ProvisionProgress({ phase, onCancel, busy }) {
|
|
|
4099
4170
|
"aria-busy": "true"
|
|
4100
4171
|
},
|
|
4101
4172
|
h2("div", { className: "dim-spinner", "aria-hidden": "true" }),
|
|
4102
|
-
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"),
|
|
4103
|
-
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"),
|
|
4104
|
-
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(
|
|
4105
4176
|
"div",
|
|
4106
4177
|
{ className: "bxf-actions dim-viewActions", style: { justifyContent: "center" } },
|
|
4107
|
-
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")
|
|
4108
4179
|
) : null
|
|
4109
4180
|
);
|
|
4110
4181
|
}
|
|
4111
|
-
function ProvisionError2({ error, onRetry, onCancel, busy }) {
|
|
4182
|
+
function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
|
|
4183
|
+
const repairing = isCallbackRepair(provision);
|
|
4112
4184
|
return h2(
|
|
4113
4185
|
"div",
|
|
4114
4186
|
{ className: "bxf-card bxf-provisionCard dim-surfaceCard" },
|
|
@@ -4118,7 +4190,7 @@ function ProvisionError2({ error, onRetry, onCancel, busy }) {
|
|
|
4118
4190
|
h2(
|
|
4119
4191
|
"div",
|
|
4120
4192
|
null,
|
|
4121
|
-
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"),
|
|
4122
4194
|
h2("p", null, error.message),
|
|
4123
4195
|
error.code ? h2("span", { className: "bxf-errorCode" }, error.code) : null,
|
|
4124
4196
|
h2(
|
|
@@ -4203,10 +4275,12 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
|
4203
4275
|
function BotCard({
|
|
4204
4276
|
connection,
|
|
4205
4277
|
busy,
|
|
4278
|
+
repairDisabled,
|
|
4206
4279
|
actionError,
|
|
4207
4280
|
testNotice,
|
|
4208
4281
|
removing,
|
|
4209
4282
|
onReconnect,
|
|
4283
|
+
onRepairCallback,
|
|
4210
4284
|
onWorkspaceSave,
|
|
4211
4285
|
onRequestRemove,
|
|
4212
4286
|
onConfirmRemove,
|
|
@@ -4299,6 +4373,13 @@ function BotCard({
|
|
|
4299
4373
|
"aria-busy": busy === "reconnect" ? "true" : void 0,
|
|
4300
4374
|
"aria-label": `${connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"}${bot.name}`
|
|
4301
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"),
|
|
4302
4383
|
h2(Button5, {
|
|
4303
4384
|
className: "dim-cardAction",
|
|
4304
4385
|
kind: "danger",
|
|
@@ -4335,11 +4416,13 @@ function BotList(props) {
|
|
|
4335
4416
|
{ key: bot.botId },
|
|
4336
4417
|
h2(BotCard, {
|
|
4337
4418
|
connection: bot,
|
|
4338
|
-
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),
|
|
4339
4421
|
actionError: props.errorsByBot[bot.botId],
|
|
4340
4422
|
testNotice: props.testNoticesByBot[bot.botId],
|
|
4341
4423
|
removing: props.removeTargetId === bot.botId,
|
|
4342
4424
|
onReconnect: () => props.onReconnect(bot),
|
|
4425
|
+
onRepairCallback: () => props.onRepairCallback(bot),
|
|
4343
4426
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
|
|
4344
4427
|
onRequestRemove: () => props.onRequestRemove(bot),
|
|
4345
4428
|
onConfirmRemove: () => props.onConfirmRemove(bot),
|
|
@@ -4382,11 +4465,12 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
|
|
|
4382
4465
|
if (snapshot.revision > 0 && current.revision > snapshot.revision) return current;
|
|
4383
4466
|
let provisioning = current.provisioning;
|
|
4384
4467
|
if (!provisioning && restoreProvisioning && snapshot.provisioning) {
|
|
4468
|
+
const submitted = snapshot.provisioning.submitted === true;
|
|
4385
4469
|
provisioning = {
|
|
4386
|
-
phase: snapshot.state === "connecting" ? "connecting" : "qr",
|
|
4470
|
+
phase: submitted || snapshot.state === "connecting" ? "connecting" : "qr",
|
|
4387
4471
|
...snapshot.provisioning,
|
|
4388
4472
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - now),
|
|
4389
|
-
expired: snapshot.provisioning.expiresAt <= now
|
|
4473
|
+
expired: !submitted && snapshot.provisioning.expiresAt <= now
|
|
4390
4474
|
};
|
|
4391
4475
|
}
|
|
4392
4476
|
return {
|
|
@@ -4501,7 +4585,15 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4501
4585
|
node.focus({ preventScroll: true });
|
|
4502
4586
|
setFocusBotId(null);
|
|
4503
4587
|
}, [focusBotId, model.bots]);
|
|
4504
|
-
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;
|
|
4505
4597
|
setCredentialOpen(false);
|
|
4506
4598
|
setCredentialError(null);
|
|
4507
4599
|
setProvisionBusy(true);
|
|
@@ -4510,16 +4602,27 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4510
4602
|
setModel((current) => ({
|
|
4511
4603
|
...current,
|
|
4512
4604
|
phase: current.phase === "loading" ? "ready" : current.phase,
|
|
4513
|
-
provisioning: {
|
|
4605
|
+
provisioning: {
|
|
4606
|
+
phase: "creating",
|
|
4607
|
+
operation,
|
|
4608
|
+
...botId ? { botId } : {},
|
|
4609
|
+
...botName ? { botName } : {}
|
|
4610
|
+
}
|
|
4514
4611
|
}));
|
|
4515
4612
|
try {
|
|
4516
4613
|
if (replace && previousAttemptId) {
|
|
4517
|
-
|
|
4614
|
+
try {
|
|
4615
|
+
await invoke(FEISHU_ENDPOINTS.cancelProvisioning, { attemptId: previousAttemptId });
|
|
4616
|
+
} catch {
|
|
4617
|
+
}
|
|
4518
4618
|
}
|
|
4519
4619
|
const provision2 = normalizeProvisioning2(await invoke(
|
|
4520
|
-
FEISHU_ENDPOINTS.beginProvisioning,
|
|
4521
|
-
{ locale: "zh-CN" }
|
|
4620
|
+
repairing ? FEISHU_ENDPOINTS.beginCallbackRepair : FEISHU_ENDPOINTS.beginProvisioning,
|
|
4621
|
+
repairing ? { botId } : { locale: "zh-CN" }
|
|
4522
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
|
+
}
|
|
4523
4626
|
const timestamp7 = Date.now();
|
|
4524
4627
|
setNow(timestamp7);
|
|
4525
4628
|
setModel((current) => ({
|
|
@@ -4527,20 +4630,34 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4527
4630
|
provisioning: {
|
|
4528
4631
|
phase: "qr",
|
|
4529
4632
|
...provision2,
|
|
4633
|
+
...botName ? { botName } : {},
|
|
4530
4634
|
durationMs: Math.max(1, provision2.expiresAt - timestamp7),
|
|
4531
4635
|
expired: false
|
|
4532
4636
|
}
|
|
4533
4637
|
}));
|
|
4534
|
-
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");
|
|
4535
4639
|
} catch (error) {
|
|
4536
4640
|
setModel((current) => ({
|
|
4537
4641
|
...current,
|
|
4538
|
-
provisioning: {
|
|
4642
|
+
provisioning: {
|
|
4643
|
+
phase: "error",
|
|
4644
|
+
operation,
|
|
4645
|
+
...botId ? { botId } : {},
|
|
4646
|
+
...botName ? { botName } : {},
|
|
4647
|
+
...replace && previousAttemptId ? { attemptId: previousAttemptId } : {},
|
|
4648
|
+
error: presentError3(error)
|
|
4649
|
+
}
|
|
4539
4650
|
}));
|
|
4540
4651
|
} finally {
|
|
4541
4652
|
setProvisionBusy(false);
|
|
4542
4653
|
}
|
|
4543
|
-
}, [
|
|
4654
|
+
}, [
|
|
4655
|
+
announce,
|
|
4656
|
+
invoke,
|
|
4657
|
+
model.provisioning?.attemptId,
|
|
4658
|
+
model.provisioning?.botId,
|
|
4659
|
+
model.provisioning?.botName
|
|
4660
|
+
]);
|
|
4544
4661
|
const bindCredentials = React10.useCallback(async ({ identity, secret }) => {
|
|
4545
4662
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4546
4663
|
setCredentialBusy(true);
|
|
@@ -4564,23 +4681,64 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4564
4681
|
}
|
|
4565
4682
|
}, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
|
|
4566
4683
|
const cancelProvisioning = React10.useCallback(async () => {
|
|
4567
|
-
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;
|
|
4568
4688
|
setProvisionBusy(true);
|
|
4569
4689
|
try {
|
|
4570
|
-
|
|
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
|
+
}
|
|
4571
4718
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4572
|
-
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");
|
|
4573
4720
|
await loadStatus({ silent: true, restoreProvisioning: false });
|
|
4574
|
-
scheduleAnimationFrame(() =>
|
|
4721
|
+
scheduleAnimationFrame(() => {
|
|
4722
|
+
if (repairing && activeProvision.botId) {
|
|
4723
|
+
cardRefs.current.get(activeProvision.botId)?.focus();
|
|
4724
|
+
} else {
|
|
4725
|
+
addButtonRef.current?.focus();
|
|
4726
|
+
}
|
|
4727
|
+
}, "focus");
|
|
4575
4728
|
} catch (error) {
|
|
4576
4729
|
setModel((current) => ({
|
|
4577
4730
|
...current,
|
|
4578
|
-
provisioning: {
|
|
4731
|
+
provisioning: {
|
|
4732
|
+
...activeProvision,
|
|
4733
|
+
phase: "error",
|
|
4734
|
+
attemptId,
|
|
4735
|
+
error: presentError3(error)
|
|
4736
|
+
}
|
|
4579
4737
|
}));
|
|
4580
4738
|
} finally {
|
|
4581
4739
|
setProvisionBusy(false);
|
|
4582
4740
|
}
|
|
4583
|
-
}, [announce, invoke, loadStatus, model.provisioning
|
|
4741
|
+
}, [announce, invoke, loadStatus, model.bots, model.provisioning, scheduleAnimationFrame]);
|
|
4584
4742
|
const countdownAttemptId = model.provisioning?.attemptId;
|
|
4585
4743
|
const countdownPhase = model.provisioning?.phase;
|
|
4586
4744
|
const countdownExpiresAt = model.provisioning?.expiresAt;
|
|
@@ -4609,23 +4767,26 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4609
4767
|
{ attemptId: provision2.attemptId },
|
|
4610
4768
|
controller.signal
|
|
4611
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
|
+
}
|
|
4612
4773
|
if (result.status === "connected") {
|
|
4613
4774
|
const snapshot = await loadStatus({ signal: controller.signal, silent: true, restoreProvisioning: false });
|
|
4614
|
-
const
|
|
4775
|
+
const targetBot = snapshot?.bots.find((bot) => bot.botId === result.botId);
|
|
4615
4776
|
if (!snapshot) {
|
|
4616
|
-
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");
|
|
4617
4778
|
}
|
|
4618
|
-
if (!
|
|
4779
|
+
if (!targetBot?.connected) {
|
|
4619
4780
|
setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? { ...current, provisioning: { ...current.provisioning, phase: "connecting" } } : current);
|
|
4620
4781
|
return;
|
|
4621
4782
|
}
|
|
4622
4783
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4623
|
-
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");
|
|
4624
4785
|
if (result.botId) setFocusBotId(result.botId);
|
|
4625
4786
|
return;
|
|
4626
4787
|
}
|
|
4627
4788
|
if (result.status === "failed") {
|
|
4628
|
-
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"));
|
|
4629
4790
|
error.code = "FEISHU_PROVISION_FAILED";
|
|
4630
4791
|
throw error;
|
|
4631
4792
|
}
|
|
@@ -4650,6 +4811,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4650
4811
|
setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? {
|
|
4651
4812
|
...current,
|
|
4652
4813
|
provisioning: {
|
|
4814
|
+
...current.provisioning,
|
|
4653
4815
|
phase: "error",
|
|
4654
4816
|
attemptId: provision2.attemptId,
|
|
4655
4817
|
error: presentError3(error)
|
|
@@ -4678,6 +4840,20 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4678
4840
|
return next;
|
|
4679
4841
|
});
|
|
4680
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]);
|
|
4681
4857
|
const reconnectOneBot = React10.useCallback(async (connection) => {
|
|
4682
4858
|
const { botId, bot } = connection;
|
|
4683
4859
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
@@ -4771,28 +4947,48 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4771
4947
|
}
|
|
4772
4948
|
}, [announce, invoke, loadStatus, mergeSnapshot, scheduleAnimationFrame, setBotBusy, setBotError, workspaceFence]);
|
|
4773
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
|
+
});
|
|
4774
4956
|
let provisionContent = null;
|
|
4775
4957
|
if (provision?.phase === "creating") {
|
|
4776
|
-
provisionContent = h2(ProvisionProgress, {
|
|
4958
|
+
provisionContent = h2(ProvisionProgress, {
|
|
4959
|
+
phase: "creating",
|
|
4960
|
+
provision,
|
|
4961
|
+
busy: provisionBusy
|
|
4962
|
+
});
|
|
4777
4963
|
} else if (provision?.phase === "qr") {
|
|
4778
4964
|
provisionContent = h2(QrPane, {
|
|
4779
4965
|
provision,
|
|
4780
4966
|
now,
|
|
4781
|
-
onRefresh: () => void
|
|
4967
|
+
onRefresh: () => void restartProvisioning({ replace: true }),
|
|
4782
4968
|
onCancel: () => void cancelProvisioning(),
|
|
4783
4969
|
busy: provisionBusy || model.phase !== "ready"
|
|
4784
4970
|
});
|
|
4785
4971
|
} else if (provision?.phase === "connecting") {
|
|
4786
4972
|
provisionContent = h2(ProvisionProgress, {
|
|
4787
4973
|
phase: "connecting",
|
|
4788
|
-
|
|
4974
|
+
provision,
|
|
4975
|
+
onCancel: isCallbackRepair(provision) ? void 0 : () => void cancelProvisioning(),
|
|
4789
4976
|
busy: provisionBusy
|
|
4790
4977
|
});
|
|
4791
4978
|
} else if (provision?.phase === "error") {
|
|
4792
4979
|
provisionContent = h2(ProvisionError2, {
|
|
4793
4980
|
error: provision.error,
|
|
4794
|
-
|
|
4795
|
-
|
|
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
|
+
},
|
|
4796
4992
|
busy: provisionBusy
|
|
4797
4993
|
});
|
|
4798
4994
|
}
|
|
@@ -4862,7 +5058,9 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4862
5058
|
errorsByBot,
|
|
4863
5059
|
testNoticesByBot,
|
|
4864
5060
|
removeTargetId,
|
|
5061
|
+
provisioning: provision,
|
|
4865
5062
|
onReconnect: (bot) => void reconnectOneBot(bot),
|
|
5063
|
+
onRepairCallback: repairCallback,
|
|
4866
5064
|
onWorkspaceSave: saveWorkspace,
|
|
4867
5065
|
onRequestRemove: requestRemove,
|
|
4868
5066
|
onConfirmRemove: (bot) => void confirmRemove(bot),
|
|
@@ -8901,8 +9099,9 @@ var CSS11 = String.raw`
|
|
|
8901
9099
|
.dim-logoSlack svg { width: 21px; height: 21px; }
|
|
8902
9100
|
.dim-logoWhatsapp { color: white; background: #25d366; }
|
|
8903
9101
|
.dim-logoWhatsapp svg { width: 21px; height: 21px; }
|
|
8904
|
-
.dim-channelCopy { min-width: 0; display:
|
|
9102
|
+
.dim-channelCopy { min-width: 0; display: grid; }
|
|
8905
9103
|
.dim-channelCopy strong { overflow: hidden; color: inherit; font-size: 14px; line-height: 20px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
|
|
9104
|
+
.dim-channelNote { overflow: hidden; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 10px; line-height: 13px; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
|
|
8906
9105
|
.dim-divider { width: 1px; min-height: 520px; background: var(--dsw-alias-border-l1, #eef0f3); }
|
|
8907
9106
|
.dim-panel { min-width: 0; container-type: inline-size; }
|
|
8908
9107
|
.dim-panel .bxf-page, .dim-panel .dxw-page, .dim-panel .ddt-page, .dim-panel .dqq-page, .dim-panel .dwecom-page, .dim-panel .dsl-page, .dim-panel .dwa-page { width: 100%; max-width: none; padding: 0 0 24px; }
|
|
@@ -9131,7 +9330,7 @@ var CHANNELS = Object.freeze([
|
|
|
9131
9330
|
{ id: "telegram", label: "Telegram" },
|
|
9132
9331
|
{ id: "discord", label: "Discord" },
|
|
9133
9332
|
{ id: "whatsapp", label: "WhatsApp" },
|
|
9134
|
-
{ id: "office", label: "AI Office" }
|
|
9333
|
+
{ id: "office", label: "AI Office", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" }
|
|
9135
9334
|
]);
|
|
9136
9335
|
function WeixinLogo() {
|
|
9137
9336
|
return h2(
|
|
@@ -9283,7 +9482,8 @@ function IMSettingsTab({
|
|
|
9283
9482
|
h2(
|
|
9284
9483
|
"span",
|
|
9285
9484
|
{ className: "dim-channelCopy" },
|
|
9286
|
-
h2("strong", null, channel4.label)
|
|
9485
|
+
h2("strong", null, channel4.label),
|
|
9486
|
+
channel4.note ? h2("small", { className: "dim-channelNote" }, channel4.note) : null
|
|
9287
9487
|
)
|
|
9288
9488
|
))
|
|
9289
9489
|
),
|