@xmanrui/dsh-im 4.14.0 → 4.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/README.en.md +10 -2
- package/README.md +17 -6
- package/lib/client.js +1980 -616
- package/lib/index.js +303 -293
- package/package.json +6 -2
- package/plugin-src/client/access-policy-settings.js +6 -0
- package/plugin-src/client/channels/feishu/index.js +16 -4
- package/plugin-src/client/channels/wecom-app/api.js +124 -0
- package/plugin-src/client/channels/wecom-app/index.js +612 -0
- package/plugin-src/client/channels/wecom-app/styles.js +25 -0
- package/plugin-src/client/delivery-settings.js +7 -0
- package/plugin-src/client/i18n.js +64 -1
- package/plugin-src/client/index.js +21 -0
- package/plugin-src/client/model-setting.js +135 -69
- package/plugin-src/client/session-channel-logos.js +241 -0
- package/plugin-src/client/styles.js +22 -7
- package/plugin-src/host/channels/dingtalk/index.mjs +8 -15
- package/plugin-src/host/channels/discord/index.mjs +8 -10
- package/plugin-src/host/channels/feishu/index.mjs +8 -15
- package/plugin-src/host/channels/office/index.mjs +9 -5
- package/plugin-src/host/channels/qq/index.mjs +8 -15
- package/plugin-src/host/channels/shared/access-policy-production.mjs +1 -1
- package/plugin-src/host/channels/shared/model-setting-rpc.mjs +1 -2
- package/plugin-src/host/channels/shared/startup-error.mjs +53 -0
- package/plugin-src/host/channels/shared/startup.mjs +47 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +1 -0
- package/plugin-src/host/channels/slack/index.mjs +8 -10
- package/plugin-src/host/channels/telegram/index.mjs +8 -10
- package/plugin-src/host/channels/wecom/index.mjs +8 -15
- package/plugin-src/host/channels/wecom/rpc.mjs +6 -1
- package/plugin-src/host/channels/wecom-app/index.mjs +33 -0
- package/plugin-src/host/channels/wecom-app/production.mjs +217 -0
- package/plugin-src/host/channels/wecom-app/rpc.mjs +225 -0
- package/plugin-src/host/channels/weixin/index.mjs +8 -15
- package/plugin-src/host/channels/whatsapp/index.mjs +8 -15
- package/plugin-src/host/delivery-adapter.mjs +4 -0
- package/plugin-src/host/delivery-suggestions.mjs +4 -0
- package/plugin-src/host/index.mjs +21 -2
- package/plugin-src/host/session-title-prefix.mjs +122 -0
- package/scripts/verify-model-setting.mjs +54 -0
- package/scripts/verify-session-channel-logos.mjs +59 -0
- package/scripts/verify-session-title-prefix.mjs +149 -0
- package/src/channels/feishu/bridge.mjs +305 -12
- package/src/channels/feishu/feishu-cards.mjs +38 -0
- package/src/channels/feishu/feishu-channel.mjs +88 -20
- package/src/channels/feishu/plugin-controller.mjs +1 -0
- package/src/channels/feishu/repair-manager.mjs +3 -2
- package/src/channels/shared/bot-workspace-store.mjs +11 -3
- package/src/channels/shared/command-catalog.mjs +102 -0
- package/src/channels/shared/i18n-en/feishu.mjs +14 -2
- package/src/channels/shared/i18n-en/shared-a.mjs +3 -0
- package/src/channels/shared/i18n-en/shared-c.mjs +9 -0
- package/src/channels/shared/i18n-en/wecom-app.mjs +33 -0
- package/src/channels/shared/i18n-en.mjs +2 -0
- package/src/channels/shared/model-setting.mjs +43 -8
- package/src/channels/shared/session-channel-labels.mjs +26 -0
- package/src/channels/shared/text-harness-bridge.mjs +2 -26
- package/src/channels/telegram/telegram-api.mjs +18 -6
- package/src/channels/telegram/telegram-runtime.mjs +34 -32
- package/src/channels/wecom/send-error.mjs +31 -0
- package/src/channels/wecom/wecom-bridge.mjs +59 -17
- package/src/channels/wecom-app/callback-server.mjs +471 -0
- package/src/channels/wecom-app/config-store.mjs +240 -0
- package/src/channels/wecom-app/harness-client.mjs +11 -0
- package/src/channels/wecom-app/state-store.mjs +107 -0
- package/src/channels/wecom-app/wecom-app-api.mjs +432 -0
- package/src/channels/wecom-app/wecom-app-bridge.mjs +1059 -0
- package/src/channels/wecom-app/wecom-app-controller.mjs +440 -0
- package/src/channels/wecom-app/wecom-app-runtime.mjs +221 -0
package/lib/client.js
CHANGED
|
@@ -270,14 +270,14 @@ var require_semver = __commonJS({
|
|
|
270
270
|
if (!m[4]) {
|
|
271
271
|
this.prerelease = [];
|
|
272
272
|
} else {
|
|
273
|
-
this.prerelease = m[4].split(".").map((
|
|
274
|
-
if (/^[0-9]+$/.test(
|
|
275
|
-
const num = +
|
|
273
|
+
this.prerelease = m[4].split(".").map((id6) => {
|
|
274
|
+
if (/^[0-9]+$/.test(id6)) {
|
|
275
|
+
const num = +id6;
|
|
276
276
|
if (num >= 0 && num < MAX_SAFE_INTEGER) {
|
|
277
277
|
return num;
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
-
return
|
|
280
|
+
return id6;
|
|
281
281
|
});
|
|
282
282
|
}
|
|
283
283
|
this.build = m[5] ? m[5].split(".") : [];
|
|
@@ -566,13 +566,13 @@ __export(index_exports, {
|
|
|
566
566
|
name: () => name
|
|
567
567
|
});
|
|
568
568
|
module.exports = __toCommonJS(index_exports);
|
|
569
|
-
var
|
|
569
|
+
var React28 = __toESM(require("react"), 1);
|
|
570
570
|
|
|
571
571
|
// package.json
|
|
572
572
|
var package_default = {
|
|
573
573
|
name: "@xmanrui/dsh-im",
|
|
574
|
-
version: "4.
|
|
575
|
-
description: "\u628A\
|
|
574
|
+
version: "4.16.0",
|
|
575
|
+
description: "\u628A\u5341\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect ten IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
576
576
|
keywords: [
|
|
577
577
|
"deepseek-harness",
|
|
578
578
|
"dsh",
|
|
@@ -606,6 +606,10 @@ var package_default = {
|
|
|
606
606
|
{
|
|
607
607
|
name: "Chan-0312",
|
|
608
608
|
url: "https://github.com/Chan-0312"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
name: "BuvkB",
|
|
612
|
+
url: "https://github.com/BuvkB"
|
|
609
613
|
}
|
|
610
614
|
],
|
|
611
615
|
license: "MIT",
|
|
@@ -1075,6 +1079,7 @@ var EN = Object.freeze({
|
|
|
1075
1079
|
"\u5F00\u542F\uFF08\u81EA\u52A8\u5F00\u542F\u72EC\u7ACB\u98DE\u4E66\u8BDD\u9898\uFF09": "On (auto-open a dedicated Feishu topic)",
|
|
1076
1080
|
"\u5F00\u542F\u540E\uFF0C\u7FA4\u804A\u4E2D\u5411\u673A\u5668\u4EBA\u63D0\u95EE\u4F1A\u81EA\u52A8\u5F00\u542F\u72EC\u7ACB\u98DE\u4E66\u8BDD\u9898\uFF0C\u56DE\u590D\u843D\u5728\u8BDD\u9898\u5185\uFF1B\u6BCF\u4E2A\u8BDD\u9898\u662F dsh \u4F1A\u8BDD\u5217\u8868\u91CC\u4E00\u6761\u72EC\u7ACB\u4F1A\u8BDD\uFF0C\u4E0A\u4E0B\u6587\u4E92\u4E0D\u4E32\u3002\u79C1\u804A\u4E0D\u53D7\u5F71\u54CD\u3002": "When enabled, questions to the bot in a group auto-open a dedicated Feishu topic and replies stay inside it. Each topic is an independent conversation in dsh with its own context. Private chats are unaffected.",
|
|
1077
1081
|
"\u5206\u6B65\u76F4\u63A8": "Step push",
|
|
1082
|
+
"\u67E5\u770B\u5206\u6B65\u76F4\u63A8\u8BF4\u660E": "View step push help",
|
|
1078
1083
|
"\u5F00\u542F\u540E\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E": "Push tool calls and process notes step by step",
|
|
1079
1084
|
"\u5173\u95ED\uFF08\u4FDD\u6301\u6D41\u5F0F\u5361\u6A21\u5F0F\uFF09": "Off (keep the streaming card)",
|
|
1080
1085
|
"\u5F00\u542F\uFF08\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E\uFF09": "On (push tool calls and process notes step by step)",
|
|
@@ -1213,6 +1218,14 @@ var EN = Object.freeze({
|
|
|
1213
1218
|
"Agent Preset \u65E0\u6548\u3002": "The Agent Preset is invalid.",
|
|
1214
1219
|
"Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002": "The Agent Preset does not exist or is unavailable.",
|
|
1215
1220
|
"\u6A21\u578B": "Model",
|
|
1221
|
+
"\u6A21\u578B\u4E0E\u601D\u8003\u5F3A\u5EA6": "Model and reasoning effort",
|
|
1222
|
+
"\u601D\u8003\u5F3A\u5EA6": "Reasoning effort",
|
|
1223
|
+
"\u8DDF\u968F\u6A21\u578B\u9ED8\u8BA4": "Model default",
|
|
1224
|
+
"\u5148\u9009\u62E9\u6A21\u578B\uFF0C\u518D\u8BBE\u7F6E\u601D\u8003\u5F3A\u5EA6\u3002": "Select a model to configure its reasoning effort.",
|
|
1225
|
+
"\u8BE5\u6A21\u578B\u672A\u63D0\u4F9B\u53EF\u8C03\u8282\u7684\u601D\u8003\u5F3A\u5EA6\u3002": "This model does not provide adjustable reasoning effort.",
|
|
1226
|
+
"\u5DF2\u4FDD\u5B58\u7684\u601D\u8003\u5F3A\u5EA6\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u5F3A\u5EA6\u6216\u6062\u590D\u9ED8\u8BA4\u3002": "The saved reasoning effort is unavailable. Choose another effort or restore the default.",
|
|
1227
|
+
"\u4F7F\u7528\u6A21\u578B\u6216\u670D\u52A1\u63D0\u4F9B\u65B9\u7684\u9ED8\u8BA4\u601D\u8003\u5F3A\u5EA6\u3002": "Use the default reasoning effort from the model or provider.",
|
|
1228
|
+
"\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6240\u9009\u601D\u8003\u5F3A\u5EA6\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u3002": "This model does not support the selected reasoning effort. Choose another effort.",
|
|
1216
1229
|
"\u67E5\u770B\u6A21\u578B\u8BBE\u7F6E\u8BF4\u660E": "View model setting help",
|
|
1217
1230
|
"\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B": "Follow the default model",
|
|
1218
1231
|
"\u6A21\u578B\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the model. Try again.",
|
|
@@ -1313,7 +1326,7 @@ var EN = Object.freeze({
|
|
|
1313
1326
|
"\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\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 permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
|
|
1314
1327
|
"\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a group-message permission QR code for the existing Feishu app\u2026",
|
|
1315
1328
|
"\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210": "Group-message permission was not granted",
|
|
1316
|
-
"\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u589E\u91CF\u8865\u5145\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\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 the missing card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), im:resource for uploading images or files sent by the bot, and application:app_slash_command:read / write for the native command panel. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.",
|
|
1329
|
+
"\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u589E\u91CF\u8865\u5145\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\u3001\u63A5\u6536\u7FA4\u5185\u5176\u4ED6\u673A\u5668\u4EBA @ \u5F53\u524D\u673A\u5668\u4EBA\u6240\u9700\u7684 im:message.group_at_msg.include_bot:readonly\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\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 the missing card-button callback, im:message:readonly for reading images or files in user messages (shown by Feishu as \u201CRead direct and group messages\u201D), im:resource for uploading images or files sent by the bot, im:message.group_at_msg.include_bot:readonly for receiving group messages from other bots that mention this bot, and application:app_slash_command:read / write for the native command panel. It does not create a new app. The confirmation page shows only missing items; this bot reconnects briefly afterward, while other bots are unaffected.",
|
|
1317
1330
|
"\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5F53\u524D\u7F3A\u5C11\u7684\u4E0A\u8FF0\u914D\u7F6E": "Review the existing app name and confirm that only the missing items described above are added",
|
|
1318
1331
|
"\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u4E0E\u56DE\u8C03\u8865\u5168\u5B8C\u6210": "Keep this page open until permissions and the callback are complete",
|
|
1319
1332
|
"\u53D6\u6D88\u8865\u5168": "Cancel setup",
|
|
@@ -1744,7 +1757,61 @@ var EN = Object.freeze({
|
|
|
1744
1757
|
"\u786E\u8BA4\u6E05\u7406\u8FC7\u671F\u9644\u4EF6": "Confirm expired attachment cleanup",
|
|
1745
1758
|
"\u786E\u8BA4\u6E05\u7406\u5F53\u524D\u5DF2\u8FC7\u671F\u7684\u9644\u4EF6\uFF1F": "Clean up the attachments that are currently expired?",
|
|
1746
1759
|
"\u786E\u8BA4\u6E05\u7406": "Confirm cleanup",
|
|
1747
|
-
"\u6B63\u5728\u6E05\u7406\u2026": "Cleaning up\u2026"
|
|
1760
|
+
"\u6B63\u5728\u6E05\u7406\u2026": "Cleaning up\u2026",
|
|
1761
|
+
"\u6B63\u5728\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001\u2026": "Loading WeCom app status\u2026",
|
|
1762
|
+
"\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "Add WeCom app",
|
|
1763
|
+
"\u6536\u8D77\u8868\u5355": "Collapse form",
|
|
1764
|
+
"\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528": "Add a WeCom self-built app",
|
|
1765
|
+
"\u6B63\u5728\u586B\u5199": "Filling in details",
|
|
1766
|
+
"\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "No WeCom app connected yet",
|
|
1767
|
+
"\u5728\u4F01\u4E1A\u5FAE\u4FE1\u4E2D\u521B\u5EFA\u81EA\u5EFA\u5E94\u7528\uFF0C\u5373\u53EF\u5728\u5FAE\u4FE1\u91CC\u4F7F\u7528": "Create a self-built app in WeCom to use it inside WeChat",
|
|
1768
|
+
"\u5728\u5E94\u7528\u7BA1\u7406\u540E\u53F0\u521B\u5EFA\u81EA\u5EFA\u5E94\u7528\uFF0C\u5F00\u542F\u300C\u63A5\u6536\u6D88\u606F\u300D\u5E76\u586B\u5165\u4E0B\u9762\u7684\u53C2\u6570\u3002\u6210\u5458\u7684\u5FAE\u4FE1\u5173\u6CE8\u8BE5\u4F01\u4E1A\u7684\u5FAE\u4FE1\u63D2\u4EF6\u540E\uFF0C\u5C31\u80FD\u5728\u5FAE\u4FE1\u4E2D\u4E0E\u672C\u5E94\u7528\u53CC\u5411\u5BF9\u8BDD\u3002": "Create the self-built app in the WeCom admin console, enable receive-messages, and fill in the parameters below. Once members follow the enterprise WeChat plugin, they can chat with this app directly inside WeChat.",
|
|
1769
|
+
"\u586B\u5199\u5E94\u7528\u53C2\u6570": "Fill in app parameters",
|
|
1770
|
+
"\u4F01\u4E1A ID\uFF08CorpID\uFF09": "Corp ID",
|
|
1771
|
+
"\u4F8B\u5982 ww1234567890abcdef": "for example ww1234567890abcdef",
|
|
1772
|
+
"\u5E94\u7528 AgentId": "AgentId",
|
|
1773
|
+
"\u4F8B\u5982 1000002": "for example 1000002",
|
|
1774
|
+
"\u5E94\u7528 Secret": "App Secret",
|
|
1775
|
+
"\u5E94\u7528\u8BE6\u60C5\u9875\u7684 Secret": "The Secret from the app details page",
|
|
1776
|
+
"\u56DE\u8C03 Token": "Callback Token",
|
|
1777
|
+
"\u63A5\u6536\u6D88\u606F \u2192 API \u63A5\u6536\u4E2D\u7684 Token": "The Token from Receive messages \u2192 API receive",
|
|
1778
|
+
"43 \u4F4D\u5B57\u6BCD\u6216\u6570\u5B57": "43 alphanumeric characters",
|
|
1779
|
+
"\u4EE3\u7406\u5730\u5740\uFF08\u53EF\u9009\uFF09": "API proxy (optional)",
|
|
1780
|
+
"\u7559\u7A7A\u76F4\u8FDE qyapi.weixin.qq.com": "leave empty to reach qyapi.weixin.qq.com directly",
|
|
1781
|
+
"\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF08\u53EF\u9009\uFF09": "Public callback base URL (optional)",
|
|
1782
|
+
"\u4F8B\u5982 https://im.example.com": "for example https://im.example.com",
|
|
1783
|
+
"\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00": "Streaming replies: on",
|
|
1784
|
+
"\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173": "Streaming replies: off",
|
|
1785
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5BA2\u6237\u7AEF\u5B9E\u65F6\u51FA\u5B57\uFF1B\u5FAE\u4FE1\u7AEF\u4E0D\u652F\u6301\u65F6\u81EA\u52A8\u6539\u4E3A\u6574\u6BB5\u53D1\u9001": "Streams replies in the WeCom client; falls back to segmented text messages when the WeChat side does not support it",
|
|
1786
|
+
"\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528": "Bind a WeCom self-built app",
|
|
1787
|
+
"\u56DE\u8C03 URL\uFF08\u586B\u5165\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u300C\u63A5\u6536\u6D88\u606F \u2192 \u8BBE\u7F6EAPI\u63A5\u6536\u300D\uFF09": "Callback URL (paste into the WeCom console under Receive messages \u2192 API receive)",
|
|
1788
|
+
"\u672A\u914D\u7F6E\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF1A\u8BF7\u5728\u672C\u9875\u300C\u8BBE\u7F6E\u300D\u4E2D\u586B\u5199\u56DE\u8C03\u57FA\u5740\uFF0C\u6216\u624B\u52A8\u62FC\u63A5 \u56DE\u8C03\u57FA\u5740 + \u8DEF\u5F84": "No public callback base URL configured: fill it in under Settings on this page, or manually combine the base URL and the path",
|
|
1789
|
+
"\u91CD\u7F6E\u5BC6\u94A5": "Reset secret",
|
|
1790
|
+
"\u91CD\u7F6E\u4E2D\u2026": "Resetting\u2026",
|
|
1791
|
+
"\u91CD\u7F6E\u5BC6\u94A5\u540E\u56DE\u8C03 URL \u4F1A\u53D8\u5316\uFF0C\u9700\u8981\u540C\u6B65\u66F4\u65B0\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u3002\u82E5\u516C\u7F51\u53CD\u4EE3\u672A\u5C31\u7EEA\uFF0C\u53EF\u4E34\u65F6\u4F7F\u7528 http://\u670D\u52A1\u5668IP:\u7AEF\u53E3 \u5F62\u5F0F\u7684\u56DE\u8C03\u5730\u5740\u3002": "Resetting the secret changes the callback URL; update the WeCom console accordingly. If the public reverse proxy is not ready yet, a http://server-ip:port callback address works temporarily.",
|
|
1792
|
+
"\u4FDD\u5B58\u8BBE\u7F6E": "Save settings",
|
|
1793
|
+
"\u8FD9\u4F1A\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u56DE\u8C03\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u7684\u5E94\u7528\u4E0D\u4F1A\u88AB\u5220\u9664\u3002": "This removes the locally stored app credentials, callback configuration, and session mappings. The app in the WeCom console is not deleted.",
|
|
1794
|
+
"\u4FDD\u7559\u5E94\u7528": "Keep app",
|
|
1795
|
+
"\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "Connected WeCom apps",
|
|
1796
|
+
"HTTP \u56DE\u8C03\u901A\u9053": "HTTP callback channel",
|
|
1797
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "WeCom app",
|
|
1798
|
+
"\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58": "Corp ID saved securely",
|
|
1799
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u56DE\u8C03\u901A\u9053\u5C31\u7EEA": "WeCom app callback channel is ready",
|
|
1800
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA": "WeCom app connection is not ready",
|
|
1801
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u4ECD\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5\u3002": "The WeCom app is still not ready; the plugin keeps retrying automatically.",
|
|
1802
|
+
"\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002": "Connection check finished.",
|
|
1803
|
+
"\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002": "Connection check finished; the test message was sent.",
|
|
1804
|
+
"\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u5E94\u7528\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002": "Connection check finished. The app has not received a private chat usable for testing yet.",
|
|
1805
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u5DF2\u7ED1\u5B9A\u3002\u8BF7\u628A\u56DE\u8C03 URL \u586B\u5165\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u5E76\u4FDD\u5B58\u3002": "The WeCom app is bound. Paste the callback URL into the WeCom console and save.",
|
|
1806
|
+
"\u56DE\u8C03\u5BC6\u94A5\u5DF2\u91CD\u7F6E\uFF0C\u8BF7\u628A\u65B0\u7684\u56DE\u8C03 URL \u66F4\u65B0\u5230\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u3002": "The callback secret was reset; update the new callback URL in the WeCom console.",
|
|
1807
|
+
"\u56DE\u8C03\u5BC6\u94A5\u91CD\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002": "The callback secret reset failed; try again later.",
|
|
1808
|
+
"\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001": "Could not load WeCom app status",
|
|
1809
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E": "WeCom app settings",
|
|
1810
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5": "The WeCom app settings page is missing the RPC connection",
|
|
1811
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25": "The WeCom app operation failed",
|
|
1812
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5": "The WeCom app operation failed; try again later",
|
|
1813
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94": "The WeCom app service returned an unrecognized response",
|
|
1814
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868": "The WeCom app service did not return a valid bot list"
|
|
1748
1815
|
});
|
|
1749
1816
|
var en = EN;
|
|
1750
1817
|
var zh = Object.freeze(Object.fromEntries(
|
|
@@ -1760,78 +1827,78 @@ function isEnglish() {
|
|
|
1760
1827
|
function channelName(value) {
|
|
1761
1828
|
return localizeText(value);
|
|
1762
1829
|
}
|
|
1763
|
-
function translateDynamic(
|
|
1764
|
-
const guidanceLimit = /^增强提示词不得超过 (\d+) 个字符。$/.exec(
|
|
1830
|
+
function translateDynamic(text7) {
|
|
1831
|
+
const guidanceLimit = /^增强提示词不得超过 (\d+) 个字符。$/.exec(text7);
|
|
1765
1832
|
if (guidanceLimit) return `Guidance must not exceed ${guidanceLimit[1]} characters.`;
|
|
1766
|
-
let match = /^(\d+) \/ (\d+) 在线$/.exec(
|
|
1833
|
+
let match = /^(\d+) \/ (\d+) 在线$/.exec(text7);
|
|
1767
1834
|
if (match) return `${match[1]}/${match[2]} online`;
|
|
1768
|
-
match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(
|
|
1835
|
+
match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(text7);
|
|
1769
1836
|
if (match) return `${match[2]} of ${match[1]} bots online`;
|
|
1770
|
-
match = /^请输入 -1、0 或 1~(\d+) 之间的整数。$/.exec(
|
|
1837
|
+
match = /^请输入 -1、0 或 1~(\d+) 之间的整数。$/.exec(text7);
|
|
1771
1838
|
if (match) return `Enter -1, 0, or an integer from 1 to ${match[1]}.`;
|
|
1772
|
-
match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(
|
|
1839
|
+
match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(text7);
|
|
1773
1840
|
if (match) return `Loading ${channelName(match[1])} bot status\u2026`;
|
|
1774
|
-
match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(
|
|
1841
|
+
match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(text7);
|
|
1775
1842
|
if (match) return `Could not load ${channelName(match[1])} bot status`;
|
|
1776
|
-
match = /^尚未接入\s*(.+?)\s*机器人$/.exec(
|
|
1843
|
+
match = /^尚未接入\s*(.+?)\s*机器人$/.exec(text7);
|
|
1777
1844
|
if (match) return `No ${channelName(match[1])} bot connected yet`;
|
|
1778
|
-
match = /^已接入的\s*(.+?)\s*机器人$/.exec(
|
|
1845
|
+
match = /^已接入的\s*(.+?)\s*机器人$/.exec(text7);
|
|
1779
1846
|
if (match) return `Connected ${channelName(match[1])} bots`;
|
|
1780
|
-
match = /^手动接入(.+)机器人$/.exec(
|
|
1847
|
+
match = /^手动接入(.+)机器人$/.exec(text7);
|
|
1781
1848
|
if (match) return `Connect ${channelName(match[1])} bot manually`;
|
|
1782
|
-
match = /^(.+) 设置$/.exec(
|
|
1849
|
+
match = /^(.+) 设置$/.exec(text7);
|
|
1783
1850
|
if (match) return `${channelName(match[1])} settings`;
|
|
1784
|
-
match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(
|
|
1851
|
+
match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(text7);
|
|
1785
1852
|
if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
|
|
1786
|
-
match = /^从 DeepSeek Harness 移除(.+)$/.exec(
|
|
1853
|
+
match = /^从 DeepSeek Harness 移除(.+)$/.exec(text7);
|
|
1787
1854
|
if (match) return `Remove ${match[1]} from DeepSeek Harness`;
|
|
1788
|
-
match = /^(.+)的飞书授权流程$/.exec(
|
|
1855
|
+
match = /^(.+)的飞书授权流程$/.exec(text7);
|
|
1789
1856
|
if (match) return `Feishu authorization flow for ${match[1]}`;
|
|
1790
|
-
match = /^用于为(.+)补全权限与回调的一次性授权二维码$/.exec(
|
|
1857
|
+
match = /^用于为(.+)补全权限与回调的一次性授权二维码$/.exec(text7);
|
|
1791
1858
|
if (match) return `One-time QR code for completing permissions and the callback for ${match[1]}`;
|
|
1792
|
-
match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(
|
|
1859
|
+
match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text7);
|
|
1793
1860
|
if (match) return `One-time QR code for granting group-message permission to ${match[1]}`;
|
|
1794
|
-
match = /^正在为「(.+)」补全权限与回调$/.exec(
|
|
1861
|
+
match = /^正在为「(.+)」补全权限与回调$/.exec(text7);
|
|
1795
1862
|
if (match) return `Completing permissions and the callback for \u201C${match[1]}\u201D`;
|
|
1796
|
-
match = /^正在为「(.+)」开通群消息权限$/.exec(
|
|
1863
|
+
match = /^正在为「(.+)」开通群消息权限$/.exec(text7);
|
|
1797
1864
|
if (match) return `Granting group-message permission to \u201C${match[1]}\u201D`;
|
|
1798
|
-
match = /^为(.+)补全权限与回调$/.exec(
|
|
1865
|
+
match = /^为(.+)补全权限与回调$/.exec(text7);
|
|
1799
1866
|
if (match) return `Complete permissions and the callback for ${match[1]}`;
|
|
1800
|
-
match = /^(.+)的权限补全二维码已生成,请使用飞书扫码。$/.exec(
|
|
1867
|
+
match = /^(.+)的权限补全二维码已生成,请使用飞书扫码。$/.exec(text7);
|
|
1801
1868
|
if (match) return `Permission-completion QR code generated for ${match[1]}. Scan it with Feishu.`;
|
|
1802
|
-
match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(
|
|
1869
|
+
match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text7);
|
|
1803
1870
|
if (match) return `Group-message permission QR code generated for ${match[1]}. Confirm it with Feishu.`;
|
|
1804
|
-
match = /^(.+)的权限与回调已补全。$/.exec(
|
|
1871
|
+
match = /^(.+)的权限与回调已补全。$/.exec(text7);
|
|
1805
1872
|
if (match) return `Permissions and the callback completed for ${match[1]}.`;
|
|
1806
|
-
match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(
|
|
1873
|
+
match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text7);
|
|
1807
1874
|
if (match) return `${match[1]} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.`;
|
|
1808
|
-
match = /^(检查连接|重试连接)(.+)$/.exec(
|
|
1875
|
+
match = /^(检查连接|重试连接)(.+)$/.exec(text7);
|
|
1809
1876
|
if (match) return `${localizeText(match[1])} ${match[2]}`;
|
|
1810
|
-
match = /^移除(.+)$/.exec(
|
|
1877
|
+
match = /^移除(.+)$/.exec(text7);
|
|
1811
1878
|
if (match) return `Remove ${match[1]}`;
|
|
1812
|
-
match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(
|
|
1879
|
+
match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(text7);
|
|
1813
1880
|
if (match) {
|
|
1814
1881
|
return `This stops the message connection and removes the locally stored ${localizeText(match[1])}, bot configuration, and session mappings. The bot in ${localizeText(match[2])} is not deleted.`;
|
|
1815
1882
|
}
|
|
1816
|
-
match = /^二维码剩余 (.+)$/.exec(
|
|
1883
|
+
match = /^二维码剩余 (.+)$/.exec(text7);
|
|
1817
1884
|
if (match) return `QR code expires in ${match[1]}`;
|
|
1818
|
-
match = /^最近一条消息处理失败:(.+)$/.exec(
|
|
1885
|
+
match = /^最近一条消息处理失败:(.+)$/.exec(text7);
|
|
1819
1886
|
if (match) return `Latest message failed: ${localizeText(match[1])}`;
|
|
1820
|
-
match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(
|
|
1887
|
+
match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(text7);
|
|
1821
1888
|
if (match) return `The image download failed (HTTP ${match[1]}). Send it again.`;
|
|
1822
|
-
match = /^一次最多只能处理 (\d+) 张图片。$/.exec(
|
|
1889
|
+
match = /^一次最多只能处理 (\d+) 张图片。$/.exec(text7);
|
|
1823
1890
|
if (match) return `A message can contain at most ${match[1]} images.`;
|
|
1824
|
-
match = /^状态刷新失败:(.+)$/.exec(
|
|
1891
|
+
match = /^状态刷新失败:(.+)$/.exec(text7);
|
|
1825
1892
|
if (match) return `Status refresh failed: ${match[1]}`;
|
|
1826
|
-
match = /^状态自动刷新失败:(.+)$/.exec(
|
|
1893
|
+
match = /^状态自动刷新失败:(.+)$/.exec(text7);
|
|
1827
1894
|
if (match) return `Automatic status refresh failed: ${match[1]}`;
|
|
1828
|
-
match = /^操作失败:(.+)$/.exec(
|
|
1895
|
+
match = /^操作失败:(.+)$/.exec(text7);
|
|
1829
1896
|
if (match) return `Operation failed: ${match[1]}`;
|
|
1830
|
-
match = /^连接检查失败:(.+)(参考号:(.+))$/.exec(
|
|
1897
|
+
match = /^连接检查失败:(.+)(参考号:(.+))$/.exec(text7);
|
|
1831
1898
|
if (match) return `Connection check failed: ${localizeText(match[1])} (reference: ${match[2]})`;
|
|
1832
|
-
match = /^连接检查失败:(.+)$/.exec(
|
|
1899
|
+
match = /^连接检查失败:(.+)$/.exec(text7);
|
|
1833
1900
|
if (match) return `Connection check failed: ${match[1]}`;
|
|
1834
|
-
match = /^移除失败:(.+)$/.exec(
|
|
1901
|
+
match = /^移除失败:(.+)$/.exec(text7);
|
|
1835
1902
|
if (match) return `Removal failed: ${match[1]}`;
|
|
1836
1903
|
const phrases = [
|
|
1837
1904
|
["\u4F01\u4E1A\u5FAE\u4FE1", "WeCom"],
|
|
@@ -1868,7 +1935,7 @@ function translateDynamic(text6) {
|
|
|
1868
1935
|
["\u8FDE\u63A5\u72B6\u6001", "connection status"],
|
|
1869
1936
|
["\u4E8C\u7EF4\u7801", "QR code"]
|
|
1870
1937
|
];
|
|
1871
|
-
let output =
|
|
1938
|
+
let output = text7;
|
|
1872
1939
|
for (const [source, target] of phrases) output = output.replaceAll(source, target);
|
|
1873
1940
|
return output;
|
|
1874
1941
|
}
|
|
@@ -1912,8 +1979,8 @@ var EMPTY_AGENT_PRESET_CATALOG = Object.freeze({
|
|
|
1912
1979
|
var AgentPresetCatalogContext = React3.createContext(EMPTY_AGENT_PRESET_CATALOG);
|
|
1913
1980
|
function normalizeAgentPresetId(value) {
|
|
1914
1981
|
if (typeof value !== "string") return "";
|
|
1915
|
-
const
|
|
1916
|
-
return PRESET_ID.test(
|
|
1982
|
+
const id6 = value.trim();
|
|
1983
|
+
return PRESET_ID.test(id6) ? id6 : "";
|
|
1917
1984
|
}
|
|
1918
1985
|
function normalizeAgentPresetCatalog(value) {
|
|
1919
1986
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -1922,11 +1989,11 @@ function normalizeAgentPresetCatalog(value) {
|
|
|
1922
1989
|
const items = [];
|
|
1923
1990
|
const seen = /* @__PURE__ */ new Set();
|
|
1924
1991
|
for (const entry of Array.isArray(value.items) ? value.items : []) {
|
|
1925
|
-
const
|
|
1926
|
-
if (!
|
|
1927
|
-
seen.add(
|
|
1928
|
-
const label = typeof entry?.label === "string" && entry.label.trim() ? entry.label.trim().slice(0, 128) : typeof entry?.name === "string" && entry.name.trim() ? entry.name.trim().slice(0, 128) :
|
|
1929
|
-
items.push({ id:
|
|
1992
|
+
const id6 = typeof entry === "string" ? normalizeAgentPresetId(entry) : normalizeAgentPresetId(entry?.id);
|
|
1993
|
+
if (!id6 || seen.has(id6)) continue;
|
|
1994
|
+
seen.add(id6);
|
|
1995
|
+
const label = typeof entry?.label === "string" && entry.label.trim() ? entry.label.trim().slice(0, 128) : typeof entry?.name === "string" && entry.name.trim() ? entry.name.trim().slice(0, 128) : id6;
|
|
1996
|
+
items.push({ id: id6, label });
|
|
1930
1997
|
}
|
|
1931
1998
|
return {
|
|
1932
1999
|
defaultId: normalizeAgentPresetId(value.defaultId),
|
|
@@ -2022,14 +2089,15 @@ var React4 = __toESM(require("react"), 1);
|
|
|
2022
2089
|
// src/channels/shared/model-setting.mjs
|
|
2023
2090
|
var MAX_PROVIDER_ID_LENGTH = 256;
|
|
2024
2091
|
var MAX_MODEL_ID_LENGTH = 1024;
|
|
2092
|
+
var MAX_EFFORT_ID_LENGTH = 256;
|
|
2025
2093
|
var MAX_LABEL_LENGTH = 256;
|
|
2026
2094
|
var UNSAFE_DISPLAY_TEXT = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]+/gu;
|
|
2027
2095
|
var UNSAFE_ID_TEXT = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
|
|
2028
2096
|
function cleanId(value, maxLength) {
|
|
2029
2097
|
if (typeof value !== "string") return "";
|
|
2030
|
-
const
|
|
2031
|
-
if (!
|
|
2032
|
-
return
|
|
2098
|
+
const id6 = value.trim();
|
|
2099
|
+
if (!id6 || id6.length > maxLength || UNSAFE_ID_TEXT.test(id6)) return "";
|
|
2100
|
+
return id6;
|
|
2033
2101
|
}
|
|
2034
2102
|
function cleanLabel(value, fallback) {
|
|
2035
2103
|
if (typeof value !== "string") return fallback;
|
|
@@ -2045,7 +2113,27 @@ function normalizeModelSelection(value) {
|
|
|
2045
2113
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2046
2114
|
const provider = cleanId(value.provider, MAX_PROVIDER_ID_LENGTH);
|
|
2047
2115
|
const model = cleanId(value.model, MAX_MODEL_ID_LENGTH);
|
|
2048
|
-
|
|
2116
|
+
const reasoningEffort = value.reasoningEffort === void 0 ? void 0 : cleanId(value.reasoningEffort, MAX_EFFORT_ID_LENGTH);
|
|
2117
|
+
if (!provider || !model || reasoningEffort === "") return null;
|
|
2118
|
+
return { provider, model, ...reasoningEffort === void 0 ? {} : { reasoningEffort } };
|
|
2119
|
+
}
|
|
2120
|
+
function sameModelSelection(left, right) {
|
|
2121
|
+
return left?.provider === right?.provider && left?.model === right?.model && left?.reasoningEffort === right?.reasoningEffort;
|
|
2122
|
+
}
|
|
2123
|
+
function normalizeReasoning(value) {
|
|
2124
|
+
if (!value || typeof value !== "object" || !Array.isArray(value.efforts)) return void 0;
|
|
2125
|
+
const efforts = [];
|
|
2126
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2127
|
+
for (const entry of value.efforts) {
|
|
2128
|
+
const id6 = cleanId(entry?.id, MAX_EFFORT_ID_LENGTH);
|
|
2129
|
+
if (!id6 || seen.has(id6)) continue;
|
|
2130
|
+
seen.add(id6);
|
|
2131
|
+
const description = cleanLabel(entry.description, "");
|
|
2132
|
+
efforts.push({ id: id6, name: cleanLabel(entry.name, id6), ...description ? { description } : {} });
|
|
2133
|
+
}
|
|
2134
|
+
if (!efforts.length) return void 0;
|
|
2135
|
+
const defaultEffort = cleanId(value.defaultEffort, MAX_EFFORT_ID_LENGTH);
|
|
2136
|
+
return { efforts, ...seen.has(defaultEffort) ? { defaultEffort } : {} };
|
|
2049
2137
|
}
|
|
2050
2138
|
function modelSelectionId(value) {
|
|
2051
2139
|
const selection = normalizeModelSelection(value);
|
|
@@ -2069,9 +2157,13 @@ function normalizeModelCatalog(value) {
|
|
|
2069
2157
|
const key = `${provider}\0${model}`;
|
|
2070
2158
|
if (seen.has(key)) continue;
|
|
2071
2159
|
seen.add(key);
|
|
2160
|
+
const description = cleanLabel(entry.description, "");
|
|
2161
|
+
const reasoning = normalizeReasoning(entry.reasoning);
|
|
2072
2162
|
models.push({
|
|
2073
2163
|
id: model,
|
|
2074
|
-
name: cleanLabel(entry.name, model)
|
|
2164
|
+
name: cleanLabel(entry.name, model),
|
|
2165
|
+
...description ? { description } : {},
|
|
2166
|
+
...reasoning ? { reasoning } : {}
|
|
2075
2167
|
});
|
|
2076
2168
|
}
|
|
2077
2169
|
if (models.length > 0) {
|
|
@@ -2085,109 +2177,244 @@ function normalizeModelCatalog(value) {
|
|
|
2085
2177
|
const failures = [];
|
|
2086
2178
|
for (const candidate of Array.isArray(value.failures) ? value.failures : []) {
|
|
2087
2179
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
2088
|
-
const
|
|
2089
|
-
if (!
|
|
2090
|
-
failures.push({ id:
|
|
2180
|
+
const id6 = cleanId(candidate.id, MAX_PROVIDER_ID_LENGTH);
|
|
2181
|
+
if (!id6) continue;
|
|
2182
|
+
failures.push({ id: id6, name: cleanLabel(candidate.name, id6) });
|
|
2091
2183
|
}
|
|
2092
2184
|
return { groups, failures };
|
|
2093
2185
|
}
|
|
2186
|
+
function modelCatalogEntry(catalog, selection) {
|
|
2187
|
+
const normalized = normalizeModelSelection(selection);
|
|
2188
|
+
if (!normalized) return void 0;
|
|
2189
|
+
return normalizeModelCatalog(catalog).groups.filter((group) => group.id === normalized.provider).flatMap((group) => group.models).find((model) => model.id === normalized.model);
|
|
2190
|
+
}
|
|
2094
2191
|
|
|
2095
2192
|
// plugin-src/client/model-setting.js
|
|
2096
2193
|
var SET_MODEL_ENDPOINT = "bot.model.set";
|
|
2097
2194
|
var ModelCatalogContext = React4.createContext(EMPTY_MODEL_CATALOG);
|
|
2098
|
-
function
|
|
2099
|
-
return
|
|
2195
|
+
function chevron(open = false) {
|
|
2196
|
+
return h2(
|
|
2197
|
+
"svg",
|
|
2198
|
+
{
|
|
2199
|
+
width: 14,
|
|
2200
|
+
height: 14,
|
|
2201
|
+
viewBox: "0 0 16 16",
|
|
2202
|
+
"aria-hidden": true,
|
|
2203
|
+
className: "dim-modelChevron",
|
|
2204
|
+
style: open ? { transform: "rotate(90deg)" } : void 0
|
|
2205
|
+
},
|
|
2206
|
+
h2("path", { d: "m6 4 4 4-4 4", fill: "none", stroke: "currentColor", strokeWidth: 1.5 })
|
|
2207
|
+
);
|
|
2100
2208
|
}
|
|
2101
2209
|
function ModelEditor({ model = null, disabled = false, onSave }) {
|
|
2102
|
-
const catalog = normalizeModelCatalog(
|
|
2103
|
-
|
|
2104
|
-
);
|
|
2105
|
-
const
|
|
2106
|
-
const
|
|
2210
|
+
const catalog = normalizeModelCatalog(React4.useContext(ModelCatalogContext));
|
|
2211
|
+
const id6 = React4.useId();
|
|
2212
|
+
const rootRef = React4.useRef(null);
|
|
2213
|
+
const menuRef = React4.useRef(null);
|
|
2214
|
+
const triggerRef = React4.useRef(null);
|
|
2215
|
+
const restoreFocusRef = React4.useRef(false);
|
|
2216
|
+
const savingRef = React4.useRef(false);
|
|
2217
|
+
const [pane, setPane] = React4.useState(null);
|
|
2107
2218
|
const [saving, setSaving] = React4.useState(false);
|
|
2108
2219
|
const [error, setError] = React4.useState(null);
|
|
2109
|
-
const
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
const
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2220
|
+
const current = normalizeModelSelection(model);
|
|
2221
|
+
const entry = modelCatalogEntry(catalog, current);
|
|
2222
|
+
const currentAvailable = !current || Boolean(entry);
|
|
2223
|
+
const reasoning = entry?.reasoning;
|
|
2224
|
+
const effort = current?.reasoningEffort;
|
|
2225
|
+
const effectiveEffort = effort ?? reasoning?.defaultEffort;
|
|
2226
|
+
const effortEntry = reasoning?.efforts.find((level) => level.id === effectiveEffort);
|
|
2227
|
+
const effortUnavailable = effort !== void 0 && !reasoning?.efforts.some((level) => level.id === effort);
|
|
2228
|
+
const defaultName = reasoning?.efforts.find((level) => level.id === reasoning.defaultEffort)?.name;
|
|
2229
|
+
const defaultLabel = localizeText("\u8DDF\u968F\u6A21\u578B\u9ED8\u8BA4") + (defaultName ? ` \xB7 ${defaultName}` : "");
|
|
2230
|
+
const effortLabel = !current ? localizeText("\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B") : effort === void 0 ? defaultLabel : effortEntry?.name ?? effort;
|
|
2231
|
+
const effortHint = !current ? "\u5148\u9009\u62E9\u6A21\u578B\uFF0C\u518D\u8BBE\u7F6E\u601D\u8003\u5F3A\u5EA6\u3002" : !currentAvailable ? null : effortUnavailable ? "\u5DF2\u4FDD\u5B58\u7684\u601D\u8003\u5F3A\u5EA6\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u5F3A\u5EA6\u6216\u6062\u590D\u9ED8\u8BA4\u3002" : !reasoning ? "\u8BE5\u6A21\u578B\u672A\u63D0\u4F9B\u53EF\u8C03\u8282\u7684\u601D\u8003\u5F3A\u5EA6\u3002" : null;
|
|
2232
|
+
const effortDisabled = !current || !currentAvailable || !reasoning && effort === void 0;
|
|
2233
|
+
const close = (restoreFocus = false) => {
|
|
2234
|
+
restoreFocusRef.current = restoreFocus;
|
|
2235
|
+
setPane(null);
|
|
2236
|
+
};
|
|
2237
|
+
React4.useEffect(() => {
|
|
2238
|
+
if (!pane && !saving && !disabled && restoreFocusRef.current) {
|
|
2239
|
+
restoreFocusRef.current = false;
|
|
2240
|
+
triggerRef.current?.focus();
|
|
2118
2241
|
}
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2242
|
+
}, [pane, saving, disabled]);
|
|
2243
|
+
React4.useEffect(() => {
|
|
2244
|
+
if (!pane) return void 0;
|
|
2245
|
+
const options = menuRef.current?.querySelectorAll('[role="menuitemradio"]');
|
|
2246
|
+
const selected = menuRef.current?.querySelector('[aria-checked="true"]');
|
|
2247
|
+
(selected ?? options?.[0])?.focus();
|
|
2248
|
+
const outside = (event) => {
|
|
2249
|
+
if (!rootRef.current?.contains(event.target)) setPane(null);
|
|
2250
|
+
};
|
|
2251
|
+
globalThis.document?.addEventListener("mousedown", outside);
|
|
2252
|
+
return () => globalThis.document?.removeEventListener("mousedown", outside);
|
|
2253
|
+
}, [pane]);
|
|
2254
|
+
const save = async (next) => {
|
|
2255
|
+
if (savingRef.current || disabled) return;
|
|
2256
|
+
if (sameModelSelection(current, next)) {
|
|
2257
|
+
close(true);
|
|
2258
|
+
return;
|
|
2259
|
+
}
|
|
2260
|
+
savingRef.current = true;
|
|
2126
2261
|
setSaving(true);
|
|
2127
2262
|
setError(null);
|
|
2128
2263
|
try {
|
|
2129
2264
|
await onSave?.(next);
|
|
2265
|
+
close(true);
|
|
2130
2266
|
} catch (cause) {
|
|
2131
2267
|
setError(cause?.message ?? "\u6A21\u578B\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
2132
2268
|
} finally {
|
|
2269
|
+
savingRef.current = false;
|
|
2133
2270
|
setSaving(false);
|
|
2134
2271
|
}
|
|
2135
2272
|
};
|
|
2273
|
+
const option = (key, label, description, selected, next) => h2(
|
|
2274
|
+
"button",
|
|
2275
|
+
{
|
|
2276
|
+
key,
|
|
2277
|
+
type: "button",
|
|
2278
|
+
role: "menuitemradio",
|
|
2279
|
+
"aria-checked": selected,
|
|
2280
|
+
className: "dim-modelOption",
|
|
2281
|
+
disabled: disabled || saving,
|
|
2282
|
+
onClick: () => {
|
|
2283
|
+
void save(next);
|
|
2284
|
+
}
|
|
2285
|
+
},
|
|
2286
|
+
h2(
|
|
2287
|
+
"span",
|
|
2288
|
+
{ className: "dim-modelOptionCopy" },
|
|
2289
|
+
h2("span", { className: "dim-modelOptionName" }, label),
|
|
2290
|
+
description ? h2("span", { className: "dim-modelDescription" }, description) : null
|
|
2291
|
+
),
|
|
2292
|
+
h2("span", { className: "dim-modelCheck", "aria-hidden": true }, selected ? "\u2713" : "")
|
|
2293
|
+
);
|
|
2294
|
+
const row = (key, label, value, blocked = false) => h2(
|
|
2295
|
+
"button",
|
|
2296
|
+
{
|
|
2297
|
+
type: "button",
|
|
2298
|
+
className: "dim-modelRow",
|
|
2299
|
+
disabled: disabled || saving || blocked,
|
|
2300
|
+
"aria-label": label,
|
|
2301
|
+
"aria-haspopup": "menu",
|
|
2302
|
+
"aria-expanded": pane === key,
|
|
2303
|
+
"aria-controls": pane === key ? `${id6}-menu` : void 0,
|
|
2304
|
+
"aria-describedby": key === "effort" && effortHint ? `${id6}-hint` : void 0,
|
|
2305
|
+
onClick: (event) => {
|
|
2306
|
+
triggerRef.current = event.currentTarget;
|
|
2307
|
+
setPane(pane === key ? null : key);
|
|
2308
|
+
}
|
|
2309
|
+
},
|
|
2310
|
+
h2("span", { className: "dim-modelRowLabel" }, label),
|
|
2311
|
+
h2("span", { className: "dim-modelValue", title: value }, value),
|
|
2312
|
+
chevron(pane === key)
|
|
2313
|
+
);
|
|
2136
2314
|
return h2(
|
|
2137
2315
|
"div",
|
|
2138
|
-
{
|
|
2316
|
+
{
|
|
2317
|
+
ref: rootRef,
|
|
2318
|
+
className: "dim-preset dim-modelSetting",
|
|
2319
|
+
onBlur: (event) => {
|
|
2320
|
+
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) close();
|
|
2321
|
+
},
|
|
2322
|
+
onKeyDown: (event) => {
|
|
2323
|
+
if (!pane) return;
|
|
2324
|
+
if (event.key === "Escape") {
|
|
2325
|
+
event.preventDefault();
|
|
2326
|
+
event.stopPropagation();
|
|
2327
|
+
close(true);
|
|
2328
|
+
}
|
|
2329
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
2330
|
+
const items = [...menuRef.current?.querySelectorAll('[role="menuitemradio"]:not(:disabled)') ?? []];
|
|
2331
|
+
if (!items.length) return;
|
|
2332
|
+
event.preventDefault();
|
|
2333
|
+
const at = items.indexOf(globalThis.document?.activeElement);
|
|
2334
|
+
const next = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : (at + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length;
|
|
2335
|
+
items[next]?.focus();
|
|
2336
|
+
}
|
|
2337
|
+
},
|
|
2139
2338
|
h2(
|
|
2140
2339
|
"div",
|
|
2141
2340
|
{ className: "dim-presetHeader" },
|
|
2142
2341
|
h2(
|
|
2143
2342
|
"span",
|
|
2144
2343
|
{ className: "dim-presetTitle" },
|
|
2145
|
-
|
|
2344
|
+
"\u6A21\u578B\u4E0E\u601D\u8003\u5F3A\u5EA6",
|
|
2146
2345
|
h2(
|
|
2147
2346
|
"span",
|
|
2148
2347
|
{ className: "dim-presetHelp" },
|
|
2149
|
-
h2(
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2348
|
+
h2(
|
|
2349
|
+
"button",
|
|
2350
|
+
{
|
|
2351
|
+
type: "button",
|
|
2352
|
+
className: "dim-presetHelpButton",
|
|
2353
|
+
"aria-label": "\u67E5\u770B\u6A21\u578B\u8BBE\u7F6E\u8BF4\u660E",
|
|
2354
|
+
"aria-describedby": `${id6}-help`
|
|
2355
|
+
},
|
|
2356
|
+
h2("span", { "aria-hidden": true }, "?")
|
|
2357
|
+
),
|
|
2358
|
+
h2(
|
|
2359
|
+
"span",
|
|
2360
|
+
{ id: `${id6}-help`, className: "dim-presetTooltip", role: "tooltip" },
|
|
2361
|
+
"\u53EA\u5F71\u54CD\u65B0\u5EFA\u4F1A\u8BDD\uFF1B\u82E5\u5F53\u524D\u804A\u5929\u5DF2\u6709\u4F1A\u8BDD\uFF0C\u5148\u53D1\u9001 /new\uFF0C\u518D\u53D1\u9001\u666E\u901A\u6D88\u606F\u751F\u6548\u3002"
|
|
2362
|
+
)
|
|
2160
2363
|
)
|
|
2161
2364
|
),
|
|
2162
|
-
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
2365
|
+
saving ? h2("span", { className: "dim-presetStatus", role: "status" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
2163
2366
|
),
|
|
2164
|
-
|
|
2165
|
-
|
|
2367
|
+
row("model", "\u6A21\u578B", entry?.name ?? (current ? modelSelectionId(current) : localizeText("\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B"))),
|
|
2368
|
+
row("effort", "\u601D\u8003\u5F3A\u5EA6", effortLabel, effortDisabled),
|
|
2369
|
+
pane ? h2(
|
|
2370
|
+
"div",
|
|
2166
2371
|
{
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
"aria-label": "\u6A21\u578B",
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
}
|
|
2372
|
+
ref: menuRef,
|
|
2373
|
+
id: `${id6}-menu`,
|
|
2374
|
+
role: "menu",
|
|
2375
|
+
"aria-label": pane === "model" ? "\u6A21\u578B" : "\u601D\u8003\u5F3A\u5EA6",
|
|
2376
|
+
"aria-busy": saving,
|
|
2377
|
+
className: "dim-modelMenu"
|
|
2174
2378
|
},
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2379
|
+
pane === "model" ? [
|
|
2380
|
+
option("default", "\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B", null, !current, null),
|
|
2381
|
+
...catalog.groups.map((group) => h2(
|
|
2382
|
+
"section",
|
|
2383
|
+
{ key: group.id, role: "group", "aria-label": group.name },
|
|
2384
|
+
h2("div", { className: "dim-modelGroupTitle" }, group.name),
|
|
2385
|
+
...group.models.map((choice) => {
|
|
2386
|
+
const selected = current?.provider === group.id && current?.model === choice.id;
|
|
2387
|
+
return option(
|
|
2388
|
+
choice.id,
|
|
2389
|
+
choice.name,
|
|
2390
|
+
choice.description ?? `${group.id}/${choice.id}`,
|
|
2391
|
+
selected,
|
|
2392
|
+
selected ? current : { provider: group.id, model: choice.id }
|
|
2393
|
+
);
|
|
2394
|
+
})
|
|
2395
|
+
))
|
|
2396
|
+
] : [
|
|
2397
|
+
option(
|
|
2398
|
+
"provider-default",
|
|
2399
|
+
defaultLabel,
|
|
2400
|
+
"\u4F7F\u7528\u6A21\u578B\u6216\u670D\u52A1\u63D0\u4F9B\u65B9\u7684\u9ED8\u8BA4\u601D\u8003\u5F3A\u5EA6\u3002",
|
|
2401
|
+
effort === void 0,
|
|
2402
|
+
current ? { provider: current.provider, model: current.model } : null
|
|
2403
|
+
),
|
|
2404
|
+
...(reasoning?.efforts ?? []).map((level) => option(
|
|
2405
|
+
`effort:${level.id}`,
|
|
2406
|
+
level.name,
|
|
2407
|
+
level.description,
|
|
2408
|
+
effort === level.id,
|
|
2409
|
+
{ ...current, reasoningEffort: level.id }
|
|
2410
|
+
))
|
|
2411
|
+
]
|
|
2412
|
+
) : null,
|
|
2413
|
+
effortHint ? h2("p", {
|
|
2414
|
+
id: `${id6}-hint`,
|
|
2415
|
+
className: "dim-modelHint",
|
|
2416
|
+
role: effortUnavailable ? "status" : void 0
|
|
2417
|
+
}, effortHint) : null,
|
|
2191
2418
|
error || !currentAvailable ? h2(
|
|
2192
2419
|
"p",
|
|
2193
2420
|
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
|
@@ -2238,11 +2465,11 @@ function normalizeAccessPolicyUserId(value) {
|
|
|
2238
2465
|
value = String(value);
|
|
2239
2466
|
}
|
|
2240
2467
|
if (typeof value !== "string") throw invalidAccessPolicy("\u7528\u6237\u6807\u8BC6\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002");
|
|
2241
|
-
const
|
|
2242
|
-
if (!
|
|
2468
|
+
const id6 = value.trim();
|
|
2469
|
+
if (!id6 || id6.length > ACCESS_POLICY_USER_ID_MAX_LENGTH || CONTROL_CHARACTERS.test(id6)) {
|
|
2243
2470
|
throw invalidAccessPolicy(`\u7528\u6237\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A\u3001\u5305\u542B\u63A7\u5236\u5B57\u7B26\u6216\u8D85\u8FC7 ${ACCESS_POLICY_USER_ID_MAX_LENGTH} \u4E2A\u5B57\u7B26\u3002`);
|
|
2244
2471
|
}
|
|
2245
|
-
return
|
|
2472
|
+
return id6;
|
|
2246
2473
|
}
|
|
2247
2474
|
function validateAccessPolicyUser(input) {
|
|
2248
2475
|
if (!hasExactKeys(input, USER_KEYS)) {
|
|
@@ -2259,7 +2486,7 @@ function validateAccessPolicyUser(input) {
|
|
|
2259
2486
|
function validateUsers(input, { listMessage, duplicateMessage }) {
|
|
2260
2487
|
if (!Array.isArray(input)) throw invalidAccessPolicy(listMessage);
|
|
2261
2488
|
const users = input.map(validateAccessPolicyUser);
|
|
2262
|
-
if (new Set(users.map(({ id:
|
|
2489
|
+
if (new Set(users.map(({ id: id6 }) => id6)).size !== users.length) {
|
|
2263
2490
|
throw invalidAccessPolicy(duplicateMessage);
|
|
2264
2491
|
}
|
|
2265
2492
|
return Object.freeze(users);
|
|
@@ -2481,8 +2708,8 @@ function optionalString(value, maxLength = 240) {
|
|
|
2481
2708
|
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
2482
2709
|
}
|
|
2483
2710
|
function opaqueId(value) {
|
|
2484
|
-
const
|
|
2485
|
-
return
|
|
2711
|
+
const id6 = optionalString(value, 128);
|
|
2712
|
+
return id6 && /^[a-z\d_-]+$/i.test(id6) ? id6 : void 0;
|
|
2486
2713
|
}
|
|
2487
2714
|
function timestamp(value) {
|
|
2488
2715
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -2813,13 +3040,13 @@ function CollapsibleAccountSection({
|
|
|
2813
3040
|
defaultOpen = false,
|
|
2814
3041
|
open: controlledOpen,
|
|
2815
3042
|
onToggle,
|
|
2816
|
-
id:
|
|
3043
|
+
id: id6,
|
|
2817
3044
|
className = "",
|
|
2818
3045
|
children
|
|
2819
3046
|
}) {
|
|
2820
3047
|
const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
|
|
2821
3048
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
2822
|
-
const contentId =
|
|
3049
|
+
const contentId = id6 ? `${id6}-content` : void 0;
|
|
2823
3050
|
const toggle = () => {
|
|
2824
3051
|
if (controlledOpen === void 0) setUncontrolledOpen((value) => !value);
|
|
2825
3052
|
onToggle?.(!open);
|
|
@@ -3492,7 +3719,7 @@ function ContextEnhancementScopeEditor({
|
|
|
3492
3719
|
)
|
|
3493
3720
|
);
|
|
3494
3721
|
}
|
|
3495
|
-
function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id:
|
|
3722
|
+
function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id6 }) {
|
|
3496
3723
|
const [draft, setDraft] = React9.useState(() => {
|
|
3497
3724
|
const normalized = normalizeContextEnhancementConfig(config);
|
|
3498
3725
|
return {
|
|
@@ -3584,7 +3811,7 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
|
|
|
3584
3811
|
}, h2(
|
|
3585
3812
|
"section",
|
|
3586
3813
|
{
|
|
3587
|
-
id:
|
|
3814
|
+
id: id6,
|
|
3588
3815
|
ref: dialogRef,
|
|
3589
3816
|
className: "dim-contextDialog",
|
|
3590
3817
|
role: "dialog",
|
|
@@ -3850,7 +4077,7 @@ function messageErrorTime(value) {
|
|
|
3850
4077
|
return null;
|
|
3851
4078
|
}
|
|
3852
4079
|
}
|
|
3853
|
-
function ChannelListHeading({ className = "", id:
|
|
4080
|
+
function ChannelListHeading({ className = "", id: id6, title, connectionLabel }) {
|
|
3854
4081
|
const helpId = React11.useId();
|
|
3855
4082
|
return h2(
|
|
3856
4083
|
"div",
|
|
@@ -3858,7 +4085,7 @@ function ChannelListHeading({ className = "", id: id5, title, connectionLabel })
|
|
|
3858
4085
|
h2(
|
|
3859
4086
|
"div",
|
|
3860
4087
|
{ className: "dim-listTitle" },
|
|
3861
|
-
h2("h3",
|
|
4088
|
+
h2("h3", id6 ? { id: id6 } : null, title),
|
|
3862
4089
|
h2(
|
|
3863
4090
|
"span",
|
|
3864
4091
|
{ className: "dim-channelHelp" },
|
|
@@ -5117,7 +5344,7 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
5117
5344
|
function createTokenChannelApi(channel4, connectionSummary, {
|
|
5118
5345
|
normalizeBotExtension = () => ({})
|
|
5119
5346
|
} = {}) {
|
|
5120
|
-
const
|
|
5347
|
+
const unwrapRpcResult14 = (result) => {
|
|
5121
5348
|
if (!isRecord2(result) || typeof result.ok !== "boolean") {
|
|
5122
5349
|
throw new Error(`${channel4} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
|
|
5123
5350
|
}
|
|
@@ -5128,7 +5355,7 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5128
5355
|
}
|
|
5129
5356
|
return result.value;
|
|
5130
5357
|
};
|
|
5131
|
-
const
|
|
5358
|
+
const normalizeBot8 = (value) => {
|
|
5132
5359
|
if (!isRecord2(value) || !id(value.botId)) return void 0;
|
|
5133
5360
|
const connected = value.connected === true;
|
|
5134
5361
|
const state = ACCOUNT_STATES2.has(value.state) ? value.state : "offline";
|
|
@@ -5162,12 +5389,12 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5162
5389
|
...isRecord2(extension) ? extension : {}
|
|
5163
5390
|
};
|
|
5164
5391
|
};
|
|
5165
|
-
const
|
|
5392
|
+
const normalizeSnapshot10 = (value) => {
|
|
5166
5393
|
const source = isRecord2(value?.snapshot) ? value.snapshot : value;
|
|
5167
5394
|
if (!isRecord2(source) || !Array.isArray(source.bots)) {
|
|
5168
5395
|
throw new Error(`${channel4} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
|
|
5169
5396
|
}
|
|
5170
|
-
const bots = source.bots.map(
|
|
5397
|
+
const bots = source.bots.map(normalizeBot8).filter(Boolean);
|
|
5171
5398
|
return {
|
|
5172
5399
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
5173
5400
|
bots,
|
|
@@ -5176,11 +5403,11 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5176
5403
|
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
5177
5404
|
};
|
|
5178
5405
|
};
|
|
5179
|
-
const
|
|
5406
|
+
const presentError14 = (error) => ({
|
|
5180
5407
|
code: text2(error?.code, `${channel4.toUpperCase()}_ERROR`, 80),
|
|
5181
5408
|
message: text2(error?.message, `${channel4}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
|
|
5182
5409
|
});
|
|
5183
|
-
return Object.freeze({ unwrapRpcResult:
|
|
5410
|
+
return Object.freeze({ unwrapRpcResult: unwrapRpcResult14, normalizeSnapshot: normalizeSnapshot10, presentError: presentError14 });
|
|
5184
5411
|
}
|
|
5185
5412
|
|
|
5186
5413
|
// plugin-src/client/channels/discord/api.js
|
|
@@ -5245,7 +5472,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5245
5472
|
AccountSettings = null,
|
|
5246
5473
|
accountSettingsEndpoint = null
|
|
5247
5474
|
} = definition;
|
|
5248
|
-
function
|
|
5475
|
+
function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
5249
5476
|
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
5250
5477
|
const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
|
|
5251
5478
|
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
@@ -5536,7 +5763,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5536
5763
|
title: `\u5DF2\u63A5\u5165\u7684 ${channel4} \u673A\u5668\u4EBA`,
|
|
5537
5764
|
connectionLabel
|
|
5538
5765
|
}),
|
|
5539
|
-
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(
|
|
5766
|
+
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard6, {
|
|
5540
5767
|
account,
|
|
5541
5768
|
busy: busyByBot[account.botId],
|
|
5542
5769
|
testNotice: testNoticeByBot[account.botId],
|
|
@@ -5698,7 +5925,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5698
5925
|
)
|
|
5699
5926
|
)));
|
|
5700
5927
|
}
|
|
5701
|
-
return { SettingsTab, AccountCard:
|
|
5928
|
+
return { SettingsTab, AccountCard: AccountCard6 };
|
|
5702
5929
|
}
|
|
5703
5930
|
|
|
5704
5931
|
// plugin-src/client/channels/discord/styles.js
|
|
@@ -6344,7 +6571,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
6344
6571
|
h2("span", null, repairing ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u8865\u5168\u6743\u9650\u4E0E\u56DE\u8C03` : grantingGroupMessages ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
|
|
6345
6572
|
),
|
|
6346
6573
|
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u8865\u5168\u6743\u9650" : grantingGroupMessages ? "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
6347
|
-
h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u589E\u91CF\u8865\u5145\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\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"),
|
|
6574
|
+
h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u589E\u91CF\u8865\u5145\u5F53\u524D\u7F3A\u5C11\u7684\u5361\u7247\u6309\u94AE\u56DE\u8C03\u3001\u8BFB\u53D6\u7528\u6237\u6D88\u606F\u5185\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:message:readonly\uFF08\u98DE\u4E66\u663E\u793A\u4E3A\u201C\u83B7\u53D6\u5355\u804A\u3001\u7FA4\u7EC4\u6D88\u606F\u201D\uFF09\u3001\u4E0A\u4F20\u673A\u5668\u4EBA\u56FE\u7247\u6216\u6587\u4EF6\u6240\u9700\u7684 im:resource\u3001\u63A5\u6536\u7FA4\u5185\u5176\u4ED6\u673A\u5668\u4EBA @ \u5F53\u524D\u673A\u5668\u4EBA\u6240\u9700\u7684 im:message.group_at_msg.include_bot:readonly\uFF0C\u4EE5\u53CA\u539F\u751F\u547D\u4EE4\u9762\u677F\u6240\u9700\u7684 application:app_slash_command:read / write\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u9875\u53EA\u663E\u793A\u5F53\u524D\u7F3A\u5C11\u9879\uFF0C\u5B8C\u6210\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\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"),
|
|
6348
6575
|
h2(
|
|
6349
6576
|
"ol",
|
|
6350
6577
|
{ className: "bxf-steps dim-steps" },
|
|
@@ -6428,14 +6655,14 @@ var HEALTH_LABELS = {
|
|
|
6428
6655
|
offline: "\u8FDE\u63A5\u4E2D\u65AD",
|
|
6429
6656
|
error: "\u9700\u8981\u5904\u7406"
|
|
6430
6657
|
};
|
|
6431
|
-
function formatCheckedTime(
|
|
6432
|
-
if (!
|
|
6658
|
+
function formatCheckedTime(timestamp8) {
|
|
6659
|
+
if (!timestamp8) return "\u5C1A\u672A\u68C0\u67E5";
|
|
6433
6660
|
try {
|
|
6434
6661
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
6435
6662
|
hour: "2-digit",
|
|
6436
6663
|
minute: "2-digit",
|
|
6437
6664
|
second: "2-digit"
|
|
6438
|
-
}).format(new Date(
|
|
6665
|
+
}).format(new Date(timestamp8));
|
|
6439
6666
|
} catch {
|
|
6440
6667
|
return "\u521A\u521A";
|
|
6441
6668
|
}
|
|
@@ -6489,6 +6716,7 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
|
6489
6716
|
}
|
|
6490
6717
|
function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
6491
6718
|
const titleId = React15.useId();
|
|
6719
|
+
const helpId = `${titleId}-help`;
|
|
6492
6720
|
const current = value === true ? "on" : "off";
|
|
6493
6721
|
const [saving, setSaving] = React15.useState(false);
|
|
6494
6722
|
const [error, setError] = React15.useState(null);
|
|
@@ -6514,7 +6742,26 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
6514
6742
|
h2(
|
|
6515
6743
|
"div",
|
|
6516
6744
|
{ className: "dim-feishuGroupControlHeader" },
|
|
6517
|
-
h2(
|
|
6745
|
+
h2(
|
|
6746
|
+
"div",
|
|
6747
|
+
{ className: "dim-presetTitle" },
|
|
6748
|
+
h2("h3", { id: titleId }, "\u5206\u6B65\u76F4\u63A8"),
|
|
6749
|
+
h2(
|
|
6750
|
+
"span",
|
|
6751
|
+
{ className: "dim-presetHelp" },
|
|
6752
|
+
h2("button", {
|
|
6753
|
+
type: "button",
|
|
6754
|
+
className: "dim-presetHelpButton",
|
|
6755
|
+
"aria-label": "\u67E5\u770B\u5206\u6B65\u76F4\u63A8\u8BF4\u660E",
|
|
6756
|
+
"aria-describedby": helpId
|
|
6757
|
+
}, h2("span", { "aria-hidden": "true" }, "?")),
|
|
6758
|
+
h2("span", {
|
|
6759
|
+
id: helpId,
|
|
6760
|
+
className: "dim-presetTooltip",
|
|
6761
|
+
role: "tooltip"
|
|
6762
|
+
}, "\u5F00\u542F\u540E\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E")
|
|
6763
|
+
)
|
|
6764
|
+
),
|
|
6518
6765
|
saving ? h2("span", { className: "dim-feishuGroupControlStatus", role: "status" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
6519
6766
|
),
|
|
6520
6767
|
h2(
|
|
@@ -6531,11 +6778,6 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
6531
6778
|
h2("option", { value: "off" }, "\u5173\u95ED\uFF08\u4FDD\u6301\u6D41\u5F0F\u5361\u6A21\u5F0F\uFF09"),
|
|
6532
6779
|
h2("option", { value: "on" }, "\u5F00\u542F\uFF08\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E\uFF09")
|
|
6533
6780
|
),
|
|
6534
|
-
h2(
|
|
6535
|
-
"p",
|
|
6536
|
-
{ className: "dim-feishuGroupHelp" },
|
|
6537
|
-
"\u5F00\u542F\u540E\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E"
|
|
6538
|
-
),
|
|
6539
6781
|
error ? h2("p", {
|
|
6540
6782
|
className: "dim-feishuGroupError",
|
|
6541
6783
|
role: "alert"
|
|
@@ -6993,15 +7235,15 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
6993
7235
|
if (targetedUpdate && (provision2.operation !== operation || provision2.botId !== botId)) {
|
|
6994
7236
|
throw new Error(grantingGroupMessages ? "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801" : "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6743\u9650\u8865\u5168\u4E8C\u7EF4\u7801");
|
|
6995
7237
|
}
|
|
6996
|
-
const
|
|
6997
|
-
setNow(
|
|
7238
|
+
const timestamp8 = Date.now();
|
|
7239
|
+
setNow(timestamp8);
|
|
6998
7240
|
setModel((current) => ({
|
|
6999
7241
|
...current,
|
|
7000
7242
|
provisioning: {
|
|
7001
7243
|
phase: "qr",
|
|
7002
7244
|
...provision2,
|
|
7003
7245
|
...botName ? { botName } : {},
|
|
7004
|
-
durationMs: Math.max(1, provision2.expiresAt -
|
|
7246
|
+
durationMs: Math.max(1, provision2.expiresAt - timestamp8),
|
|
7005
7247
|
expired: false
|
|
7006
7248
|
}
|
|
7007
7249
|
}));
|
|
@@ -7118,9 +7360,9 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
7118
7360
|
React15.useEffect(() => {
|
|
7119
7361
|
if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
|
|
7120
7362
|
const tick = () => {
|
|
7121
|
-
const
|
|
7122
|
-
setNow(
|
|
7123
|
-
if (
|
|
7363
|
+
const timestamp8 = Date.now();
|
|
7364
|
+
setNow(timestamp8);
|
|
7365
|
+
if (timestamp8 >= countdownExpiresAt) {
|
|
7124
7366
|
setModel((current) => current.provisioning?.attemptId === countdownAttemptId ? { ...current, provisioning: { ...current.provisioning, expired: true } } : current);
|
|
7125
7367
|
}
|
|
7126
7368
|
};
|
|
@@ -10353,17 +10595,13 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
10353
10595
|
)));
|
|
10354
10596
|
}
|
|
10355
10597
|
|
|
10356
|
-
// plugin-src/client/channels/
|
|
10357
|
-
var
|
|
10358
|
-
|
|
10359
|
-
// plugin-src/client/channels/weixin/api.js
|
|
10360
|
-
var WEIXIN_RPC_CHANNEL = "/weixin";
|
|
10361
|
-
var WEIXIN_ENDPOINTS = Object.freeze({
|
|
10598
|
+
// plugin-src/client/channels/wecom-app/api.js
|
|
10599
|
+
var WECOM_APP_RPC_CHANNEL = "/wecom-app";
|
|
10600
|
+
var WECOM_APP_ENDPOINTS = Object.freeze({
|
|
10362
10601
|
status: "connection.status",
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
cancelProvisioning: "provision.cancel",
|
|
10602
|
+
bindApp: "bot.bind",
|
|
10603
|
+
updateSettings: "bot.settings.update",
|
|
10604
|
+
resetCallbackSecret: "bot.callback-secret.reset",
|
|
10367
10605
|
reconnectBot: "bot.reconnect",
|
|
10368
10606
|
deleteBot: "bot.delete",
|
|
10369
10607
|
setWorkspace: "bot.workspace.set",
|
|
@@ -10373,25 +10611,24 @@ var WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
10373
10611
|
setAccessPolicy: "bot.access-policy.set"
|
|
10374
10612
|
});
|
|
10375
10613
|
var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
10376
|
-
var PROVISION_STATES4 = /* @__PURE__ */ new Set([
|
|
10377
|
-
"starting",
|
|
10378
|
-
"pending",
|
|
10379
|
-
"scanned",
|
|
10380
|
-
"needs_verification",
|
|
10381
|
-
"connecting",
|
|
10382
|
-
"connected",
|
|
10383
|
-
"expired",
|
|
10384
|
-
"failed",
|
|
10385
|
-
"cancelled"
|
|
10386
|
-
]);
|
|
10387
10614
|
function isRecord6(value) {
|
|
10388
10615
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
10389
10616
|
}
|
|
10390
|
-
function
|
|
10391
|
-
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
10617
|
+
function text5(value, fallback, max = 240) {
|
|
10618
|
+
return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
|
|
10619
|
+
}
|
|
10620
|
+
function id4(value) {
|
|
10621
|
+
const result = text5(value, "", 128);
|
|
10622
|
+
return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
|
|
10623
|
+
}
|
|
10624
|
+
function optionalUrl(value) {
|
|
10625
|
+
const raw = text5(value, "", 512);
|
|
10626
|
+
return /^https?:\/\//iu.test(raw) ? raw : null;
|
|
10392
10627
|
}
|
|
10393
10628
|
function timestamp5(value) {
|
|
10394
|
-
|
|
10629
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
10630
|
+
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
10631
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
10395
10632
|
}
|
|
10396
10633
|
function normalizeTestMessage4(value) {
|
|
10397
10634
|
if (!isRecord6(value)) return null;
|
|
@@ -10401,154 +10638,993 @@ function normalizeTestMessage4(value) {
|
|
|
10401
10638
|
return { sent: false, code };
|
|
10402
10639
|
}
|
|
10403
10640
|
function unwrapRpcResult8(result) {
|
|
10404
|
-
if (!isRecord6(result) || typeof result.ok !== "boolean")
|
|
10405
|
-
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
10406
|
-
}
|
|
10641
|
+
if (!isRecord6(result) || typeof result.ok !== "boolean") throw new Error("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
10407
10642
|
if (!result.ok) {
|
|
10408
|
-
const error = new Error(
|
|
10409
|
-
error.code =
|
|
10643
|
+
const error = new Error(text5(result.error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25"));
|
|
10644
|
+
error.code = text5(result.error?.code, "WECOM_APP_RPC_ERROR", 80);
|
|
10410
10645
|
throw error;
|
|
10411
10646
|
}
|
|
10412
10647
|
return result.value;
|
|
10413
10648
|
}
|
|
10414
|
-
function safeQrSource5(value) {
|
|
10415
|
-
return typeof value === "string" && /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
|
|
10416
|
-
}
|
|
10417
|
-
function safeVerificationUrl(value) {
|
|
10418
|
-
if (typeof value !== "string") return void 0;
|
|
10419
|
-
try {
|
|
10420
|
-
const url = new URL(value);
|
|
10421
|
-
const host = url.hostname.toLowerCase();
|
|
10422
|
-
return url.protocol === "https:" && (host === "weixin.qq.com" || host.endsWith(".weixin.qq.com") || host === "wechat.com" || host.endsWith(".wechat.com")) ? url.toString() : void 0;
|
|
10423
|
-
} catch {
|
|
10424
|
-
return void 0;
|
|
10425
|
-
}
|
|
10426
|
-
}
|
|
10427
|
-
function normalizeProvisioning5(value) {
|
|
10428
|
-
if (!isRecord6(value) || !string(value.attemptId)) {
|
|
10429
|
-
throw new Error("\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
10430
|
-
}
|
|
10431
|
-
const status = PROVISION_STATES4.has(value.status) ? value.status : "failed";
|
|
10432
|
-
const result = {
|
|
10433
|
-
attemptId: string(value.attemptId),
|
|
10434
|
-
status,
|
|
10435
|
-
expiresAt: timestamp5(value.expiresAt) ?? Date.now(),
|
|
10436
|
-
pollIntervalMs: Math.min(5e3, Math.max(500, Number(value.pollIntervalMs) || 1e3)),
|
|
10437
|
-
verificationRequired: value.verificationRequired === true || status === "needs_verification"
|
|
10438
|
-
};
|
|
10439
|
-
const verificationUrl = safeVerificationUrl(value.verificationUrl);
|
|
10440
|
-
const qrCodeDataUrl = safeQrSource5(value.qrCodeDataUrl);
|
|
10441
|
-
if (verificationUrl) result.verificationUrl = verificationUrl;
|
|
10442
|
-
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
10443
|
-
if (string(value.botId)) result.botId = string(value.botId);
|
|
10444
|
-
if (value.alreadyConnected === true) result.alreadyConnected = true;
|
|
10445
|
-
if (isRecord6(value.error)) {
|
|
10446
|
-
result.error = {
|
|
10447
|
-
code: string(value.error.code, "WEIXIN_PROVISION_FAILED"),
|
|
10448
|
-
message: string(value.error.message, "\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210")
|
|
10449
|
-
};
|
|
10450
|
-
}
|
|
10451
|
-
return result;
|
|
10452
|
-
}
|
|
10453
10649
|
function normalizeBot5(value) {
|
|
10454
|
-
if (!isRecord6(value) || !
|
|
10455
|
-
const state = ACCOUNT_STATES5.has(value.state) ? value.state : "error";
|
|
10650
|
+
if (!isRecord6(value) || !id4(value.botId)) return void 0;
|
|
10456
10651
|
const connected = value.connected === true;
|
|
10652
|
+
const state = ACCOUNT_STATES5.has(value.state) ? value.state : "offline";
|
|
10457
10653
|
return {
|
|
10458
|
-
botId:
|
|
10459
|
-
state: connected ? "connected" : state,
|
|
10654
|
+
botId: id4(value.botId),
|
|
10460
10655
|
connected,
|
|
10461
|
-
|
|
10462
|
-
workspace:
|
|
10656
|
+
state: connected ? "connected" : state,
|
|
10657
|
+
workspace: text5(value.workspace, "", 4096),
|
|
10463
10658
|
model: normalizeModelSelection(value.model),
|
|
10464
10659
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
10465
10660
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
10466
10661
|
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
10467
10662
|
bot: {
|
|
10468
|
-
name:
|
|
10469
|
-
|
|
10663
|
+
name: text5(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", 100),
|
|
10664
|
+
corpIdMasked: text5(value.bot?.corpIdMasked, "\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58", 140),
|
|
10665
|
+
agentId: text5(value.bot?.agentId, "", 32),
|
|
10666
|
+
apiBaseUrl: optionalUrl(value.bot?.apiBaseUrl) ?? "",
|
|
10667
|
+
callbackBaseUrl: optionalUrl(value.bot?.callbackBaseUrl) ?? "",
|
|
10668
|
+
streamEnabled: value.bot?.streamEnabled !== false,
|
|
10669
|
+
callbackUrl: optionalUrl(value.bot?.callbackUrl) ?? ""
|
|
10470
10670
|
},
|
|
10471
10671
|
health: {
|
|
10472
|
-
|
|
10473
|
-
summary: string(value.health?.summary, connected ? "\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38" : "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA"),
|
|
10672
|
+
summary: text5(value.health?.summary, connected ? "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u56DE\u8C03\u901A\u9053\u5C31\u7EEA" : "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
10474
10673
|
lastCheckedAt: timestamp5(value.health?.lastCheckedAt)
|
|
10475
10674
|
},
|
|
10476
|
-
stats: {
|
|
10477
|
-
messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
|
|
10478
|
-
messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
|
|
10479
|
-
},
|
|
10480
10675
|
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
10481
10676
|
error: isRecord6(value.error) ? {
|
|
10482
|
-
code:
|
|
10483
|
-
message:
|
|
10677
|
+
code: text5(value.error.code, "WECOM_APP_ACCOUNT_ERROR", 80),
|
|
10678
|
+
message: text5(value.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
|
|
10484
10679
|
} : null
|
|
10485
10680
|
};
|
|
10486
10681
|
}
|
|
10487
10682
|
function normalizeSnapshot7(value) {
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
const bots = value.bots.map(normalizeBot5).filter(Boolean);
|
|
10683
|
+
const source = isRecord6(value?.snapshot) ? value.snapshot : value;
|
|
10684
|
+
if (!isRecord6(source) || !Array.isArray(source.bots)) throw new Error("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
10685
|
+
const bots = source.bots.map(normalizeBot5).filter(Boolean);
|
|
10492
10686
|
return {
|
|
10493
|
-
|
|
10494
|
-
revision: Number(value.revision) || 0,
|
|
10495
|
-
state: string(value.state, "offline"),
|
|
10687
|
+
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
10496
10688
|
bots,
|
|
10497
|
-
totals: {
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
|
|
10502
|
-
testMessage: normalizeTestMessage4(value.testMessage),
|
|
10503
|
-
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
|
10504
|
-
modelCatalog: normalizeModelCatalog(value.modelCatalog)
|
|
10689
|
+
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
10690
|
+
testMessage: normalizeTestMessage4(source.testMessage),
|
|
10691
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
10692
|
+
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
10505
10693
|
};
|
|
10506
10694
|
}
|
|
10507
10695
|
function presentError8(error) {
|
|
10508
10696
|
return {
|
|
10509
|
-
code:
|
|
10510
|
-
message:
|
|
10697
|
+
code: text5(error?.code, "WECOM_APP_ERROR", 80),
|
|
10698
|
+
message: text5(error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
10511
10699
|
};
|
|
10512
10700
|
}
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10701
|
+
|
|
10702
|
+
// plugin-src/client/channels/wecom-app/index.js
|
|
10703
|
+
var React20 = __toESM(require("react"), 1);
|
|
10704
|
+
|
|
10705
|
+
// plugin-src/client/channels/wecom-app/styles.js
|
|
10706
|
+
var WECOM_APP_STYLE_ID = "xmanrui-dsh-im-wecom-app-settings";
|
|
10707
|
+
var CSS9 = String.raw`
|
|
10708
|
+
.dwecomapp-page { --ddt-accent: #07c160; --ddt-accent-deep: #059a4c; --ddt-accent-wash: #eefaf3; }
|
|
10709
|
+
.dwecomapp-avatar, .dwecomapp-brand { color: #07c160; background: #fff; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); }
|
|
10710
|
+
.dwecomapp-avatar svg, .dwecomapp-brand svg { display: block; }
|
|
10711
|
+
.dim-appFieldGrid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
|
|
10712
|
+
.dim-callbackBox { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border: 1px dashed var(--dsw-alias-border-l2, #e5e6eb); border-radius: 8px; }
|
|
10713
|
+
.dim-callbackBox strong { font-size: 12px; color: var(--dsw-alias-text-secondary, #646a73); }
|
|
10714
|
+
.dim-callbackRow { display: flex; gap: 8px; align-items: center; }
|
|
10715
|
+
.dim-callbackRow input { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
|
10716
|
+
.dim-appSwitchRow { display: flex; align-items: center; gap: 8px; font-size: 13px; }
|
|
10717
|
+
`;
|
|
10718
|
+
function installWecomAppStyles() {
|
|
10719
|
+
if (typeof document === "undefined") return () => {
|
|
10720
|
+
};
|
|
10721
|
+
const existing = document.querySelector(`style[data-plugin-css="${WECOM_APP_STYLE_ID}"]`);
|
|
10722
|
+
if (existing) return () => {
|
|
10723
|
+
};
|
|
10724
|
+
const style = document.createElement("style");
|
|
10725
|
+
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
10726
|
+
style.dataset.pluginCss = WECOM_APP_STYLE_ID;
|
|
10727
|
+
style.textContent = CSS9;
|
|
10728
|
+
document.head.appendChild(style);
|
|
10729
|
+
return () => style.remove();
|
|
10516
10730
|
}
|
|
10517
10731
|
|
|
10518
|
-
// plugin-src/client/channels/
|
|
10732
|
+
// plugin-src/client/channels/wecom-app/index.js
|
|
10519
10733
|
var Button12 = React20.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
10520
10734
|
return h2("button", {
|
|
10521
10735
|
...props,
|
|
10522
10736
|
ref,
|
|
10523
10737
|
type: "button",
|
|
10524
|
-
className: `
|
|
10738
|
+
className: `ddt-button ${className}`.trim(),
|
|
10525
10739
|
"data-kind": kind
|
|
10526
10740
|
}, children);
|
|
10527
10741
|
});
|
|
10742
|
+
function checkedTime5(value) {
|
|
10743
|
+
if (!value) return "\u5C1A\u672A\u68C0\u67E5";
|
|
10744
|
+
try {
|
|
10745
|
+
return new Intl.DateTimeFormat("zh-CN", {
|
|
10746
|
+
hour: "2-digit",
|
|
10747
|
+
minute: "2-digit",
|
|
10748
|
+
second: "2-digit"
|
|
10749
|
+
}).format(new Date(value));
|
|
10750
|
+
} catch {
|
|
10751
|
+
return "\u521A\u521A";
|
|
10752
|
+
}
|
|
10753
|
+
}
|
|
10528
10754
|
function Heading5({ totals, adding, busy, onAdd, addButtonRef }) {
|
|
10529
10755
|
return h2(
|
|
10530
10756
|
"div",
|
|
10531
|
-
{ className: "
|
|
10757
|
+
{ className: "ddt-heading" },
|
|
10532
10758
|
h2(
|
|
10533
10759
|
"div",
|
|
10534
|
-
{ className: "
|
|
10535
|
-
h2(
|
|
10536
|
-
|
|
10537
|
-
className: "dim-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10760
|
+
{ className: "ddt-tools" },
|
|
10761
|
+
h2(
|
|
10762
|
+
"div",
|
|
10763
|
+
{ className: "dim-bindActions" },
|
|
10764
|
+
h2(Button12, {
|
|
10765
|
+
kind: "primary",
|
|
10766
|
+
className: "dim-scanButton",
|
|
10767
|
+
onClick: onAdd,
|
|
10768
|
+
disabled: adding || busy,
|
|
10769
|
+
ref: addButtonRef,
|
|
10770
|
+
"aria-label": "\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528"
|
|
10771
|
+
}, adding ? "\u6536\u8D77\u8868\u5355" : "\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528")
|
|
10772
|
+
),
|
|
10773
|
+
totals.configured > 0 ? h2(
|
|
10774
|
+
"div",
|
|
10775
|
+
{ className: "ddt-badge dim-onlineBadge" },
|
|
10776
|
+
h2("span", null, `${totals.connected} / ${totals.configured} \u5728\u7EBF`)
|
|
10777
|
+
) : null
|
|
10778
|
+
)
|
|
10779
|
+
);
|
|
10780
|
+
}
|
|
10781
|
+
function LoadingView5() {
|
|
10782
|
+
return h2(
|
|
10783
|
+
"div",
|
|
10784
|
+
{ className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView", "aria-busy": "true" },
|
|
10785
|
+
h2("div", { className: "ddt-spinner dim-spinner" }),
|
|
10786
|
+
h2("span", null, "\u6B63\u5728\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001\u2026")
|
|
10787
|
+
);
|
|
10788
|
+
}
|
|
10789
|
+
function EmptyView5({ busy, onStart }) {
|
|
10790
|
+
return h2(
|
|
10791
|
+
"div",
|
|
10792
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
10793
|
+
h2(
|
|
10794
|
+
"div",
|
|
10795
|
+
{ className: "ddt-cardBody ddt-empty dim-surfaceBody dim-emptyView" },
|
|
10796
|
+
h2(
|
|
10797
|
+
"div",
|
|
10798
|
+
{ className: "dim-emptyCopy" },
|
|
10799
|
+
h2(
|
|
10800
|
+
"div",
|
|
10801
|
+
{ className: "ddt-stateLabel dim-stateLabel" },
|
|
10802
|
+
h2("span", { className: "ddt-dot dim-stateDot" }),
|
|
10803
|
+
h2("span", null, "\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528")
|
|
10804
|
+
),
|
|
10805
|
+
h2("h3", null, "\u5728\u4F01\u4E1A\u5FAE\u4FE1\u4E2D\u521B\u5EFA\u81EA\u5EFA\u5E94\u7528\uFF0C\u5373\u53EF\u5728\u5FAE\u4FE1\u91CC\u4F7F\u7528"),
|
|
10806
|
+
h2("p", null, "\u5728\u5E94\u7528\u7BA1\u7406\u540E\u53F0\u521B\u5EFA\u81EA\u5EFA\u5E94\u7528\uFF0C\u5F00\u542F\u300C\u63A5\u6536\u6D88\u606F\u300D\u5E76\u586B\u5165\u4E0B\u9762\u7684\u53C2\u6570\u3002\u6210\u5458\u7684\u5FAE\u4FE1\u5173\u6CE8\u8BE5\u4F01\u4E1A\u7684\u5FAE\u4FE1\u63D2\u4EF6\u540E\uFF0C\u5C31\u80FD\u5728\u5FAE\u4FE1\u4E2D\u4E0E\u672C\u5E94\u7528\u53CC\u5411\u5BF9\u8BDD\u3002"),
|
|
10807
|
+
h2(
|
|
10808
|
+
"div",
|
|
10809
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
10810
|
+
h2(Button12, { kind: "primary", onClick: onStart, disabled: busy }, "\u586B\u5199\u5E94\u7528\u53C2\u6570")
|
|
10811
|
+
)
|
|
10812
|
+
),
|
|
10813
|
+
h2(
|
|
10814
|
+
"div",
|
|
10815
|
+
{ className: "ddt-brandMark dim-emptyBrand dwecomapp-brand", "aria-hidden": "true" },
|
|
10816
|
+
h2(WecomLogoGlyph, { size: 64 })
|
|
10817
|
+
)
|
|
10818
|
+
)
|
|
10819
|
+
);
|
|
10820
|
+
}
|
|
10821
|
+
function Field({ label, value, onChange, placeholder, busy, required = false, type = "text" }) {
|
|
10822
|
+
return h2(
|
|
10823
|
+
"label",
|
|
10824
|
+
{ className: "dim-credentialField" },
|
|
10825
|
+
h2("span", null, label),
|
|
10826
|
+
h2("input", {
|
|
10827
|
+
value,
|
|
10828
|
+
onChange: (event) => onChange(event.target.value),
|
|
10829
|
+
placeholder,
|
|
10830
|
+
type,
|
|
10831
|
+
autoCapitalize: "none",
|
|
10832
|
+
autoCorrect: "off",
|
|
10833
|
+
spellCheck: false,
|
|
10834
|
+
autoComplete: "off",
|
|
10835
|
+
disabled: busy,
|
|
10836
|
+
required
|
|
10837
|
+
})
|
|
10838
|
+
);
|
|
10839
|
+
}
|
|
10840
|
+
function BindForm({ busy, error, onSubmit, onCancel }) {
|
|
10841
|
+
const [corpId, setCorpId] = React20.useState("");
|
|
10842
|
+
const [agentId, setAgentId] = React20.useState("");
|
|
10843
|
+
const [secret, setSecret] = React20.useState("");
|
|
10844
|
+
const [token, setToken] = React20.useState("");
|
|
10845
|
+
const [aesKey, setAesKey] = React20.useState("");
|
|
10846
|
+
const [apiBaseUrl, setApiBaseUrl] = React20.useState("");
|
|
10847
|
+
const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState("");
|
|
10848
|
+
const [streamEnabled, setStreamEnabled] = React20.useState(true);
|
|
10849
|
+
const headingId = React20.useId();
|
|
10850
|
+
const formRef = React20.useRef(null);
|
|
10851
|
+
const submit = (event) => {
|
|
10852
|
+
event.preventDefault();
|
|
10853
|
+
if (busy) return;
|
|
10854
|
+
void onSubmit?.({
|
|
10855
|
+
corpId: corpId.trim(),
|
|
10856
|
+
agentId: agentId.trim(),
|
|
10857
|
+
secret: secret.trim(),
|
|
10858
|
+
token: token.trim(),
|
|
10859
|
+
encodingAESKey: aesKey.trim(),
|
|
10860
|
+
apiBaseUrl: apiBaseUrl.trim() || void 0,
|
|
10861
|
+
callbackBaseUrl: callbackBaseUrl.trim() || void 0,
|
|
10862
|
+
streamEnabled
|
|
10863
|
+
});
|
|
10864
|
+
};
|
|
10865
|
+
return h2(
|
|
10866
|
+
"section",
|
|
10867
|
+
{
|
|
10868
|
+
className: "ddt-card dim-surfaceCard dim-credentialPanel",
|
|
10869
|
+
"aria-labelledby": headingId
|
|
10870
|
+
},
|
|
10871
|
+
h2("h3", { id: headingId, className: "dim-credentialTitle" }, "\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528"),
|
|
10872
|
+
h2(
|
|
10873
|
+
"form",
|
|
10874
|
+
{ ref: formRef, className: "dim-credentialForm", onSubmit: submit },
|
|
10875
|
+
h2(
|
|
10876
|
+
"div",
|
|
10877
|
+
{ className: "dim-appFieldGrid" },
|
|
10878
|
+
h2(Field, { label: "\u4F01\u4E1A ID\uFF08CorpID\uFF09", value: corpId, onChange: setCorpId, placeholder: "\u4F8B\u5982 ww1234567890abcdef", busy, required: true }),
|
|
10879
|
+
h2(Field, { label: "\u5E94\u7528 AgentId", value: agentId, onChange: setAgentId, placeholder: "\u4F8B\u5982 1000002", busy, required: true }),
|
|
10880
|
+
h2(Field, { label: "\u5E94\u7528 Secret", value: secret, onChange: setSecret, placeholder: "\u5E94\u7528\u8BE6\u60C5\u9875\u7684 Secret", busy, required: true, type: "password" }),
|
|
10881
|
+
h2(Field, { label: "\u56DE\u8C03 Token", value: token, onChange: setToken, placeholder: "\u63A5\u6536\u6D88\u606F \u2192 API \u63A5\u6536\u4E2D\u7684 Token", busy, required: true, type: "password" }),
|
|
10882
|
+
h2(Field, { label: "EncodingAESKey", value: aesKey, onChange: setAesKey, placeholder: "43 \u4F4D\u5B57\u6BCD\u6216\u6570\u5B57", busy, required: true, type: "password" }),
|
|
10883
|
+
h2(Field, { label: "\u4EE3\u7406\u5730\u5740\uFF08\u53EF\u9009\uFF09", value: apiBaseUrl, onChange: setApiBaseUrl, placeholder: "\u7559\u7A7A\u76F4\u8FDE qyapi.weixin.qq.com", busy })
|
|
10884
|
+
),
|
|
10885
|
+
h2(
|
|
10886
|
+
"div",
|
|
10887
|
+
{ className: "dim-appFieldGrid" },
|
|
10888
|
+
h2(Field, { label: "\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF08\u53EF\u9009\uFF09", value: callbackBaseUrl, onChange: setCallbackBaseUrl, placeholder: "\u4F8B\u5982 https://im.example.com", busy }),
|
|
10889
|
+
h2(
|
|
10890
|
+
"div",
|
|
10891
|
+
{ className: "dim-appSwitchRow" },
|
|
10892
|
+
h2("button", {
|
|
10893
|
+
type: "button",
|
|
10894
|
+
className: "ddt-button dim-streamToggle",
|
|
10895
|
+
"aria-pressed": streamEnabled ? "true" : "false",
|
|
10896
|
+
onClick: () => setStreamEnabled((value) => !value),
|
|
10897
|
+
disabled: busy
|
|
10898
|
+
}, streamEnabled ? "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00" : "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173"),
|
|
10899
|
+
h2("span", { className: "dim-switchHint" }, "\u4F01\u4E1A\u5FAE\u4FE1\u5BA2\u6237\u7AEF\u5B9E\u65F6\u51FA\u5B57\uFF1B\u5FAE\u4FE1\u7AEF\u4E0D\u652F\u6301\u65F6\u81EA\u52A8\u6539\u4E3A\u6574\u6BB5\u53D1\u9001")
|
|
10900
|
+
)
|
|
10901
|
+
),
|
|
10902
|
+
error ? h2("div", { className: "ddt-inlineError dim-inlineError", role: "alert" }, h2("p", null, error.message)) : null,
|
|
10903
|
+
h2(
|
|
10904
|
+
"div",
|
|
10905
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
10906
|
+
h2(Button12, { kind: "primary", onClick: () => formRef.current?.requestSubmit(), disabled: busy }, busy ? "\u6B63\u5728\u7ED1\u5B9A\u2026" : "\u4FDD\u5B58\u5E76\u8FDE\u63A5"),
|
|
10907
|
+
h2(Button12, { kind: "quiet", onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10908
|
+
)
|
|
10909
|
+
)
|
|
10910
|
+
);
|
|
10911
|
+
}
|
|
10912
|
+
function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
|
|
10913
|
+
const [copied, setCopied] = React20.useState(false);
|
|
10914
|
+
const copy = async () => {
|
|
10915
|
+
try {
|
|
10916
|
+
await navigator.clipboard.writeText(url);
|
|
10917
|
+
setCopied(true);
|
|
10918
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
10919
|
+
} catch {
|
|
10920
|
+
setCopied(false);
|
|
10921
|
+
}
|
|
10922
|
+
onCopy?.();
|
|
10923
|
+
};
|
|
10924
|
+
return h2(
|
|
10925
|
+
"div",
|
|
10926
|
+
{ className: "dim-callbackBox" },
|
|
10927
|
+
h2("strong", null, "\u56DE\u8C03 URL\uFF08\u586B\u5165\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u300C\u63A5\u6536\u6D88\u606F \u2192 \u8BBE\u7F6EAPI\u63A5\u6536\u300D\uFF09"),
|
|
10928
|
+
h2(
|
|
10929
|
+
"div",
|
|
10930
|
+
{ className: "dim-callbackRow" },
|
|
10931
|
+
h2("input", {
|
|
10932
|
+
value: url || "\u672A\u914D\u7F6E\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF1A\u8BF7\u5728\u672C\u9875\u300C\u8BBE\u7F6E\u300D\u4E2D\u586B\u5199\u56DE\u8C03\u57FA\u5740\uFF0C\u6216\u624B\u52A8\u62FC\u63A5 \u56DE\u8C03\u57FA\u5740 + \u8DEF\u5F84",
|
|
10933
|
+
readOnly: true,
|
|
10934
|
+
onFocus: (event) => event.target.select?.()
|
|
10935
|
+
}),
|
|
10936
|
+
url ? h2(Button12, { onClick: copy, disabled: busy, small: true }, copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236") : null,
|
|
10937
|
+
h2(Button12, { kind: "danger", onClick: onReset, disabled: busy || resetBusy }, resetBusy ? "\u91CD\u7F6E\u4E2D\u2026" : "\u91CD\u7F6E\u5BC6\u94A5")
|
|
10938
|
+
),
|
|
10939
|
+
h2(
|
|
10940
|
+
"span",
|
|
10941
|
+
{ className: "dim-callbackHint" },
|
|
10942
|
+
"\u91CD\u7F6E\u5BC6\u94A5\u540E\u56DE\u8C03 URL \u4F1A\u53D8\u5316\uFF0C\u9700\u8981\u540C\u6B65\u66F4\u65B0\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u3002\u82E5\u516C\u7F51\u53CD\u4EE3\u672A\u5C31\u7EEA\uFF0C\u53EF\u4E34\u65F6\u4F7F\u7528 http://\u670D\u52A1\u5668IP:\u7AEF\u53E3 \u5F62\u5F0F\u7684\u56DE\u8C03\u5730\u5740\u3002"
|
|
10943
|
+
)
|
|
10944
|
+
);
|
|
10945
|
+
}
|
|
10946
|
+
function AppSettingsEditor({ bot, busy, onSave }) {
|
|
10947
|
+
const [apiBaseUrl, setApiBaseUrl] = React20.useState(bot.apiBaseUrl ?? "");
|
|
10948
|
+
const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState(bot.callbackBaseUrl ?? "");
|
|
10949
|
+
const [streamEnabled, setStreamEnabled] = React20.useState(bot.streamEnabled !== false);
|
|
10950
|
+
const [dirty, setDirty] = React20.useState(false);
|
|
10951
|
+
const formRef = React20.useRef(null);
|
|
10952
|
+
React20.useEffect(() => {
|
|
10953
|
+
setApiBaseUrl(bot.apiBaseUrl ?? "");
|
|
10954
|
+
setCallbackBaseUrl(bot.callbackBaseUrl ?? "");
|
|
10955
|
+
setStreamEnabled(bot.streamEnabled !== false);
|
|
10956
|
+
setDirty(false);
|
|
10957
|
+
}, [bot.apiBaseUrl, bot.callbackBaseUrl, bot.streamEnabled]);
|
|
10958
|
+
const touch = () => setDirty(true);
|
|
10959
|
+
const save = (event) => {
|
|
10960
|
+
event.preventDefault();
|
|
10961
|
+
if (!dirty || busy) return;
|
|
10962
|
+
void onSave({
|
|
10963
|
+
apiBaseUrl: apiBaseUrl.trim() || null,
|
|
10964
|
+
callbackBaseUrl: callbackBaseUrl.trim() || null,
|
|
10965
|
+
streamEnabled
|
|
10966
|
+
});
|
|
10967
|
+
setDirty(false);
|
|
10968
|
+
};
|
|
10969
|
+
return h2(
|
|
10970
|
+
"form",
|
|
10971
|
+
{ ref: formRef, className: "dim-appFieldGrid", onSubmit: save },
|
|
10972
|
+
h2(Field, { label: "\u4EE3\u7406\u5730\u5740\uFF08\u53EF\u9009\uFF09", value: apiBaseUrl, onChange: (value) => {
|
|
10973
|
+
setApiBaseUrl(value);
|
|
10974
|
+
touch();
|
|
10975
|
+
}, placeholder: "\u7559\u7A7A\u76F4\u8FDE qyapi.weixin.qq.com", busy }),
|
|
10976
|
+
h2(Field, { label: "\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF08\u53EF\u9009\uFF09", value: callbackBaseUrl, onChange: (value) => {
|
|
10977
|
+
setCallbackBaseUrl(value);
|
|
10978
|
+
touch();
|
|
10979
|
+
}, placeholder: "\u4F8B\u5982 https://im.example.com", busy }),
|
|
10980
|
+
h2(
|
|
10981
|
+
"div",
|
|
10982
|
+
{ className: "dim-appSwitchRow" },
|
|
10983
|
+
h2("button", {
|
|
10984
|
+
type: "button",
|
|
10985
|
+
className: "ddt-button dim-streamToggle",
|
|
10986
|
+
"aria-pressed": streamEnabled ? "true" : "false",
|
|
10987
|
+
onClick: () => {
|
|
10988
|
+
setStreamEnabled((value) => !value);
|
|
10989
|
+
touch();
|
|
10990
|
+
},
|
|
10991
|
+
disabled: busy
|
|
10992
|
+
}, streamEnabled ? "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00" : "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173")
|
|
10993
|
+
),
|
|
10994
|
+
h2(
|
|
10995
|
+
"div",
|
|
10996
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
10997
|
+
h2(Button12, { onClick: () => formRef.current?.requestSubmit(), disabled: busy || !dirty }, busy ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u8BBE\u7F6E")
|
|
10998
|
+
)
|
|
10999
|
+
);
|
|
11000
|
+
}
|
|
11001
|
+
function RemoveConfirmation5({ account, busy, onConfirm, onCancel }) {
|
|
11002
|
+
return h2(
|
|
11003
|
+
"div",
|
|
11004
|
+
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
11005
|
+
h2("strong", null, `\u4ECE DeepSeek Harness \u79FB\u9664\u201C${account.bot.name}\u201D\uFF1F`),
|
|
11006
|
+
h2("p", null, "\u8FD9\u4F1A\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684\u5E94\u7528\u51ED\u636E\u3001\u56DE\u8C03\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u7684\u5E94\u7528\u4E0D\u4F1A\u88AB\u5220\u9664\u3002"),
|
|
11007
|
+
h2(
|
|
11008
|
+
"div",
|
|
11009
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
11010
|
+
h2(Button12, { onClick: onCancel, disabled: busy }, "\u4FDD\u7559\u5E94\u7528"),
|
|
11011
|
+
h2(Button12, { kind: "danger", onClick: onConfirm, disabled: busy }, busy ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664\u63A5\u5165")
|
|
11012
|
+
)
|
|
11013
|
+
);
|
|
11014
|
+
}
|
|
11015
|
+
function AccountCard4({
|
|
11016
|
+
account,
|
|
11017
|
+
busy,
|
|
11018
|
+
feedback,
|
|
11019
|
+
removing,
|
|
11020
|
+
onReconnect,
|
|
11021
|
+
onSettingsSave,
|
|
11022
|
+
onSecretReset,
|
|
11023
|
+
onWorkspaceSave,
|
|
11024
|
+
onModelSave,
|
|
11025
|
+
onAgentPresetSave,
|
|
11026
|
+
onContextEnhancementSave,
|
|
11027
|
+
onRequestRemove,
|
|
11028
|
+
onConfirmRemove,
|
|
11029
|
+
onCancelRemove
|
|
11030
|
+
}) {
|
|
11031
|
+
const tone = account.connected ? "success" : account.state === "error" ? "error" : "warning";
|
|
11032
|
+
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : account.state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
11033
|
+
const summary2 = account.error?.message ?? (account.connected ? null : account.health.summary);
|
|
11034
|
+
const elementId = `wecomapp-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
11035
|
+
return h2(
|
|
11036
|
+
"article",
|
|
11037
|
+
{ className: "ddt-card dim-botCard", "data-bot-id": account.botId },
|
|
11038
|
+
h2(
|
|
11039
|
+
"div",
|
|
11040
|
+
{ className: "ddt-cardBody dim-botCardBody" },
|
|
11041
|
+
h2(
|
|
11042
|
+
CollapsibleAccountSection,
|
|
11043
|
+
{
|
|
11044
|
+
id: elementId,
|
|
11045
|
+
header: h2(
|
|
11046
|
+
"div",
|
|
11047
|
+
{ className: "ddt-accountTop dim-botCardTop" },
|
|
11048
|
+
h2(
|
|
11049
|
+
"div",
|
|
11050
|
+
{ className: "ddt-accountIdentity dim-botIdentity" },
|
|
11051
|
+
h2("div", { className: "ddt-avatar dim-botAvatar dwecomapp-avatar", "aria-hidden": "true" }, h2(WecomLogoGlyph, { size: 29 })),
|
|
11052
|
+
h2(
|
|
11053
|
+
"div",
|
|
11054
|
+
{ className: "dim-botName" },
|
|
11055
|
+
h2("h3", null, account.bot.name),
|
|
11056
|
+
h2("p", null, `${account.bot.corpIdMasked} \xB7 AgentId ${account.bot.agentId}`)
|
|
11057
|
+
)
|
|
11058
|
+
),
|
|
11059
|
+
h2(
|
|
11060
|
+
"div",
|
|
11061
|
+
{
|
|
11062
|
+
className: "dim-botCardTools",
|
|
11063
|
+
onClick: (event) => {
|
|
11064
|
+
event.stopPropagation();
|
|
11065
|
+
},
|
|
11066
|
+
onKeyDown: (event) => {
|
|
11067
|
+
if (event.key === "Enter" || event.key === " ") event.stopPropagation();
|
|
11068
|
+
}
|
|
11069
|
+
},
|
|
11070
|
+
h2(BotStatusMeta, {
|
|
11071
|
+
className: "ddt-health",
|
|
11072
|
+
dotClassName: "ddt-dot",
|
|
11073
|
+
tone,
|
|
11074
|
+
stateLabel: stateLabel2,
|
|
11075
|
+
lastCheckedAt: account.health.lastCheckedAt,
|
|
11076
|
+
formatCheckedTime: checkedTime5
|
|
11077
|
+
}),
|
|
11078
|
+
h2(BotSettingsButton, {
|
|
11079
|
+
channel: "wecomApp",
|
|
11080
|
+
botId: account.botId,
|
|
11081
|
+
botName: account.bot.name,
|
|
11082
|
+
connected: account.connected,
|
|
11083
|
+
accessPolicy: account.accessPolicy
|
|
11084
|
+
})
|
|
11085
|
+
)
|
|
11086
|
+
)
|
|
11087
|
+
},
|
|
11088
|
+
h2(CallbackUrlBox, {
|
|
11089
|
+
url: account.bot.callbackUrl,
|
|
11090
|
+
busy: Boolean(busy),
|
|
11091
|
+
resetBusy: busy === "reset",
|
|
11092
|
+
onReset: onSecretReset
|
|
11093
|
+
}),
|
|
11094
|
+
h2(AppSettingsEditor, {
|
|
11095
|
+
bot: account.bot,
|
|
11096
|
+
busy: Boolean(busy),
|
|
11097
|
+
onSave: onSettingsSave
|
|
11098
|
+
}),
|
|
11099
|
+
h2(WorkspaceEditor, {
|
|
11100
|
+
workspace: account.workspace,
|
|
11101
|
+
disabled: Boolean(busy),
|
|
11102
|
+
onSave: onWorkspaceSave
|
|
11103
|
+
}),
|
|
11104
|
+
h2(ModelEditor, {
|
|
11105
|
+
model: account.model,
|
|
11106
|
+
disabled: Boolean(busy),
|
|
11107
|
+
onSave: onModelSave
|
|
11108
|
+
}),
|
|
11109
|
+
h2(AgentPresetEditor, {
|
|
11110
|
+
agentPreset: account.agentPreset,
|
|
11111
|
+
disabled: Boolean(busy),
|
|
11112
|
+
onSave: onAgentPresetSave
|
|
11113
|
+
}),
|
|
11114
|
+
h2(ContextEnhancementEditor, {
|
|
11115
|
+
config: account.contextEnhancement,
|
|
11116
|
+
disabled: Boolean(busy),
|
|
11117
|
+
onSave: onContextEnhancementSave
|
|
11118
|
+
}),
|
|
11119
|
+
h2(
|
|
11120
|
+
"div",
|
|
11121
|
+
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
11122
|
+
h2(
|
|
11123
|
+
"div",
|
|
11124
|
+
{ className: "dim-cardFooterLayout" },
|
|
11125
|
+
h2(
|
|
11126
|
+
"div",
|
|
11127
|
+
{ className: "ddt-actions dim-cardActions" },
|
|
11128
|
+
h2(Button12, { className: "dim-cardAction", onClick: onReconnect, disabled: Boolean(busy) }, busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
|
|
11129
|
+
h2(Button12, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
|
|
11130
|
+
),
|
|
11131
|
+
summary2 ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary2) : null,
|
|
11132
|
+
account.lastMessageError ? h2(LastMessageErrorSummary, {
|
|
11133
|
+
className: "ddt-summary",
|
|
11134
|
+
error: account.lastMessageError
|
|
11135
|
+
}) : null,
|
|
11136
|
+
feedback ? h2("div", {
|
|
11137
|
+
className: "ddt-summary dim-cardFeedback",
|
|
11138
|
+
role: "status",
|
|
11139
|
+
"aria-live": "polite"
|
|
11140
|
+
}, feedback) : null
|
|
11141
|
+
)
|
|
11142
|
+
)
|
|
11143
|
+
)
|
|
11144
|
+
),
|
|
11145
|
+
removing ? h2(RemoveConfirmation5, {
|
|
11146
|
+
account,
|
|
11147
|
+
busy: busy === "delete",
|
|
11148
|
+
onConfirm: onConfirmRemove,
|
|
11149
|
+
onCancel: onCancelRemove
|
|
11150
|
+
}) : null
|
|
11151
|
+
);
|
|
11152
|
+
}
|
|
11153
|
+
function WecomAppSettingsTab({ rpcCall }) {
|
|
11154
|
+
const [model, setModel] = React20.useState({
|
|
11155
|
+
phase: "loading",
|
|
11156
|
+
bots: [],
|
|
11157
|
+
totals: { configured: 0, connected: 0 },
|
|
11158
|
+
error: null,
|
|
11159
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
11160
|
+
modelCatalog: EMPTY_MODEL_CATALOG
|
|
11161
|
+
});
|
|
11162
|
+
const [bindOpen, setBindOpen] = React20.useState(false);
|
|
11163
|
+
const [bindError, setBindError] = React20.useState(null);
|
|
11164
|
+
const [busy, setBusy] = React20.useState(false);
|
|
11165
|
+
const [busyByBot, setBusyByBot] = React20.useState({});
|
|
11166
|
+
const [feedbackByBot, setFeedbackByBot] = React20.useState({});
|
|
11167
|
+
const [removeTarget, setRemoveTarget] = React20.useState(null);
|
|
11168
|
+
const [notice, setNotice] = React20.useState("");
|
|
11169
|
+
const mounted = React20.useRef(true);
|
|
11170
|
+
const workspaceFence = useWorkspaceSnapshotFence();
|
|
11171
|
+
const addButtonRef = React20.useRef(null);
|
|
11172
|
+
const noticeFrameRef = React20.useRef(null);
|
|
11173
|
+
const announce = React20.useCallback((message) => {
|
|
11174
|
+
if (!mounted.current) return;
|
|
11175
|
+
if (noticeFrameRef.current !== null) {
|
|
11176
|
+
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
11177
|
+
noticeFrameRef.current = null;
|
|
11178
|
+
}
|
|
11179
|
+
setNotice("");
|
|
11180
|
+
if (message) {
|
|
11181
|
+
noticeFrameRef.current = window.requestAnimationFrame(() => {
|
|
11182
|
+
noticeFrameRef.current = null;
|
|
11183
|
+
if (mounted.current) setNotice(message);
|
|
11184
|
+
});
|
|
11185
|
+
}
|
|
11186
|
+
}, []);
|
|
11187
|
+
React20.useEffect(() => {
|
|
11188
|
+
const disposeDingtalk = installDingtalkStyles();
|
|
11189
|
+
const disposeWecomApp = installWecomAppStyles();
|
|
11190
|
+
mounted.current = true;
|
|
11191
|
+
return () => {
|
|
11192
|
+
mounted.current = false;
|
|
11193
|
+
if (noticeFrameRef.current !== null) {
|
|
11194
|
+
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
11195
|
+
noticeFrameRef.current = null;
|
|
11196
|
+
}
|
|
11197
|
+
disposeWecomApp();
|
|
11198
|
+
disposeDingtalk();
|
|
11199
|
+
};
|
|
11200
|
+
}, []);
|
|
11201
|
+
const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
|
|
11202
|
+
if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
11203
|
+
return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
|
|
11204
|
+
}, [rpcCall]);
|
|
11205
|
+
const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
11206
|
+
const workspaceVersion = workspaceFence.beginStatus();
|
|
11207
|
+
if (workspaceVersion === null) return void 0;
|
|
11208
|
+
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
11209
|
+
try {
|
|
11210
|
+
const snapshot = normalizeSnapshot7(await invoke(WECOM_APP_ENDPOINTS.status, {}, signal));
|
|
11211
|
+
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
11212
|
+
setModel({
|
|
11213
|
+
phase: "ready",
|
|
11214
|
+
bots: snapshot.bots,
|
|
11215
|
+
totals: snapshot.totals,
|
|
11216
|
+
error: null,
|
|
11217
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11218
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11219
|
+
});
|
|
11220
|
+
if (restore && snapshot.bots.length > 0) setBindOpen(false);
|
|
11221
|
+
return snapshot;
|
|
11222
|
+
} catch (error) {
|
|
11223
|
+
if (error?.name !== "AbortError" && mounted.current && !signal?.aborted && workspaceFence.canCommitStatus(workspaceVersion)) {
|
|
11224
|
+
setModel((current) => ({ ...current, phase: silent ? current.phase : "error", error: presentError8(error) }));
|
|
11225
|
+
}
|
|
11226
|
+
return void 0;
|
|
11227
|
+
}
|
|
11228
|
+
}, [invoke, workspaceFence]);
|
|
11229
|
+
React20.useEffect(() => {
|
|
11230
|
+
const controller = new AbortController();
|
|
11231
|
+
void loadStatus({ signal: controller.signal, restore: true });
|
|
11232
|
+
return () => controller.abort();
|
|
11233
|
+
}, [loadStatus]);
|
|
11234
|
+
React20.useEffect(() => {
|
|
11235
|
+
if (model.phase !== "ready") return void 0;
|
|
11236
|
+
const controller = new AbortController();
|
|
11237
|
+
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
11238
|
+
return () => {
|
|
11239
|
+
controller.abort();
|
|
11240
|
+
window.clearInterval(timer);
|
|
11241
|
+
};
|
|
11242
|
+
}, [loadStatus, model.phase]);
|
|
11243
|
+
const bindApp = React20.useCallback(async (payload) => {
|
|
11244
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
11245
|
+
setBusy(true);
|
|
11246
|
+
setBindError(null);
|
|
11247
|
+
try {
|
|
11248
|
+
const snapshot = normalizeSnapshot7(await invoke(WECOM_APP_ENDPOINTS.bindApp, payload));
|
|
11249
|
+
if (!mounted.current) return;
|
|
11250
|
+
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
11251
|
+
setModel({
|
|
11252
|
+
phase: "ready",
|
|
11253
|
+
bots: snapshot.bots,
|
|
11254
|
+
totals: snapshot.totals,
|
|
11255
|
+
error: null,
|
|
11256
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11257
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11258
|
+
});
|
|
11259
|
+
}
|
|
11260
|
+
setBindOpen(false);
|
|
11261
|
+
announce("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u5DF2\u7ED1\u5B9A\u3002\u8BF7\u628A\u56DE\u8C03 URL \u586B\u5165\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u5E76\u4FDD\u5B58\u3002");
|
|
11262
|
+
} catch (error) {
|
|
11263
|
+
if (mounted.current) setBindError(presentError8(error));
|
|
11264
|
+
} finally {
|
|
11265
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
11266
|
+
if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
|
|
11267
|
+
if (mounted.current) setBusy(false);
|
|
11268
|
+
}
|
|
11269
|
+
}, [announce, invoke, loadStatus, workspaceFence]);
|
|
11270
|
+
const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
|
|
11271
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
11272
|
+
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
11273
|
+
try {
|
|
11274
|
+
const snapshot = normalizeSnapshot7(await invoke(endpoint, payload));
|
|
11275
|
+
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
11276
|
+
setModel({
|
|
11277
|
+
phase: "ready",
|
|
11278
|
+
bots: snapshot.bots,
|
|
11279
|
+
totals: snapshot.totals,
|
|
11280
|
+
error: null,
|
|
11281
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11282
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11283
|
+
});
|
|
11284
|
+
}
|
|
11285
|
+
return snapshot;
|
|
11286
|
+
} finally {
|
|
11287
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
11288
|
+
if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
|
|
11289
|
+
if (mounted.current) setBusyByBot((current) => {
|
|
11290
|
+
const next = { ...current };
|
|
11291
|
+
delete next[account.botId];
|
|
11292
|
+
return next;
|
|
11293
|
+
});
|
|
11294
|
+
}
|
|
11295
|
+
}, [invoke, loadStatus, workspaceFence]);
|
|
11296
|
+
const reconnect = React20.useCallback(async (account) => {
|
|
11297
|
+
setFeedbackByBot((current) => {
|
|
11298
|
+
const next = { ...current };
|
|
11299
|
+
delete next[account.botId];
|
|
11300
|
+
return next;
|
|
11301
|
+
});
|
|
11302
|
+
try {
|
|
11303
|
+
const snapshot = await botAction(
|
|
11304
|
+
account,
|
|
11305
|
+
"reconnect",
|
|
11306
|
+
WECOM_APP_ENDPOINTS.reconnectBot,
|
|
11307
|
+
{ botId: account.botId, sendTest: true }
|
|
11308
|
+
);
|
|
11309
|
+
if (!snapshot) return;
|
|
11310
|
+
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
11311
|
+
let feedback;
|
|
11312
|
+
if (!refreshed?.connected) {
|
|
11313
|
+
feedback = "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u4ECD\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5\u3002";
|
|
11314
|
+
} else if (snapshot.testMessage?.sent) {
|
|
11315
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002";
|
|
11316
|
+
} else if (snapshot.testMessage?.code === "test-target-unavailable") {
|
|
11317
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u5E94\u7528\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002";
|
|
11318
|
+
} else if (snapshot.testMessage) {
|
|
11319
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002";
|
|
11320
|
+
} else {
|
|
11321
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
|
|
11322
|
+
}
|
|
11323
|
+
if (mounted.current) {
|
|
11324
|
+
setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
|
|
11325
|
+
}
|
|
11326
|
+
announce(feedback);
|
|
11327
|
+
} catch {
|
|
11328
|
+
const feedback = "\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
11329
|
+
if (mounted.current) {
|
|
11330
|
+
setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
|
|
11331
|
+
}
|
|
11332
|
+
announce(feedback);
|
|
11333
|
+
}
|
|
11334
|
+
}, [announce, botAction]);
|
|
11335
|
+
const botList = model.bots.length > 0 ? h2(
|
|
11336
|
+
"section",
|
|
11337
|
+
{ className: "dim-listSection" },
|
|
11338
|
+
h2(ChannelListHeading, {
|
|
11339
|
+
className: "ddt-listHeading",
|
|
11340
|
+
title: "\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528",
|
|
11341
|
+
connectionLabel: "HTTP \u56DE\u8C03\u901A\u9053"
|
|
11342
|
+
}),
|
|
11343
|
+
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard4, {
|
|
11344
|
+
account,
|
|
11345
|
+
busy: busyByBot[account.botId],
|
|
11346
|
+
feedback: feedbackByBot[account.botId],
|
|
11347
|
+
removing: removeTarget === account.botId,
|
|
11348
|
+
onReconnect: () => void reconnect(account),
|
|
11349
|
+
onSettingsSave: (settings) => botAction(
|
|
11350
|
+
account,
|
|
11351
|
+
"settings",
|
|
11352
|
+
WECOM_APP_ENDPOINTS.updateSettings,
|
|
11353
|
+
{ botId: account.botId, ...settings }
|
|
11354
|
+
),
|
|
11355
|
+
onSecretReset: async () => {
|
|
11356
|
+
try {
|
|
11357
|
+
await botAction(account, "reset", WECOM_APP_ENDPOINTS.resetCallbackSecret, { botId: account.botId });
|
|
11358
|
+
announce("\u56DE\u8C03\u5BC6\u94A5\u5DF2\u91CD\u7F6E\uFF0C\u8BF7\u628A\u65B0\u7684\u56DE\u8C03 URL \u66F4\u65B0\u5230\u4F01\u4E1A\u5FAE\u4FE1\u540E\u53F0\u3002");
|
|
11359
|
+
} catch {
|
|
11360
|
+
announce("\u56DE\u8C03\u5BC6\u94A5\u91CD\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
11361
|
+
}
|
|
11362
|
+
},
|
|
11363
|
+
onWorkspaceSave: (workspace) => botAction(
|
|
11364
|
+
account,
|
|
11365
|
+
"workspace",
|
|
11366
|
+
WECOM_APP_ENDPOINTS.setWorkspace,
|
|
11367
|
+
{ botId: account.botId, workspace }
|
|
11368
|
+
),
|
|
11369
|
+
onModelSave: (selectedModel) => botAction(
|
|
11370
|
+
account,
|
|
11371
|
+
"model",
|
|
11372
|
+
WECOM_APP_ENDPOINTS.setModel,
|
|
11373
|
+
{ botId: account.botId, model: selectedModel }
|
|
11374
|
+
),
|
|
11375
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
11376
|
+
account,
|
|
11377
|
+
"preset",
|
|
11378
|
+
WECOM_APP_ENDPOINTS.setAgentPreset,
|
|
11379
|
+
{ botId: account.botId, agentPreset }
|
|
11380
|
+
),
|
|
11381
|
+
onContextEnhancementSave: (config) => botAction(
|
|
11382
|
+
account,
|
|
11383
|
+
"context-enhancement",
|
|
11384
|
+
WECOM_APP_ENDPOINTS.setContextEnhancement,
|
|
11385
|
+
{ botId: account.botId, config }
|
|
11386
|
+
),
|
|
11387
|
+
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
11388
|
+
onCancelRemove: () => setRemoveTarget(null),
|
|
11389
|
+
onConfirmRemove: async () => {
|
|
11390
|
+
await botAction(account, "delete", WECOM_APP_ENDPOINTS.deleteBot, { botId: account.botId, confirm: true });
|
|
11391
|
+
if (mounted.current) setRemoveTarget(null);
|
|
11392
|
+
}
|
|
11393
|
+
}))))
|
|
11394
|
+
) : null;
|
|
11395
|
+
const bindView = bindOpen ? h2(BindForm, {
|
|
11396
|
+
busy,
|
|
11397
|
+
error: bindError,
|
|
11398
|
+
onSubmit: bindApp,
|
|
11399
|
+
onCancel: () => {
|
|
11400
|
+
setBindOpen(false);
|
|
11401
|
+
setBindError(null);
|
|
11402
|
+
}
|
|
11403
|
+
}) : null;
|
|
11404
|
+
return h2(ModelCatalogContext.Provider, {
|
|
11405
|
+
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11406
|
+
}, h2(AgentPresetCatalogContext.Provider, {
|
|
11407
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
11408
|
+
}, h2(
|
|
11409
|
+
"section",
|
|
11410
|
+
{ className: "ddt-page dwecomapp-page dim-channelPage", "aria-label": "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E" },
|
|
11411
|
+
h2(Heading5, {
|
|
11412
|
+
totals: model.totals,
|
|
11413
|
+
adding: bindOpen,
|
|
11414
|
+
busy,
|
|
11415
|
+
onAdd: () => {
|
|
11416
|
+
setBindOpen((value) => !value);
|
|
11417
|
+
setBindError(null);
|
|
11418
|
+
},
|
|
11419
|
+
addButtonRef
|
|
11420
|
+
}),
|
|
11421
|
+
h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
11422
|
+
model.phase === "loading" ? h2(LoadingView5) : model.phase === "error" ? h2("div", { className: "ddt-card dim-surfaceCard" }, h2("div", { className: "ddt-inlineError dim-inlineError" }, h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button12, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
|
|
11423
|
+
React20.Fragment,
|
|
11424
|
+
null,
|
|
11425
|
+
bindView,
|
|
11426
|
+
model.bots.length === 0 && !bindOpen ? h2(EmptyView5, { busy, onStart: () => setBindOpen(true) }) : null,
|
|
11427
|
+
botList
|
|
11428
|
+
)
|
|
11429
|
+
)));
|
|
11430
|
+
}
|
|
11431
|
+
|
|
11432
|
+
// plugin-src/client/channels/weixin/index.js
|
|
11433
|
+
var React21 = __toESM(require("react"), 1);
|
|
11434
|
+
|
|
11435
|
+
// plugin-src/client/channels/weixin/api.js
|
|
11436
|
+
var WEIXIN_RPC_CHANNEL = "/weixin";
|
|
11437
|
+
var WEIXIN_ENDPOINTS = Object.freeze({
|
|
11438
|
+
status: "connection.status",
|
|
11439
|
+
beginProvisioning: "provision.begin",
|
|
11440
|
+
pollProvisioning: "provision.poll",
|
|
11441
|
+
submitVerification: "provision.verify",
|
|
11442
|
+
cancelProvisioning: "provision.cancel",
|
|
11443
|
+
reconnectBot: "bot.reconnect",
|
|
11444
|
+
deleteBot: "bot.delete",
|
|
11445
|
+
setWorkspace: "bot.workspace.set",
|
|
11446
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
11447
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
11448
|
+
setContextEnhancement: "bot.context-enhancement.set",
|
|
11449
|
+
setAccessPolicy: "bot.access-policy.set"
|
|
11450
|
+
});
|
|
11451
|
+
var ACCOUNT_STATES6 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
11452
|
+
var PROVISION_STATES4 = /* @__PURE__ */ new Set([
|
|
11453
|
+
"starting",
|
|
11454
|
+
"pending",
|
|
11455
|
+
"scanned",
|
|
11456
|
+
"needs_verification",
|
|
11457
|
+
"connecting",
|
|
11458
|
+
"connected",
|
|
11459
|
+
"expired",
|
|
11460
|
+
"failed",
|
|
11461
|
+
"cancelled"
|
|
11462
|
+
]);
|
|
11463
|
+
function isRecord7(value) {
|
|
11464
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11465
|
+
}
|
|
11466
|
+
function string(value, fallback = "") {
|
|
11467
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
11468
|
+
}
|
|
11469
|
+
function timestamp6(value) {
|
|
11470
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
11471
|
+
}
|
|
11472
|
+
function normalizeTestMessage5(value) {
|
|
11473
|
+
if (!isRecord7(value)) return null;
|
|
11474
|
+
if (value.sent === true) return { sent: true };
|
|
11475
|
+
if (value.sent !== false) return null;
|
|
11476
|
+
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
11477
|
+
return { sent: false, code };
|
|
11478
|
+
}
|
|
11479
|
+
function unwrapRpcResult9(result) {
|
|
11480
|
+
if (!isRecord7(result) || typeof result.ok !== "boolean") {
|
|
11481
|
+
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
11482
|
+
}
|
|
11483
|
+
if (!result.ok) {
|
|
11484
|
+
const error = new Error(string(result.error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25"));
|
|
11485
|
+
error.code = string(result.error?.code, "WEIXIN_RPC_ERROR");
|
|
11486
|
+
throw error;
|
|
11487
|
+
}
|
|
11488
|
+
return result.value;
|
|
11489
|
+
}
|
|
11490
|
+
function safeQrSource5(value) {
|
|
11491
|
+
return typeof value === "string" && /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
|
|
11492
|
+
}
|
|
11493
|
+
function safeVerificationUrl(value) {
|
|
11494
|
+
if (typeof value !== "string") return void 0;
|
|
11495
|
+
try {
|
|
11496
|
+
const url = new URL(value);
|
|
11497
|
+
const host = url.hostname.toLowerCase();
|
|
11498
|
+
return url.protocol === "https:" && (host === "weixin.qq.com" || host.endsWith(".weixin.qq.com") || host === "wechat.com" || host.endsWith(".wechat.com")) ? url.toString() : void 0;
|
|
11499
|
+
} catch {
|
|
11500
|
+
return void 0;
|
|
11501
|
+
}
|
|
11502
|
+
}
|
|
11503
|
+
function normalizeProvisioning5(value) {
|
|
11504
|
+
if (!isRecord7(value) || !string(value.attemptId)) {
|
|
11505
|
+
throw new Error("\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
11506
|
+
}
|
|
11507
|
+
const status = PROVISION_STATES4.has(value.status) ? value.status : "failed";
|
|
11508
|
+
const result = {
|
|
11509
|
+
attemptId: string(value.attemptId),
|
|
11510
|
+
status,
|
|
11511
|
+
expiresAt: timestamp6(value.expiresAt) ?? Date.now(),
|
|
11512
|
+
pollIntervalMs: Math.min(5e3, Math.max(500, Number(value.pollIntervalMs) || 1e3)),
|
|
11513
|
+
verificationRequired: value.verificationRequired === true || status === "needs_verification"
|
|
11514
|
+
};
|
|
11515
|
+
const verificationUrl = safeVerificationUrl(value.verificationUrl);
|
|
11516
|
+
const qrCodeDataUrl = safeQrSource5(value.qrCodeDataUrl);
|
|
11517
|
+
if (verificationUrl) result.verificationUrl = verificationUrl;
|
|
11518
|
+
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
11519
|
+
if (string(value.botId)) result.botId = string(value.botId);
|
|
11520
|
+
if (value.alreadyConnected === true) result.alreadyConnected = true;
|
|
11521
|
+
if (isRecord7(value.error)) {
|
|
11522
|
+
result.error = {
|
|
11523
|
+
code: string(value.error.code, "WEIXIN_PROVISION_FAILED"),
|
|
11524
|
+
message: string(value.error.message, "\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210")
|
|
11525
|
+
};
|
|
11526
|
+
}
|
|
11527
|
+
return result;
|
|
11528
|
+
}
|
|
11529
|
+
function normalizeBot6(value) {
|
|
11530
|
+
if (!isRecord7(value) || !string(value.botId) || !isRecord7(value.bot)) return null;
|
|
11531
|
+
const state = ACCOUNT_STATES6.has(value.state) ? value.state : "error";
|
|
11532
|
+
const connected = value.connected === true;
|
|
11533
|
+
return {
|
|
11534
|
+
botId: string(value.botId),
|
|
11535
|
+
state: connected ? "connected" : state,
|
|
11536
|
+
connected,
|
|
11537
|
+
configured: value.configured === true,
|
|
11538
|
+
workspace: string(value.workspace).slice(0, 4096),
|
|
11539
|
+
model: normalizeModelSelection(value.model),
|
|
11540
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
11541
|
+
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
11542
|
+
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
11543
|
+
bot: {
|
|
11544
|
+
name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
|
|
11545
|
+
accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
|
|
11546
|
+
},
|
|
11547
|
+
health: {
|
|
11548
|
+
status: string(value.health?.status, connected ? "healthy" : "offline"),
|
|
11549
|
+
summary: string(value.health?.summary, connected ? "\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38" : "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA"),
|
|
11550
|
+
lastCheckedAt: timestamp6(value.health?.lastCheckedAt)
|
|
11551
|
+
},
|
|
11552
|
+
stats: {
|
|
11553
|
+
messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
|
|
11554
|
+
messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
|
|
11555
|
+
},
|
|
11556
|
+
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
11557
|
+
error: isRecord7(value.error) ? {
|
|
11558
|
+
code: string(value.error.code, "WEIXIN_ACCOUNT_ERROR"),
|
|
11559
|
+
message: string(value.error.message, "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA")
|
|
11560
|
+
} : null
|
|
11561
|
+
};
|
|
11562
|
+
}
|
|
11563
|
+
function normalizeSnapshot8(value) {
|
|
11564
|
+
if (!isRecord7(value) || !Array.isArray(value.bots)) {
|
|
11565
|
+
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868");
|
|
11566
|
+
}
|
|
11567
|
+
const bots = value.bots.map(normalizeBot6).filter(Boolean);
|
|
11568
|
+
return {
|
|
11569
|
+
schemaVersion: Number(value.schemaVersion) || 1,
|
|
11570
|
+
revision: Number(value.revision) || 0,
|
|
11571
|
+
state: string(value.state, "offline"),
|
|
11572
|
+
bots,
|
|
11573
|
+
totals: {
|
|
11574
|
+
configured: bots.length,
|
|
11575
|
+
connected: bots.filter((bot) => bot.connected).length
|
|
11576
|
+
},
|
|
11577
|
+
provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
|
|
11578
|
+
testMessage: normalizeTestMessage5(value.testMessage),
|
|
11579
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
|
11580
|
+
modelCatalog: normalizeModelCatalog(value.modelCatalog)
|
|
11581
|
+
};
|
|
11582
|
+
}
|
|
11583
|
+
function presentError9(error) {
|
|
11584
|
+
return {
|
|
11585
|
+
code: string(error?.code, "WEIXIN_ERROR"),
|
|
11586
|
+
message: string(error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
11587
|
+
};
|
|
11588
|
+
}
|
|
11589
|
+
function formatRemaining5(milliseconds) {
|
|
11590
|
+
const seconds = Math.max(0, Math.ceil(milliseconds / 1e3));
|
|
11591
|
+
return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
|
|
11592
|
+
}
|
|
11593
|
+
|
|
11594
|
+
// plugin-src/client/channels/weixin/index.js
|
|
11595
|
+
var Button14 = React21.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
11596
|
+
return h2("button", {
|
|
11597
|
+
...props,
|
|
11598
|
+
ref,
|
|
11599
|
+
type: "button",
|
|
11600
|
+
className: `dxw-button ${className}`.trim(),
|
|
11601
|
+
"data-kind": kind
|
|
11602
|
+
}, children);
|
|
11603
|
+
});
|
|
11604
|
+
function Heading6({ totals, adding, busy, onAdd, addButtonRef }) {
|
|
11605
|
+
return h2(
|
|
11606
|
+
"div",
|
|
11607
|
+
{ className: "dxw-heading" },
|
|
11608
|
+
h2(
|
|
11609
|
+
"div",
|
|
11610
|
+
{ className: "dxw-tools" },
|
|
11611
|
+
h2(Button14, {
|
|
11612
|
+
kind: "primary",
|
|
11613
|
+
className: "dim-scanButton",
|
|
11614
|
+
onClick: onAdd,
|
|
11615
|
+
disabled: adding || busy,
|
|
11616
|
+
ref: addButtonRef,
|
|
11617
|
+
"aria-label": "\u626B\u7801\u63A5\u5165\u5FAE\u4FE1\u673A\u5668\u4EBA"
|
|
11618
|
+
}, h2(QrActionIcon), adding ? "\u6B63\u5728\u63A5\u5165" : "\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA"),
|
|
11619
|
+
totals.configured > 0 ? h2(
|
|
11620
|
+
"div",
|
|
10545
11621
|
{ className: "dxw-badge dim-onlineBadge" },
|
|
10546
11622
|
h2("span", null, `${totals.connected} / ${totals.configured} \u5728\u7EBF`)
|
|
10547
11623
|
) : null
|
|
10548
11624
|
)
|
|
10549
11625
|
);
|
|
10550
11626
|
}
|
|
10551
|
-
function
|
|
11627
|
+
function LoadingView6() {
|
|
10552
11628
|
return h2(
|
|
10553
11629
|
"div",
|
|
10554
11630
|
{ className: "dxw-card dxw-loading dim-surfaceCard dim-loadingView", "aria-busy": "true" },
|
|
@@ -10556,7 +11632,7 @@ function LoadingView5() {
|
|
|
10556
11632
|
h2("span", null, "\u6B63\u5728\u8BFB\u53D6\u5FAE\u4FE1\u8FDE\u63A5\u72B6\u6001\u2026")
|
|
10557
11633
|
);
|
|
10558
11634
|
}
|
|
10559
|
-
function
|
|
11635
|
+
function EmptyView6({ onStart, busy }) {
|
|
10560
11636
|
return h2(
|
|
10561
11637
|
"div",
|
|
10562
11638
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10578,7 +11654,7 @@ function EmptyView5({ onStart, busy }) {
|
|
|
10578
11654
|
"div",
|
|
10579
11655
|
{ className: "dxw-actions dim-viewActions" },
|
|
10580
11656
|
h2(
|
|
10581
|
-
|
|
11657
|
+
Button14,
|
|
10582
11658
|
{ kind: "primary", onClick: onStart, disabled: busy },
|
|
10583
11659
|
busy ? "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" : "\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801"
|
|
10584
11660
|
)
|
|
@@ -10589,14 +11665,14 @@ function EmptyView5({ onStart, busy }) {
|
|
|
10589
11665
|
);
|
|
10590
11666
|
}
|
|
10591
11667
|
function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
10592
|
-
const [imageFailed, setImageFailed] =
|
|
11668
|
+
const [imageFailed, setImageFailed] = React21.useState(false);
|
|
10593
11669
|
const source = safeQrSource5(provision.qrCodeDataUrl);
|
|
10594
11670
|
const href = safeVerificationUrl(provision.verificationUrl);
|
|
10595
11671
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
10596
11672
|
const expired = remaining === 0 || provision.status === "expired";
|
|
10597
11673
|
const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
|
|
10598
11674
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
10599
|
-
|
|
11675
|
+
React21.useEffect(() => setImageFailed(false), [source]);
|
|
10600
11676
|
return h2(
|
|
10601
11677
|
"div",
|
|
10602
11678
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10648,24 +11724,24 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
10648
11724
|
h2(
|
|
10649
11725
|
"div",
|
|
10650
11726
|
{ className: "dxw-actions dim-viewActions" },
|
|
10651
|
-
expired ? h2(
|
|
11727
|
+
expired ? h2(Button14, { kind: "primary", onClick: onRefresh, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801") : null,
|
|
10652
11728
|
href ? h2("a", {
|
|
10653
11729
|
className: "dxw-button",
|
|
10654
11730
|
href,
|
|
10655
11731
|
target: "_blank",
|
|
10656
11732
|
rel: "noopener noreferrer"
|
|
10657
11733
|
}, "\u6253\u5F00\u5907\u7528\u94FE\u63A5") : null,
|
|
10658
|
-
!expired ? h2(
|
|
10659
|
-
h2(
|
|
11734
|
+
!expired ? h2(Button14, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
|
|
11735
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10660
11736
|
)
|
|
10661
11737
|
)
|
|
10662
11738
|
)
|
|
10663
11739
|
);
|
|
10664
11740
|
}
|
|
10665
11741
|
function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
10666
|
-
const [code, setCode] =
|
|
11742
|
+
const [code, setCode] = React21.useState("");
|
|
10667
11743
|
const valid = /^\d{4,8}$/.test(code);
|
|
10668
|
-
|
|
11744
|
+
React21.useEffect(() => setCode(""), [provision.attemptId]);
|
|
10669
11745
|
return h2(
|
|
10670
11746
|
"div",
|
|
10671
11747
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10706,7 +11782,7 @@ function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
|
10706
11782
|
disabled: !valid || busy
|
|
10707
11783
|
}, busy ? "\u6B63\u5728\u9A8C\u8BC1\u2026" : "\u7EE7\u7EED\u8FDE\u63A5")
|
|
10708
11784
|
),
|
|
10709
|
-
h2(
|
|
11785
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88\u7ED1\u5B9A")
|
|
10710
11786
|
)
|
|
10711
11787
|
);
|
|
10712
11788
|
}
|
|
@@ -10720,7 +11796,7 @@ function ProgressPanel2({ scanned, onCancel, busy }) {
|
|
|
10720
11796
|
onCancel ? h2(
|
|
10721
11797
|
"div",
|
|
10722
11798
|
{ className: "dxw-actions dim-viewActions", style: { justifyContent: "center", marginTop: 14 } },
|
|
10723
|
-
h2(
|
|
11799
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10724
11800
|
) : null
|
|
10725
11801
|
);
|
|
10726
11802
|
}
|
|
@@ -10738,25 +11814,25 @@ function ProvisionError3({ provision, busy, onRetry, onClose }) {
|
|
|
10738
11814
|
h2(
|
|
10739
11815
|
"div",
|
|
10740
11816
|
{ className: "dxw-actions dim-viewActions" },
|
|
10741
|
-
h2(
|
|
10742
|
-
h2(
|
|
11817
|
+
h2(Button14, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
11818
|
+
h2(Button14, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
|
|
10743
11819
|
)
|
|
10744
11820
|
)
|
|
10745
11821
|
);
|
|
10746
11822
|
}
|
|
10747
|
-
function
|
|
10748
|
-
if (!
|
|
11823
|
+
function checkedTime6(timestamp8) {
|
|
11824
|
+
if (!timestamp8) return "\u5C1A\u672A\u68C0\u67E5";
|
|
10749
11825
|
try {
|
|
10750
11826
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
10751
11827
|
hour: "2-digit",
|
|
10752
11828
|
minute: "2-digit",
|
|
10753
11829
|
second: "2-digit"
|
|
10754
|
-
}).format(new Date(
|
|
11830
|
+
}).format(new Date(timestamp8));
|
|
10755
11831
|
} catch {
|
|
10756
11832
|
return "\u521A\u521A";
|
|
10757
11833
|
}
|
|
10758
11834
|
}
|
|
10759
|
-
function
|
|
11835
|
+
function AccountCard5({
|
|
10760
11836
|
account,
|
|
10761
11837
|
busy,
|
|
10762
11838
|
feedback,
|
|
@@ -10810,7 +11886,7 @@ function AccountCard4({
|
|
|
10810
11886
|
tone,
|
|
10811
11887
|
stateLabel: account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA",
|
|
10812
11888
|
lastCheckedAt: account.health.lastCheckedAt,
|
|
10813
|
-
formatCheckedTime:
|
|
11889
|
+
formatCheckedTime: checkedTime6
|
|
10814
11890
|
}),
|
|
10815
11891
|
h2(BotSettingsButton, {
|
|
10816
11892
|
channel: "weixin",
|
|
@@ -10853,11 +11929,11 @@ function AccountCard4({
|
|
|
10853
11929
|
"div",
|
|
10854
11930
|
{ className: "dxw-actions dim-cardActions" },
|
|
10855
11931
|
h2(
|
|
10856
|
-
|
|
11932
|
+
Button14,
|
|
10857
11933
|
{ className: "dim-cardAction", onClick: onReconnect, disabled: Boolean(busy) },
|
|
10858
11934
|
busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"
|
|
10859
11935
|
),
|
|
10860
|
-
h2(
|
|
11936
|
+
h2(Button14, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
|
|
10861
11937
|
),
|
|
10862
11938
|
summary2 ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary2) : null,
|
|
10863
11939
|
account.lastMessageError ? h2(LastMessageErrorSummary, {
|
|
@@ -10881,9 +11957,9 @@ function AccountCard4({
|
|
|
10881
11957
|
h2(
|
|
10882
11958
|
"div",
|
|
10883
11959
|
{ className: "dxw-actions dim-viewActions" },
|
|
10884
|
-
h2(
|
|
11960
|
+
h2(Button14, { onClick: onCancelRemove, disabled: busy === "delete" }, "\u4FDD\u7559\u8D26\u53F7"),
|
|
10885
11961
|
h2(
|
|
10886
|
-
|
|
11962
|
+
Button14,
|
|
10887
11963
|
{ kind: "danger", onClick: onConfirmRemove, disabled: busy === "delete" },
|
|
10888
11964
|
busy === "delete" ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664"
|
|
10889
11965
|
)
|
|
@@ -10903,7 +11979,7 @@ function AccountList2(props) {
|
|
|
10903
11979
|
h2("ul", { className: "dxw-list dim-botList" }, props.bots.map((account) => h2(
|
|
10904
11980
|
"li",
|
|
10905
11981
|
{ key: account.botId },
|
|
10906
|
-
h2(
|
|
11982
|
+
h2(AccountCard5, {
|
|
10907
11983
|
account,
|
|
10908
11984
|
busy: props.busyByBot[account.botId],
|
|
10909
11985
|
feedback: props.feedbackByBot[account.botId],
|
|
@@ -10931,7 +12007,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
|
|
|
10931
12007
|
};
|
|
10932
12008
|
}
|
|
10933
12009
|
function WeixinSettingsTab({ rpcCall }) {
|
|
10934
|
-
const [model, setModel] =
|
|
12010
|
+
const [model, setModel] = React21.useState({
|
|
10935
12011
|
phase: "loading",
|
|
10936
12012
|
bots: [],
|
|
10937
12013
|
totals: EMPTY_TOTALS3,
|
|
@@ -10940,33 +12016,33 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10940
12016
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
10941
12017
|
modelCatalog: EMPTY_MODEL_CATALOG
|
|
10942
12018
|
});
|
|
10943
|
-
const [provision, setProvision] =
|
|
10944
|
-
const [busy, setBusy] =
|
|
10945
|
-
const [busyByBot, setBusyByBot] =
|
|
10946
|
-
const [feedbackByBot, setFeedbackByBot] =
|
|
10947
|
-
const [removeTarget, setRemoveTarget] =
|
|
10948
|
-
const [notice, setNotice] =
|
|
10949
|
-
const [now, setNow] =
|
|
10950
|
-
const addButtonRef =
|
|
10951
|
-
const mountedRef =
|
|
12019
|
+
const [provision, setProvision] = React21.useState(null);
|
|
12020
|
+
const [busy, setBusy] = React21.useState(false);
|
|
12021
|
+
const [busyByBot, setBusyByBot] = React21.useState({});
|
|
12022
|
+
const [feedbackByBot, setFeedbackByBot] = React21.useState({});
|
|
12023
|
+
const [removeTarget, setRemoveTarget] = React21.useState(null);
|
|
12024
|
+
const [notice, setNotice] = React21.useState("");
|
|
12025
|
+
const [now, setNow] = React21.useState(() => Date.now());
|
|
12026
|
+
const addButtonRef = React21.useRef(null);
|
|
12027
|
+
const mountedRef = React21.useRef(true);
|
|
10952
12028
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
10953
12029
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
10954
|
-
|
|
12030
|
+
React21.useEffect(() => {
|
|
10955
12031
|
mountedRef.current = true;
|
|
10956
12032
|
return () => {
|
|
10957
12033
|
mountedRef.current = false;
|
|
10958
12034
|
};
|
|
10959
12035
|
}, []);
|
|
10960
|
-
const announce =
|
|
12036
|
+
const announce = React21.useCallback((value) => {
|
|
10961
12037
|
setNotice("");
|
|
10962
12038
|
scheduleAnimationFrame(() => {
|
|
10963
12039
|
if (value) setNotice(value);
|
|
10964
12040
|
}, "announcement");
|
|
10965
12041
|
}, [scheduleAnimationFrame]);
|
|
10966
|
-
const invoke =
|
|
10967
|
-
return
|
|
12042
|
+
const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
|
|
12043
|
+
return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
|
|
10968
12044
|
}, [rpcCall]);
|
|
10969
|
-
const loadStatus =
|
|
12045
|
+
const loadStatus = React21.useCallback(async ({
|
|
10970
12046
|
signal,
|
|
10971
12047
|
silent = false,
|
|
10972
12048
|
restoreProvisioning = false
|
|
@@ -10975,7 +12051,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10975
12051
|
if (workspaceVersion === null || !mountedRef.current) return void 0;
|
|
10976
12052
|
if (!silent) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
10977
12053
|
try {
|
|
10978
|
-
const snapshot =
|
|
12054
|
+
const snapshot = normalizeSnapshot8(await invoke(WEIXIN_ENDPOINTS.status, {}, signal));
|
|
10979
12055
|
if (signal?.aborted || !mountedRef.current || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
10980
12056
|
setModel({
|
|
10981
12057
|
phase: "ready",
|
|
@@ -10999,17 +12075,17 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10999
12075
|
setModel((current) => ({
|
|
11000
12076
|
...current,
|
|
11001
12077
|
phase: silent && current.phase === "ready" ? "ready" : "error",
|
|
11002
|
-
error:
|
|
12078
|
+
error: presentError9(error)
|
|
11003
12079
|
}));
|
|
11004
12080
|
return void 0;
|
|
11005
12081
|
}
|
|
11006
12082
|
}, [invoke, workspaceFence]);
|
|
11007
|
-
|
|
12083
|
+
React21.useEffect(() => {
|
|
11008
12084
|
const controller = new AbortController();
|
|
11009
12085
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
11010
12086
|
return () => controller.abort();
|
|
11011
12087
|
}, [loadStatus]);
|
|
11012
|
-
|
|
12088
|
+
React21.useEffect(() => {
|
|
11013
12089
|
if (model.phase !== "ready") return void 0;
|
|
11014
12090
|
const controller = new AbortController();
|
|
11015
12091
|
let running = false;
|
|
@@ -11028,12 +12104,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11028
12104
|
window.clearInterval(timer);
|
|
11029
12105
|
};
|
|
11030
12106
|
}, [loadStatus, model.phase]);
|
|
11031
|
-
|
|
12107
|
+
React21.useEffect(() => {
|
|
11032
12108
|
if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
|
|
11033
12109
|
const timer = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
11034
12110
|
return () => window.clearInterval(timer);
|
|
11035
12111
|
}, [provision?.attemptId, provision?.status]);
|
|
11036
|
-
const startProvisioning =
|
|
12112
|
+
const startProvisioning = React21.useCallback(async ({ replace = false } = {}) => {
|
|
11037
12113
|
setBusy(true);
|
|
11038
12114
|
try {
|
|
11039
12115
|
if (replace && provision?.attemptId) {
|
|
@@ -11047,14 +12123,14 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11047
12123
|
} catch (error) {
|
|
11048
12124
|
setProvision({
|
|
11049
12125
|
status: "failed",
|
|
11050
|
-
error:
|
|
12126
|
+
error: presentError9(error),
|
|
11051
12127
|
...provision?.attemptId ? { attemptId: provision.attemptId } : {}
|
|
11052
12128
|
});
|
|
11053
12129
|
} finally {
|
|
11054
12130
|
setBusy(false);
|
|
11055
12131
|
}
|
|
11056
12132
|
}, [announce, invoke, provision?.attemptId]);
|
|
11057
|
-
const cancelProvisioning =
|
|
12133
|
+
const cancelProvisioning = React21.useCallback(async () => {
|
|
11058
12134
|
setBusy(true);
|
|
11059
12135
|
try {
|
|
11060
12136
|
if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
|
|
@@ -11064,12 +12140,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11064
12140
|
announce("\u5DF2\u53D6\u6D88\u5FAE\u4FE1\u7ED1\u5B9A\u3002");
|
|
11065
12141
|
scheduleAnimationFrame(() => addButtonRef.current?.focus(), "focus");
|
|
11066
12142
|
} catch (error) {
|
|
11067
|
-
setProvision((current) => ({ ...current, status: "failed", error:
|
|
12143
|
+
setProvision((current) => ({ ...current, status: "failed", error: presentError9(error) }));
|
|
11068
12144
|
} finally {
|
|
11069
12145
|
setBusy(false);
|
|
11070
12146
|
}
|
|
11071
12147
|
}, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
|
|
11072
|
-
const submitVerification =
|
|
12148
|
+
const submitVerification = React21.useCallback(async (verifyCode) => {
|
|
11073
12149
|
if (!provision?.attemptId) return;
|
|
11074
12150
|
setBusy(true);
|
|
11075
12151
|
try {
|
|
@@ -11080,12 +12156,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11080
12156
|
setProvision((current) => ({ ...current, ...next }));
|
|
11081
12157
|
announce("\u914D\u5BF9\u7801\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u7B49\u5F85\u5FAE\u4FE1\u786E\u8BA4\u3002");
|
|
11082
12158
|
} catch (error) {
|
|
11083
|
-
setProvision((current) => ({ ...current, status: "failed", error:
|
|
12159
|
+
setProvision((current) => ({ ...current, status: "failed", error: presentError9(error) }));
|
|
11084
12160
|
} finally {
|
|
11085
12161
|
setBusy(false);
|
|
11086
12162
|
}
|
|
11087
12163
|
}, [announce, invoke, provision?.attemptId]);
|
|
11088
|
-
|
|
12164
|
+
React21.useEffect(() => {
|
|
11089
12165
|
const attemptId = provision?.attemptId;
|
|
11090
12166
|
if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
|
|
11091
12167
|
const controller = new AbortController();
|
|
@@ -11124,7 +12200,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11124
12200
|
}
|
|
11125
12201
|
} catch (error) {
|
|
11126
12202
|
if (scheduler.disposed || error?.name === "AbortError") return;
|
|
11127
|
-
setProvision((current) => current?.attemptId === attemptId ? { ...current, status: "failed", error:
|
|
12203
|
+
setProvision((current) => current?.attemptId === attemptId ? { ...current, status: "failed", error: presentError9(error) } : current);
|
|
11128
12204
|
}
|
|
11129
12205
|
};
|
|
11130
12206
|
scheduler.schedule(poll, provision.pollIntervalMs ?? 1e3);
|
|
@@ -11133,7 +12209,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11133
12209
|
controller.abort();
|
|
11134
12210
|
};
|
|
11135
12211
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
|
|
11136
|
-
const setBotBusy =
|
|
12212
|
+
const setBotBusy = React21.useCallback((botId, value) => {
|
|
11137
12213
|
setBusyByBot((current) => {
|
|
11138
12214
|
const next = { ...current };
|
|
11139
12215
|
if (value) next[botId] = value;
|
|
@@ -11141,7 +12217,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11141
12217
|
return next;
|
|
11142
12218
|
});
|
|
11143
12219
|
}, []);
|
|
11144
|
-
const reconnect =
|
|
12220
|
+
const reconnect = React21.useCallback(async (account) => {
|
|
11145
12221
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11146
12222
|
setBotBusy(account.botId, "reconnect");
|
|
11147
12223
|
setFeedbackByBot((current) => {
|
|
@@ -11150,7 +12226,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11150
12226
|
return next;
|
|
11151
12227
|
});
|
|
11152
12228
|
try {
|
|
11153
|
-
const snapshot =
|
|
12229
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11154
12230
|
WEIXIN_ENDPOINTS.reconnectBot,
|
|
11155
12231
|
{ botId: account.botId, sendTest: true }
|
|
11156
12232
|
));
|
|
@@ -11193,11 +12269,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11193
12269
|
setBotBusy(account.botId, null);
|
|
11194
12270
|
}
|
|
11195
12271
|
}, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11196
|
-
const saveWorkspace =
|
|
12272
|
+
const saveWorkspace = React21.useCallback(async (account, workspace) => {
|
|
11197
12273
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
11198
12274
|
setBotBusy(account.botId, "workspace");
|
|
11199
12275
|
try {
|
|
11200
|
-
const snapshot =
|
|
12276
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11201
12277
|
WEIXIN_ENDPOINTS.setWorkspace,
|
|
11202
12278
|
{ botId: account.botId, workspace }
|
|
11203
12279
|
));
|
|
@@ -11218,11 +12294,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11218
12294
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
11219
12295
|
}
|
|
11220
12296
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11221
|
-
const saveBotSetting =
|
|
12297
|
+
const saveBotSetting = React21.useCallback(async (account, operation, endpoint, payload) => {
|
|
11222
12298
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11223
12299
|
setBotBusy(account.botId, operation);
|
|
11224
12300
|
try {
|
|
11225
|
-
const snapshot =
|
|
12301
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11226
12302
|
endpoint,
|
|
11227
12303
|
{ botId: account.botId, ...payload }
|
|
11228
12304
|
));
|
|
@@ -11243,11 +12319,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11243
12319
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
11244
12320
|
}
|
|
11245
12321
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11246
|
-
const remove =
|
|
12322
|
+
const remove = React21.useCallback(async (account) => {
|
|
11247
12323
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11248
12324
|
setBotBusy(account.botId, "delete");
|
|
11249
12325
|
try {
|
|
11250
|
-
const snapshot =
|
|
12326
|
+
const snapshot = normalizeSnapshot8(await invoke(WEIXIN_ENDPOINTS.deleteBot, {
|
|
11251
12327
|
botId: account.botId,
|
|
11252
12328
|
confirm: true
|
|
11253
12329
|
}));
|
|
@@ -11264,7 +12340,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11264
12340
|
setRemoveTarget(null);
|
|
11265
12341
|
announce("\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002");
|
|
11266
12342
|
} catch (error) {
|
|
11267
|
-
announce(`\u79FB\u9664\u5931\u8D25\uFF1A${
|
|
12343
|
+
announce(`\u79FB\u9664\u5931\u8D25\uFF1A${presentError9(error).message}`);
|
|
11268
12344
|
} finally {
|
|
11269
12345
|
const shouldRefresh = workspaceFence.endMutation();
|
|
11270
12346
|
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
@@ -11310,7 +12386,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11310
12386
|
}, h2(
|
|
11311
12387
|
"section",
|
|
11312
12388
|
{ className: "dxw-page dim-channelPage", "aria-label": "\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
11313
|
-
h2(
|
|
12389
|
+
h2(Heading6, {
|
|
11314
12390
|
totals: model.totals,
|
|
11315
12391
|
adding: Boolean(provision),
|
|
11316
12392
|
busy,
|
|
@@ -11319,7 +12395,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11319
12395
|
}),
|
|
11320
12396
|
h2("div", { className: "dxw-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
11321
12397
|
model.error && model.phase === "ready" ? h2("div", { className: "dxw-statusNotice dim-statusNotice" }, `\u72B6\u6001\u5237\u65B0\u5931\u8D25\uFF1A${model.error.message}`) : null,
|
|
11322
|
-
model.phase === "loading" ? h2(
|
|
12398
|
+
model.phase === "loading" ? h2(LoadingView6) : model.phase === "error" ? h2(
|
|
11323
12399
|
"div",
|
|
11324
12400
|
{ className: "dxw-card dim-surfaceCard" },
|
|
11325
12401
|
h2(
|
|
@@ -11327,13 +12403,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11327
12403
|
{ className: "dxw-error dim-inlineError" },
|
|
11328
12404
|
h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u72B6\u6001"),
|
|
11329
12405
|
h2("p", null, model.error?.message ?? "\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
|
|
11330
|
-
h2(
|
|
12406
|
+
h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
11331
12407
|
)
|
|
11332
12408
|
) : h2(
|
|
11333
|
-
|
|
12409
|
+
React21.Fragment,
|
|
11334
12410
|
null,
|
|
11335
12411
|
provisionView,
|
|
11336
|
-
model.bots.length === 0 && !provision ? h2(
|
|
12412
|
+
model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
|
|
11337
12413
|
model.bots.length > 0 ? h2(AccountList2, {
|
|
11338
12414
|
bots: model.bots,
|
|
11339
12415
|
busyByBot,
|
|
@@ -11369,7 +12445,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11369
12445
|
|
|
11370
12446
|
// plugin-src/client/channels/weixin/styles.js
|
|
11371
12447
|
var WEIXIN_STYLE_ID = "xmanrui-dsh-im-weixin-settings";
|
|
11372
|
-
var
|
|
12448
|
+
var CSS10 = String.raw`
|
|
11373
12449
|
.dxw-page {
|
|
11374
12450
|
--dxw-accent: #07c160;
|
|
11375
12451
|
--dxw-accent-dark: #05994c;
|
|
@@ -11479,7 +12555,7 @@ function installWeixinStyles() {
|
|
|
11479
12555
|
const style = document.createElement("style");
|
|
11480
12556
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
11481
12557
|
style.dataset.pluginCss = WEIXIN_STYLE_ID;
|
|
11482
|
-
style.textContent =
|
|
12558
|
+
style.textContent = CSS10;
|
|
11483
12559
|
document.head.appendChild(style);
|
|
11484
12560
|
return () => style.remove();
|
|
11485
12561
|
}
|
|
@@ -11502,28 +12578,28 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
11502
12578
|
var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
|
|
11503
12579
|
var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
11504
12580
|
var QR_DATA_URL4 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
11505
|
-
function
|
|
12581
|
+
function isRecord8(value) {
|
|
11506
12582
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11507
12583
|
}
|
|
11508
|
-
function
|
|
12584
|
+
function text6(value, fallback, max = 240) {
|
|
11509
12585
|
return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
|
|
11510
12586
|
}
|
|
11511
|
-
function
|
|
11512
|
-
const result =
|
|
12587
|
+
function id5(value) {
|
|
12588
|
+
const result = text6(value, "", 128);
|
|
11513
12589
|
return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
|
|
11514
12590
|
}
|
|
11515
|
-
function
|
|
12591
|
+
function timestamp7(value) {
|
|
11516
12592
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
11517
12593
|
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
11518
12594
|
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
11519
12595
|
}
|
|
11520
|
-
function
|
|
11521
|
-
if (!
|
|
12596
|
+
function unwrapRpcResult10(result) {
|
|
12597
|
+
if (!isRecord8(result) || typeof result.ok !== "boolean") {
|
|
11522
12598
|
throw new Error("WhatsApp \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
11523
12599
|
}
|
|
11524
12600
|
if (!result.ok) {
|
|
11525
|
-
const error = new Error(
|
|
11526
|
-
error.code =
|
|
12601
|
+
const error = new Error(text6(result.error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25"));
|
|
12602
|
+
error.code = text6(result.error?.code, "WHATSAPP_RPC_ERROR", 80);
|
|
11527
12603
|
throw error;
|
|
11528
12604
|
}
|
|
11529
12605
|
return result.value;
|
|
@@ -11532,61 +12608,61 @@ function safeQrSource6(value) {
|
|
|
11532
12608
|
return typeof value === "string" && value.length <= 2 * 1024 * 1024 && QR_DATA_URL4.test(value) ? value : void 0;
|
|
11533
12609
|
}
|
|
11534
12610
|
function normalizeProvisioning6(value, now = Date.now()) {
|
|
11535
|
-
const source =
|
|
11536
|
-
if (!
|
|
11537
|
-
const attemptId =
|
|
12611
|
+
const source = isRecord8(value?.provisioning) ? value.provisioning : value;
|
|
12612
|
+
if (!isRecord8(source)) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6");
|
|
12613
|
+
const attemptId = id5(source.attemptId);
|
|
11538
12614
|
if (!attemptId) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1");
|
|
11539
|
-
const reported =
|
|
12615
|
+
const reported = text6(source.status, "failed", 32);
|
|
11540
12616
|
const result = {
|
|
11541
12617
|
attemptId,
|
|
11542
12618
|
status: PROVISION_STATES5.has(reported) ? reported : "failed",
|
|
11543
|
-
expiresAt:
|
|
12619
|
+
expiresAt: timestamp7(source.expiresAt) ?? now + 6e4,
|
|
11544
12620
|
pollIntervalMs: Math.min(5e3, Math.max(500, Number(source.pollIntervalMs) || 1e3)),
|
|
11545
12621
|
qrRevision: Number.isSafeInteger(source.qrRevision) ? source.qrRevision : 0
|
|
11546
12622
|
};
|
|
11547
12623
|
const qrCodeDataUrl = safeQrSource6(source.qrCodeDataUrl);
|
|
11548
12624
|
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
11549
|
-
if (
|
|
11550
|
-
if (
|
|
11551
|
-
code:
|
|
11552
|
-
message:
|
|
12625
|
+
if (id5(source.botId)) result.botId = id5(source.botId);
|
|
12626
|
+
if (isRecord8(source.error)) result.error = {
|
|
12627
|
+
code: text6(source.error.code, "WHATSAPP_PROVISION_FAILED", 80),
|
|
12628
|
+
message: text6(source.error.message, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
|
|
11553
12629
|
};
|
|
11554
12630
|
return result;
|
|
11555
12631
|
}
|
|
11556
|
-
function
|
|
11557
|
-
if (!
|
|
12632
|
+
function normalizeBot7(value) {
|
|
12633
|
+
if (!isRecord8(value) || !id5(value.botId)) return void 0;
|
|
11558
12634
|
const connected = value.connected === true;
|
|
11559
12635
|
const state = BOT_STATES.has(value.state) ? value.state : "offline";
|
|
11560
12636
|
return {
|
|
11561
|
-
botId:
|
|
12637
|
+
botId: id5(value.botId),
|
|
11562
12638
|
connected,
|
|
11563
12639
|
state: connected ? "connected" : state,
|
|
11564
|
-
workspace:
|
|
12640
|
+
workspace: text6(value.workspace, "", 4096),
|
|
11565
12641
|
model: normalizeModelSelection(value.model),
|
|
11566
12642
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
11567
12643
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
11568
12644
|
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
11569
12645
|
bot: {
|
|
11570
|
-
name:
|
|
11571
|
-
idMasked:
|
|
12646
|
+
name: text6(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
|
|
12647
|
+
idMasked: text6(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
|
|
11572
12648
|
},
|
|
11573
12649
|
health: {
|
|
11574
|
-
summary:
|
|
11575
|
-
lastCheckedAt:
|
|
12650
|
+
summary: text6(value.health?.summary, connected ? "WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38" : "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
12651
|
+
lastCheckedAt: timestamp7(value.health?.lastCheckedAt)
|
|
11576
12652
|
},
|
|
11577
12653
|
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
11578
|
-
error:
|
|
11579
|
-
code:
|
|
11580
|
-
message:
|
|
12654
|
+
error: isRecord8(value.error) ? {
|
|
12655
|
+
code: text6(value.error.code, "WHATSAPP_ACCOUNT_ERROR", 80),
|
|
12656
|
+
message: text6(value.error.message, "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
|
|
11581
12657
|
} : null
|
|
11582
12658
|
};
|
|
11583
12659
|
}
|
|
11584
|
-
function
|
|
11585
|
-
const source =
|
|
11586
|
-
if (!
|
|
12660
|
+
function normalizeSnapshot9(value) {
|
|
12661
|
+
const source = isRecord8(value?.snapshot) ? value.snapshot : value;
|
|
12662
|
+
if (!isRecord8(source) || !Array.isArray(source.bots)) {
|
|
11587
12663
|
throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
11588
12664
|
}
|
|
11589
|
-
const bots = source.bots.map(
|
|
12665
|
+
const bots = source.bots.map(normalizeBot7).filter(Boolean);
|
|
11590
12666
|
return {
|
|
11591
12667
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
11592
12668
|
bots,
|
|
@@ -11596,10 +12672,10 @@ function normalizeSnapshot8(value) {
|
|
|
11596
12672
|
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
11597
12673
|
};
|
|
11598
12674
|
}
|
|
11599
|
-
function
|
|
12675
|
+
function presentError10(error) {
|
|
11600
12676
|
return {
|
|
11601
|
-
code:
|
|
11602
|
-
message:
|
|
12677
|
+
code: text6(error?.code, "WHATSAPP_ERROR", 80),
|
|
12678
|
+
message: text6(error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
11603
12679
|
};
|
|
11604
12680
|
}
|
|
11605
12681
|
function formatRemaining6(milliseconds) {
|
|
@@ -11608,11 +12684,11 @@ function formatRemaining6(milliseconds) {
|
|
|
11608
12684
|
}
|
|
11609
12685
|
|
|
11610
12686
|
// plugin-src/client/channels/whatsapp/index.js
|
|
11611
|
-
var
|
|
12687
|
+
var React22 = __toESM(require("react"), 1);
|
|
11612
12688
|
|
|
11613
12689
|
// plugin-src/client/channels/whatsapp/styles.js
|
|
11614
12690
|
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
|
11615
|
-
var
|
|
12691
|
+
var CSS11 = String.raw`
|
|
11616
12692
|
.dwa-page { --ddt-accent: #25d366; --ddt-accent-deep: #128c7e; --ddt-accent-wash: #eafbf0; }
|
|
11617
12693
|
.dwa-avatar { color: #fff; background: #25d366; }
|
|
11618
12694
|
.dwa-avatar svg { display: block; }
|
|
@@ -11626,14 +12702,14 @@ function installWhatsappStyles() {
|
|
|
11626
12702
|
const style = document.createElement("style");
|
|
11627
12703
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
11628
12704
|
style.dataset.pluginCss = WHATSAPP_STYLE_ID;
|
|
11629
|
-
style.textContent =
|
|
12705
|
+
style.textContent = CSS11;
|
|
11630
12706
|
document.head.appendChild(style);
|
|
11631
12707
|
return () => style.remove();
|
|
11632
12708
|
}
|
|
11633
12709
|
|
|
11634
12710
|
// plugin-src/client/channels/whatsapp/index.js
|
|
11635
12711
|
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
|
11636
|
-
var
|
|
12712
|
+
var Button16 = React22.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
11637
12713
|
return h2("button", {
|
|
11638
12714
|
...props,
|
|
11639
12715
|
ref,
|
|
@@ -11642,7 +12718,7 @@ var Button14 = React21.forwardRef(function Button15({ children, kind = "secondar
|
|
|
11642
12718
|
"data-kind": kind
|
|
11643
12719
|
}, children);
|
|
11644
12720
|
});
|
|
11645
|
-
function
|
|
12721
|
+
function checkedTime7(value) {
|
|
11646
12722
|
if (!value) return "\u5C1A\u672A\u68C0\u67E5";
|
|
11647
12723
|
try {
|
|
11648
12724
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
@@ -11663,7 +12739,7 @@ function connectionTestNotice3(value) {
|
|
|
11663
12739
|
}
|
|
11664
12740
|
return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
11665
12741
|
}
|
|
11666
|
-
function
|
|
12742
|
+
function Heading7({ totals, busy, onAdd, addButtonRef }) {
|
|
11667
12743
|
return h2(
|
|
11668
12744
|
"div",
|
|
11669
12745
|
{ className: "ddt-heading" },
|
|
@@ -11673,7 +12749,7 @@ function Heading6({ totals, busy, onAdd, addButtonRef }) {
|
|
|
11673
12749
|
h2(
|
|
11674
12750
|
"div",
|
|
11675
12751
|
{ className: "dim-bindActions" },
|
|
11676
|
-
h2(
|
|
12752
|
+
h2(Button16, {
|
|
11677
12753
|
kind: "primary",
|
|
11678
12754
|
className: "dim-scanButton",
|
|
11679
12755
|
onClick: onAdd,
|
|
@@ -11690,13 +12766,13 @@ function Heading6({ totals, busy, onAdd, addButtonRef }) {
|
|
|
11690
12766
|
)
|
|
11691
12767
|
);
|
|
11692
12768
|
}
|
|
11693
|
-
function
|
|
12769
|
+
function LoadingView7() {
|
|
11694
12770
|
return h2("div", {
|
|
11695
12771
|
className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView",
|
|
11696
12772
|
"aria-busy": "true"
|
|
11697
12773
|
}, h2("div", { className: "ddt-spinner dim-spinner" }), "\u6B63\u5728\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001\u2026");
|
|
11698
12774
|
}
|
|
11699
|
-
function
|
|
12775
|
+
function EmptyView7({ busy, onStart }) {
|
|
11700
12776
|
return h2(
|
|
11701
12777
|
"div",
|
|
11702
12778
|
{ className: "ddt-card dim-surfaceCard" },
|
|
@@ -11718,7 +12794,7 @@ function EmptyView6({ busy, onStart }) {
|
|
|
11718
12794
|
"div",
|
|
11719
12795
|
{ className: "ddt-actions dim-viewActions" },
|
|
11720
12796
|
h2(
|
|
11721
|
-
|
|
12797
|
+
Button16,
|
|
11722
12798
|
{ kind: "primary", onClick: onStart, disabled: busy },
|
|
11723
12799
|
busy ? "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" : "\u751F\u6210\u4E8C\u7EF4\u7801"
|
|
11724
12800
|
)
|
|
@@ -11787,8 +12863,8 @@ function QrPanel5({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
11787
12863
|
h2(
|
|
11788
12864
|
"div",
|
|
11789
12865
|
{ className: "ddt-actions dim-viewActions" },
|
|
11790
|
-
h2(
|
|
11791
|
-
h2(
|
|
12866
|
+
h2(Button16, { onClick: onRefresh, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
12867
|
+
h2(Button16, { kind: "quiet", onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
11792
12868
|
)
|
|
11793
12869
|
)
|
|
11794
12870
|
)
|
|
@@ -11824,13 +12900,13 @@ function ProvisionView3({ provision, busy, onRetry, onClose }) {
|
|
|
11824
12900
|
h2(
|
|
11825
12901
|
"div",
|
|
11826
12902
|
{ className: "ddt-actions dim-viewActions" },
|
|
11827
|
-
h2(
|
|
11828
|
-
h2(
|
|
12903
|
+
h2(Button16, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
12904
|
+
h2(Button16, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
|
|
11829
12905
|
)
|
|
11830
12906
|
)
|
|
11831
12907
|
);
|
|
11832
12908
|
}
|
|
11833
|
-
function
|
|
12909
|
+
function RemoveConfirmation6({ account, busy, onConfirm, onCancel }) {
|
|
11834
12910
|
return h2(
|
|
11835
12911
|
"div",
|
|
11836
12912
|
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
@@ -11839,9 +12915,9 @@ function RemoveConfirmation5({ account, busy, onConfirm, onCancel }) {
|
|
|
11839
12915
|
h2(
|
|
11840
12916
|
"div",
|
|
11841
12917
|
{ className: "ddt-actions dim-viewActions" },
|
|
11842
|
-
h2(
|
|
12918
|
+
h2(Button16, { onClick: onCancel, disabled: busy }, "\u4FDD\u7559\u673A\u5668\u4EBA"),
|
|
11843
12919
|
h2(
|
|
11844
|
-
|
|
12920
|
+
Button16,
|
|
11845
12921
|
{ kind: "danger", onClick: onConfirm, disabled: busy },
|
|
11846
12922
|
busy ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664\u63A5\u5165"
|
|
11847
12923
|
)
|
|
@@ -11911,7 +12987,7 @@ function WhatsappAccountCard({
|
|
|
11911
12987
|
tone,
|
|
11912
12988
|
stateLabel: stateLabel2,
|
|
11913
12989
|
lastCheckedAt: account.health.lastCheckedAt,
|
|
11914
|
-
formatCheckedTime:
|
|
12990
|
+
formatCheckedTime: checkedTime7
|
|
11915
12991
|
}),
|
|
11916
12992
|
h2(BotSettingsButton, {
|
|
11917
12993
|
channel: "whatsapp",
|
|
@@ -11952,12 +13028,12 @@ function WhatsappAccountCard({
|
|
|
11952
13028
|
h2(
|
|
11953
13029
|
"div",
|
|
11954
13030
|
{ className: "ddt-actions dim-cardActions" },
|
|
11955
|
-
h2(
|
|
13031
|
+
h2(Button16, {
|
|
11956
13032
|
className: "dim-cardAction",
|
|
11957
13033
|
onClick: onReconnect,
|
|
11958
13034
|
disabled: Boolean(busy)
|
|
11959
13035
|
}, busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
|
|
11960
|
-
h2(
|
|
13036
|
+
h2(Button16, {
|
|
11961
13037
|
className: "dim-cardAction",
|
|
11962
13038
|
kind: "danger",
|
|
11963
13039
|
onClick: onRequestRemove,
|
|
@@ -11977,7 +13053,7 @@ function WhatsappAccountCard({
|
|
|
11977
13053
|
)
|
|
11978
13054
|
)
|
|
11979
13055
|
),
|
|
11980
|
-
removing ? h2(
|
|
13056
|
+
removing ? h2(RemoveConfirmation6, {
|
|
11981
13057
|
account,
|
|
11982
13058
|
busy: busy === "delete",
|
|
11983
13059
|
onConfirm: onConfirmRemove,
|
|
@@ -11986,7 +13062,7 @@ function WhatsappAccountCard({
|
|
|
11986
13062
|
);
|
|
11987
13063
|
}
|
|
11988
13064
|
function WhatsappSettingsTab({ rpcCall }) {
|
|
11989
|
-
const [model, setModel] =
|
|
13065
|
+
const [model, setModel] = React22.useState({
|
|
11990
13066
|
phase: "loading",
|
|
11991
13067
|
bots: [],
|
|
11992
13068
|
totals: { configured: 0, connected: 0 },
|
|
@@ -11994,16 +13070,16 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
11994
13070
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
11995
13071
|
modelCatalog: EMPTY_MODEL_CATALOG
|
|
11996
13072
|
});
|
|
11997
|
-
const [provision, setProvision] =
|
|
11998
|
-
const [busy, setBusy] =
|
|
11999
|
-
const [busyByBot, setBusyByBot] =
|
|
12000
|
-
const [testNoticeByBot, setTestNoticeByBot] =
|
|
12001
|
-
const [removeTarget, setRemoveTarget] =
|
|
12002
|
-
const [now, setNow] =
|
|
12003
|
-
const mounted =
|
|
13073
|
+
const [provision, setProvision] = React22.useState(null);
|
|
13074
|
+
const [busy, setBusy] = React22.useState(false);
|
|
13075
|
+
const [busyByBot, setBusyByBot] = React22.useState({});
|
|
13076
|
+
const [testNoticeByBot, setTestNoticeByBot] = React22.useState({});
|
|
13077
|
+
const [removeTarget, setRemoveTarget] = React22.useState(null);
|
|
13078
|
+
const [now, setNow] = React22.useState(Date.now());
|
|
13079
|
+
const mounted = React22.useRef(true);
|
|
12004
13080
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
12005
|
-
const addButtonRef =
|
|
12006
|
-
|
|
13081
|
+
const addButtonRef = React22.useRef(null);
|
|
13082
|
+
React22.useEffect(() => {
|
|
12007
13083
|
const disposeDingtalk = installDingtalkStyles();
|
|
12008
13084
|
const disposeWhatsapp = installWhatsappStyles();
|
|
12009
13085
|
mounted.current = true;
|
|
@@ -12013,16 +13089,16 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12013
13089
|
disposeDingtalk();
|
|
12014
13090
|
};
|
|
12015
13091
|
}, []);
|
|
12016
|
-
const invoke =
|
|
13092
|
+
const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
|
|
12017
13093
|
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
12018
|
-
return
|
|
13094
|
+
return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
|
|
12019
13095
|
}, [rpcCall]);
|
|
12020
|
-
const loadStatus =
|
|
13096
|
+
const loadStatus = React22.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
12021
13097
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
12022
13098
|
if (workspaceVersion === null) return void 0;
|
|
12023
13099
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
12024
13100
|
try {
|
|
12025
|
-
const snapshot =
|
|
13101
|
+
const snapshot = normalizeSnapshot9(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
12026
13102
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
12027
13103
|
setModel({
|
|
12028
13104
|
phase: "ready",
|
|
@@ -12042,18 +13118,18 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12042
13118
|
setModel((current) => ({
|
|
12043
13119
|
...current,
|
|
12044
13120
|
phase: silent ? current.phase : "error",
|
|
12045
|
-
error:
|
|
13121
|
+
error: presentError10(error)
|
|
12046
13122
|
}));
|
|
12047
13123
|
}
|
|
12048
13124
|
return void 0;
|
|
12049
13125
|
}
|
|
12050
13126
|
}, [invoke, workspaceFence]);
|
|
12051
|
-
|
|
13127
|
+
React22.useEffect(() => {
|
|
12052
13128
|
const controller = new AbortController();
|
|
12053
13129
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
12054
13130
|
return () => controller.abort();
|
|
12055
13131
|
}, [loadStatus]);
|
|
12056
|
-
|
|
13132
|
+
React22.useEffect(() => {
|
|
12057
13133
|
if (model.phase !== "ready") return void 0;
|
|
12058
13134
|
const controller = new AbortController();
|
|
12059
13135
|
const timer = window.setInterval(
|
|
@@ -12065,12 +13141,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12065
13141
|
window.clearInterval(timer);
|
|
12066
13142
|
};
|
|
12067
13143
|
}, [loadStatus, model.phase]);
|
|
12068
|
-
|
|
13144
|
+
React22.useEffect(() => {
|
|
12069
13145
|
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
12070
13146
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
12071
13147
|
return () => window.clearInterval(timer);
|
|
12072
13148
|
}, [provision?.attemptId, provision?.status]);
|
|
12073
|
-
const startProvisioning =
|
|
13149
|
+
const startProvisioning = React22.useCallback(async (replace = false) => {
|
|
12074
13150
|
setBusy(true);
|
|
12075
13151
|
try {
|
|
12076
13152
|
if (replace && provision?.attemptId) {
|
|
@@ -12083,12 +13159,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12083
13159
|
setNow(Date.now());
|
|
12084
13160
|
setProvision({ ...started, durationMs: Math.max(1, started.expiresAt - Date.now()) });
|
|
12085
13161
|
} catch (error) {
|
|
12086
|
-
if (mounted.current) setProvision({ status: "failed", error:
|
|
13162
|
+
if (mounted.current) setProvision({ status: "failed", error: presentError10(error) });
|
|
12087
13163
|
} finally {
|
|
12088
13164
|
if (mounted.current) setBusy(false);
|
|
12089
13165
|
}
|
|
12090
13166
|
}, [invoke, provision?.attemptId]);
|
|
12091
|
-
const closeProvision =
|
|
13167
|
+
const closeProvision = React22.useCallback(async () => {
|
|
12092
13168
|
setBusy(true);
|
|
12093
13169
|
try {
|
|
12094
13170
|
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
|
@@ -12099,7 +13175,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12099
13175
|
if (mounted.current) setBusy(false);
|
|
12100
13176
|
}
|
|
12101
13177
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
12102
|
-
|
|
13178
|
+
React22.useEffect(() => {
|
|
12103
13179
|
const attemptId = provision?.attemptId;
|
|
12104
13180
|
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
12105
13181
|
const controller = new AbortController();
|
|
@@ -12129,7 +13205,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12129
13205
|
if (ACTIVE_STATES3.has(current.status)) schedule(current.pollIntervalMs);
|
|
12130
13206
|
} catch (error) {
|
|
12131
13207
|
if (!disposed && !controller.signal.aborted && mounted.current) {
|
|
12132
|
-
setProvision({ status: "failed", error:
|
|
13208
|
+
setProvision({ status: "failed", error: presentError10(error) });
|
|
12133
13209
|
}
|
|
12134
13210
|
}
|
|
12135
13211
|
};
|
|
@@ -12140,7 +13216,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12140
13216
|
if (timer) window.clearTimeout(timer);
|
|
12141
13217
|
};
|
|
12142
13218
|
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
|
12143
|
-
const botAction =
|
|
13219
|
+
const botAction = React22.useCallback(async (account, operation, endpoint, payload) => {
|
|
12144
13220
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
12145
13221
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
12146
13222
|
if (operation === "reconnect") {
|
|
@@ -12152,7 +13228,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12152
13228
|
}
|
|
12153
13229
|
try {
|
|
12154
13230
|
const value = await invoke(endpoint, payload);
|
|
12155
|
-
const snapshot =
|
|
13231
|
+
const snapshot = normalizeSnapshot9(value);
|
|
12156
13232
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
12157
13233
|
setModel({
|
|
12158
13234
|
phase: "ready",
|
|
@@ -12251,13 +13327,13 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12251
13327
|
className: "ddt-page dwa-page dim-channelPage",
|
|
12252
13328
|
"aria-label": "WhatsApp \u8BBE\u7F6E"
|
|
12253
13329
|
},
|
|
12254
|
-
h2(
|
|
13330
|
+
h2(Heading7, {
|
|
12255
13331
|
totals: model.totals,
|
|
12256
13332
|
busy,
|
|
12257
13333
|
onAdd: () => void startProvisioning(false),
|
|
12258
13334
|
addButtonRef
|
|
12259
13335
|
}),
|
|
12260
|
-
model.phase === "loading" ? h2(
|
|
13336
|
+
model.phase === "loading" ? h2(LoadingView7) : model.phase === "error" ? h2(
|
|
12261
13337
|
"div",
|
|
12262
13338
|
{ className: "ddt-card dim-surfaceCard" },
|
|
12263
13339
|
h2(
|
|
@@ -12265,10 +13341,10 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12265
13341
|
{ className: "ddt-inlineError dim-inlineError" },
|
|
12266
13342
|
h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001"),
|
|
12267
13343
|
h2("p", null, model.error?.message),
|
|
12268
|
-
h2(
|
|
13344
|
+
h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
12269
13345
|
)
|
|
12270
13346
|
) : h2(
|
|
12271
|
-
|
|
13347
|
+
React22.Fragment,
|
|
12272
13348
|
null,
|
|
12273
13349
|
provision?.status === "pending" ? h2(QrPanel5, {
|
|
12274
13350
|
provision,
|
|
@@ -12281,17 +13357,17 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12281
13357
|
busy,
|
|
12282
13358
|
onRetry: () => void startProvisioning(true),
|
|
12283
13359
|
onClose: () => void closeProvision()
|
|
12284
|
-
}) : model.bots.length === 0 ? h2(
|
|
13360
|
+
}) : model.bots.length === 0 ? h2(EmptyView7, { busy, onStart: () => void startProvisioning(false) }) : null,
|
|
12285
13361
|
botList
|
|
12286
13362
|
)
|
|
12287
13363
|
)));
|
|
12288
13364
|
}
|
|
12289
13365
|
|
|
12290
13366
|
// plugin-src/client/delivery-settings.js
|
|
12291
|
-
var
|
|
13367
|
+
var React25 = __toESM(require("react"), 1);
|
|
12292
13368
|
|
|
12293
13369
|
// plugin-src/client/access-policy-settings.js
|
|
12294
|
-
var
|
|
13370
|
+
var React23 = __toESM(require("react"), 1);
|
|
12295
13371
|
var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
|
|
12296
13372
|
var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
|
12297
13373
|
weixin: Object.freeze({
|
|
@@ -12317,6 +13393,12 @@ var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
12317
13393
|
groupUserLabel: "\u7FA4\u6210\u5458\u7528\u6237 ID",
|
|
12318
13394
|
groupPlaceholder: "\u586B\u5199 userid"
|
|
12319
13395
|
}),
|
|
13396
|
+
wecomApp: Object.freeze({
|
|
13397
|
+
directUserLabel: "\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID",
|
|
13398
|
+
directPlaceholder: "\u586B\u5199 userid",
|
|
13399
|
+
groupUserLabel: "\u7FA4\u6210\u5458\u7528\u6237 ID",
|
|
13400
|
+
groupPlaceholder: "\u586B\u5199 userid"
|
|
13401
|
+
}),
|
|
12320
13402
|
qq: Object.freeze({
|
|
12321
13403
|
directUserLabel: "QQ User Open ID",
|
|
12322
13404
|
directPlaceholder: "\u586B\u5199 user_openid",
|
|
@@ -12366,7 +13448,7 @@ function clonePolicy(policy) {
|
|
|
12366
13448
|
group: cloneScope(policy.group)
|
|
12367
13449
|
};
|
|
12368
13450
|
}
|
|
12369
|
-
function
|
|
13451
|
+
function unwrapRpcResult11(result) {
|
|
12370
13452
|
if (result?.ok === true) return result.value;
|
|
12371
13453
|
if (result?.ok === false) {
|
|
12372
13454
|
const error = new Error(result.error?.message || "\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -12393,8 +13475,8 @@ function ScenePolicyEditor({
|
|
|
12393
13475
|
unsupported = false,
|
|
12394
13476
|
onChange
|
|
12395
13477
|
}) {
|
|
12396
|
-
const ownerHelpId =
|
|
12397
|
-
const emptyAllowlistHelpId =
|
|
13478
|
+
const ownerHelpId = React23.useId();
|
|
13479
|
+
const emptyAllowlistHelpId = React23.useId();
|
|
12398
13480
|
const allowlist = policy.mode === "allowlist";
|
|
12399
13481
|
const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
|
|
12400
13482
|
const branchKey = allowlist ? "allowlist" : "open";
|
|
@@ -12446,7 +13528,7 @@ function ScenePolicyEditor({
|
|
|
12446
13528
|
h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
|
|
12447
13529
|
h2("p", null, "\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002")
|
|
12448
13530
|
) : h2(
|
|
12449
|
-
|
|
13531
|
+
React23.Fragment,
|
|
12450
13532
|
null,
|
|
12451
13533
|
h2(
|
|
12452
13534
|
"div",
|
|
@@ -12587,16 +13669,16 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12587
13669
|
const definition = ACCESS_CHANNEL_DEFINITIONS[channel4];
|
|
12588
13670
|
const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
|
|
12589
13671
|
const initialKey = JSON.stringify(initialPolicy);
|
|
12590
|
-
const [draft, setDraft] =
|
|
13672
|
+
const [draft, setDraft] = React23.useState(() => clonePolicy(
|
|
12591
13673
|
initialPolicy ?? DEFAULT_ACCESS_POLICY
|
|
12592
13674
|
));
|
|
12593
|
-
const [saving, setSaving] =
|
|
12594
|
-
const [feedback, setFeedback] =
|
|
12595
|
-
|
|
13675
|
+
const [saving, setSaving] = React23.useState(false);
|
|
13676
|
+
const [feedback, setFeedback] = React23.useState(null);
|
|
13677
|
+
React23.useEffect(() => {
|
|
12596
13678
|
const next = normalizeAccessPolicy(account?.accessPolicy);
|
|
12597
13679
|
setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
|
|
12598
13680
|
}, [account?.botId, initialKey]);
|
|
12599
|
-
|
|
13681
|
+
React23.useEffect(() => {
|
|
12600
13682
|
setFeedback(null);
|
|
12601
13683
|
}, [account?.botId]);
|
|
12602
13684
|
if (!definition) {
|
|
@@ -12613,7 +13695,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12613
13695
|
try {
|
|
12614
13696
|
const policy = validateAccessPolicy(draft);
|
|
12615
13697
|
if (typeof rpcCall !== "function") throw new Error("\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
12616
|
-
const value =
|
|
13698
|
+
const value = unwrapRpcResult11(await rpcCall(ACCESS_POLICY_ENDPOINT, {
|
|
12617
13699
|
botId: account.botId,
|
|
12618
13700
|
policy
|
|
12619
13701
|
}));
|
|
@@ -12687,7 +13769,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12687
13769
|
}
|
|
12688
13770
|
|
|
12689
13771
|
// plugin-src/client/channels/feishu/group-settings.js
|
|
12690
|
-
var
|
|
13772
|
+
var React24 = __toESM(require("react"), 1);
|
|
12691
13773
|
var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
12692
13774
|
function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
|
|
12693
13775
|
return h2("button", {
|
|
@@ -12748,9 +13830,9 @@ function GroupResponseModeEditor({
|
|
|
12748
13830
|
onAuthorize
|
|
12749
13831
|
}) {
|
|
12750
13832
|
const current = normalizeGroupResponseMode(value);
|
|
12751
|
-
const [saving, setSaving] =
|
|
12752
|
-
const [authorizing, setAuthorizing] =
|
|
12753
|
-
const [error, setError] =
|
|
13833
|
+
const [saving, setSaving] = React24.useState(false);
|
|
13834
|
+
const [authorizing, setAuthorizing] = React24.useState(false);
|
|
13835
|
+
const [error, setError] = React24.useState(null);
|
|
12754
13836
|
const change = async (event) => {
|
|
12755
13837
|
const next = normalizeGroupResponseMode(event.target.value);
|
|
12756
13838
|
if (next === current || saving || disabled) return;
|
|
@@ -12831,8 +13913,8 @@ function GroupResponseModeEditor({
|
|
|
12831
13913
|
}
|
|
12832
13914
|
function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
|
|
12833
13915
|
const current = value === true ? "on" : "off";
|
|
12834
|
-
const [saving, setSaving] =
|
|
12835
|
-
const [error, setError] =
|
|
13916
|
+
const [saving, setSaving] = React24.useState(false);
|
|
13917
|
+
const [error, setError] = React24.useState(null);
|
|
12836
13918
|
const change = async (event) => {
|
|
12837
13919
|
const next = event.target.value === "on";
|
|
12838
13920
|
if ((next ? "on" : "off") === current || saving || disabled) return;
|
|
@@ -13019,14 +14101,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
|
|
|
13019
14101
|
);
|
|
13020
14102
|
}
|
|
13021
14103
|
function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
13022
|
-
const [settings, setSettings] =
|
|
13023
|
-
const [refreshing, setRefreshing] =
|
|
13024
|
-
const [refreshError, setRefreshError] =
|
|
13025
|
-
const [provision, setProvision] =
|
|
13026
|
-
const [provisionBusy, setProvisionBusy] =
|
|
13027
|
-
const [now, setNow] =
|
|
13028
|
-
const mounted =
|
|
13029
|
-
|
|
14104
|
+
const [settings, setSettings] = React24.useState(() => groupSettingsFrom(account));
|
|
14105
|
+
const [refreshing, setRefreshing] = React24.useState(false);
|
|
14106
|
+
const [refreshError, setRefreshError] = React24.useState(null);
|
|
14107
|
+
const [provision, setProvision] = React24.useState(null);
|
|
14108
|
+
const [provisionBusy, setProvisionBusy] = React24.useState(false);
|
|
14109
|
+
const [now, setNow] = React24.useState(() => Date.now());
|
|
14110
|
+
const mounted = React24.useRef(true);
|
|
14111
|
+
React24.useEffect(() => {
|
|
13030
14112
|
setSettings(groupSettingsFrom(account));
|
|
13031
14113
|
}, [
|
|
13032
14114
|
account.botId,
|
|
@@ -13034,22 +14116,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13034
14116
|
account.groupTopicReply,
|
|
13035
14117
|
account.groupMessagePermissionGranted
|
|
13036
14118
|
]);
|
|
13037
|
-
|
|
14119
|
+
React24.useEffect(() => {
|
|
13038
14120
|
mounted.current = true;
|
|
13039
14121
|
return () => {
|
|
13040
14122
|
mounted.current = false;
|
|
13041
14123
|
};
|
|
13042
14124
|
}, []);
|
|
13043
|
-
const invoke =
|
|
14125
|
+
const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
|
|
13044
14126
|
if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
13045
14127
|
return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
|
|
13046
14128
|
}, [rpcCall]);
|
|
13047
|
-
const applySnapshot =
|
|
14129
|
+
const applySnapshot = React24.useCallback((value) => {
|
|
13048
14130
|
const result = targetBotFromSnapshot(value, account.botId);
|
|
13049
14131
|
if (mounted.current) setSettings(groupSettingsFrom(result.bot));
|
|
13050
14132
|
return result;
|
|
13051
14133
|
}, [account.botId]);
|
|
13052
|
-
const loadSettings =
|
|
14134
|
+
const loadSettings = React24.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
|
|
13053
14135
|
setRefreshing(true);
|
|
13054
14136
|
setRefreshError(null);
|
|
13055
14137
|
try {
|
|
@@ -13059,13 +14141,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13059
14141
|
if (restoreProvisioning) {
|
|
13060
14142
|
const active = result.snapshot.provisioning;
|
|
13061
14143
|
if (active?.operation === GROUP_MESSAGE_PERMISSION_OPERATION2 && active.botId === account.botId) {
|
|
13062
|
-
const
|
|
13063
|
-
setNow(
|
|
14144
|
+
const timestamp8 = Date.now();
|
|
14145
|
+
setNow(timestamp8);
|
|
13064
14146
|
setProvision({
|
|
13065
14147
|
phase: active.submitted ? "connecting" : "qr",
|
|
13066
14148
|
...active,
|
|
13067
|
-
durationMs: Math.max(1, active.expiresAt -
|
|
13068
|
-
expired: !active.submitted && active.expiresAt <=
|
|
14149
|
+
durationMs: Math.max(1, active.expiresAt - timestamp8),
|
|
14150
|
+
expired: !active.submitted && active.expiresAt <= timestamp8
|
|
13069
14151
|
});
|
|
13070
14152
|
}
|
|
13071
14153
|
}
|
|
@@ -13078,16 +14160,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13078
14160
|
if (!signal?.aborted && mounted.current) setRefreshing(false);
|
|
13079
14161
|
}
|
|
13080
14162
|
}, [account.botId, applySnapshot, invoke]);
|
|
13081
|
-
|
|
14163
|
+
React24.useEffect(() => {
|
|
13082
14164
|
const controller = new AbortController();
|
|
13083
14165
|
void loadSettings({ signal: controller.signal, restoreProvisioning: true });
|
|
13084
14166
|
return () => controller.abort();
|
|
13085
14167
|
}, [loadSettings]);
|
|
13086
|
-
const saveSetting =
|
|
14168
|
+
const saveSetting = React24.useCallback(async (endpoint, payload) => {
|
|
13087
14169
|
const value = await invoke(endpoint, { botId: account.botId, ...payload });
|
|
13088
14170
|
applySnapshot(value);
|
|
13089
14171
|
}, [account.botId, applySnapshot, invoke]);
|
|
13090
|
-
const startAuthorization =
|
|
14172
|
+
const startAuthorization = React24.useCallback(async ({ replace = false } = {}) => {
|
|
13091
14173
|
if (provisionBusy) return;
|
|
13092
14174
|
const previousAttemptId = provision?.attemptId;
|
|
13093
14175
|
setProvisionBusy(true);
|
|
@@ -13106,13 +14188,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13106
14188
|
if (normalized.operation !== GROUP_MESSAGE_PERMISSION_OPERATION2 || normalized.botId !== account.botId) {
|
|
13107
14189
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801");
|
|
13108
14190
|
}
|
|
13109
|
-
const
|
|
14191
|
+
const timestamp8 = Date.now();
|
|
13110
14192
|
if (!mounted.current) return;
|
|
13111
|
-
setNow(
|
|
14193
|
+
setNow(timestamp8);
|
|
13112
14194
|
setProvision({
|
|
13113
14195
|
phase: normalized.submitted ? "connecting" : "qr",
|
|
13114
14196
|
...normalized,
|
|
13115
|
-
durationMs: Math.max(1, normalized.expiresAt -
|
|
14197
|
+
durationMs: Math.max(1, normalized.expiresAt - timestamp8),
|
|
13116
14198
|
expired: false
|
|
13117
14199
|
});
|
|
13118
14200
|
} catch (cause) {
|
|
@@ -13128,13 +14210,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13128
14210
|
if (mounted.current) setProvisionBusy(false);
|
|
13129
14211
|
}
|
|
13130
14212
|
}, [account.botId, invoke, provision?.attemptId, provisionBusy]);
|
|
13131
|
-
const finishAuthorization =
|
|
14213
|
+
const finishAuthorization = React24.useCallback(async (signal) => {
|
|
13132
14214
|
const bot = await loadSettings({ signal, restoreProvisioning: false });
|
|
13133
14215
|
if (signal?.aborted || !mounted.current) return;
|
|
13134
14216
|
if (!bot) throw new Error("\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001");
|
|
13135
14217
|
setProvision(null);
|
|
13136
14218
|
}, [loadSettings]);
|
|
13137
|
-
|
|
14219
|
+
React24.useEffect(() => {
|
|
13138
14220
|
if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
|
|
13139
14221
|
const timerHost = globalThis.window ?? globalThis;
|
|
13140
14222
|
const controller = new AbortController();
|
|
@@ -13178,13 +14260,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13178
14260
|
timerHost.clearTimeout(timer);
|
|
13179
14261
|
};
|
|
13180
14262
|
}, [account.botId, finishAuthorization, invoke, provision]);
|
|
13181
|
-
|
|
14263
|
+
React24.useEffect(() => {
|
|
13182
14264
|
if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
|
|
13183
14265
|
const timerHost = globalThis.window ?? globalThis;
|
|
13184
14266
|
const tick = () => {
|
|
13185
|
-
const
|
|
13186
|
-
setNow(
|
|
13187
|
-
if (
|
|
14267
|
+
const timestamp8 = Date.now();
|
|
14268
|
+
setNow(timestamp8);
|
|
14269
|
+
if (timestamp8 >= provision.expiresAt) {
|
|
13188
14270
|
setProvision((current) => current?.attemptId === provision.attemptId ? { ...current, expired: true } : current);
|
|
13189
14271
|
}
|
|
13190
14272
|
};
|
|
@@ -13192,7 +14274,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13192
14274
|
const timer = timerHost.setInterval(tick, 1e3);
|
|
13193
14275
|
return () => timerHost.clearInterval(timer);
|
|
13194
14276
|
}, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
|
|
13195
|
-
const cancelAuthorization =
|
|
14277
|
+
const cancelAuthorization = React24.useCallback(async () => {
|
|
13196
14278
|
if (!provision?.attemptId || provisionBusy) {
|
|
13197
14279
|
setProvision(null);
|
|
13198
14280
|
return;
|
|
@@ -13336,6 +14418,13 @@ var CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
13336
14418
|
group: [{ key: "chatId", label: "\u7FA4 Chat ID", placeholder: "\u586B\u5199\u7FA4 chatid" }]
|
|
13337
14419
|
}
|
|
13338
14420
|
},
|
|
14421
|
+
wecomApp: {
|
|
14422
|
+
label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528",
|
|
14423
|
+
kinds: [{ value: "user", label: "\u79C1\u804A" }],
|
|
14424
|
+
fields: {
|
|
14425
|
+
user: [{ key: "chatId", label: "\u7528\u6237 ID", placeholder: "\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID" }]
|
|
14426
|
+
}
|
|
14427
|
+
},
|
|
13339
14428
|
qq: {
|
|
13340
14429
|
label: "QQ",
|
|
13341
14430
|
kinds: [{ value: "user", label: "\u5355\u804A" }, { value: "group", label: "\u7FA4\u804A" }],
|
|
@@ -13380,10 +14469,10 @@ var CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
13380
14469
|
}
|
|
13381
14470
|
}
|
|
13382
14471
|
});
|
|
13383
|
-
function
|
|
14472
|
+
function presentError11(error, fallback) {
|
|
13384
14473
|
return error?.message || fallback;
|
|
13385
14474
|
}
|
|
13386
|
-
function
|
|
14475
|
+
function unwrapRpcResult12(result) {
|
|
13387
14476
|
if (result?.ok === true) return result.value;
|
|
13388
14477
|
if (result?.ok === false) {
|
|
13389
14478
|
const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -13435,18 +14524,18 @@ function validSuggestions(definition, value) {
|
|
|
13435
14524
|
});
|
|
13436
14525
|
}
|
|
13437
14526
|
function maskRouteValue(value) {
|
|
13438
|
-
const
|
|
13439
|
-
if (!
|
|
13440
|
-
const at =
|
|
14527
|
+
const text7 = String(value ?? "").trim();
|
|
14528
|
+
if (!text7) return "";
|
|
14529
|
+
const at = text7.indexOf("@");
|
|
13441
14530
|
if (at > 0) {
|
|
13442
|
-
const local =
|
|
13443
|
-
const domain =
|
|
14531
|
+
const local = text7.slice(0, at);
|
|
14532
|
+
const domain = text7.slice(at);
|
|
13444
14533
|
const visible = local.length <= 4 ? `${local.slice(0, 1)}\u2022\u2022${local.slice(-1)}` : `${local.slice(0, 3)}\u2026${local.slice(-2)}`;
|
|
13445
14534
|
return `${visible}${domain}`;
|
|
13446
14535
|
}
|
|
13447
|
-
if (
|
|
13448
|
-
if (
|
|
13449
|
-
return `${
|
|
14536
|
+
if (text7.length <= 6) return `${text7.slice(0, 2)}\u2026${text7.slice(-1)}`;
|
|
14537
|
+
if (text7.length <= 12) return `${text7.slice(0, 3)}\u2026${text7.slice(-3)}`;
|
|
14538
|
+
return `${text7.slice(0, 5)}\u2026${text7.slice(-4)}`;
|
|
13450
14539
|
}
|
|
13451
14540
|
function suggestionFallbackName(definition, suggestion) {
|
|
13452
14541
|
const displayName = suggestionDisplayName(suggestion);
|
|
@@ -13501,13 +14590,13 @@ function TargetForm({
|
|
|
13501
14590
|
}) {
|
|
13502
14591
|
const editing = mode === "edit";
|
|
13503
14592
|
const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
|
|
13504
|
-
const [targetId, setTargetId] =
|
|
13505
|
-
const [name2, setName] =
|
|
13506
|
-
const [kind, setKind] =
|
|
13507
|
-
const [route, setRoute] =
|
|
13508
|
-
const [error, setError] =
|
|
13509
|
-
const [testing, setTesting] =
|
|
13510
|
-
const [testState, setTestState] =
|
|
14593
|
+
const [targetId, setTargetId] = React25.useState(initialValue?.targetId ?? "");
|
|
14594
|
+
const [name2, setName] = React25.useState(initialValue?.name ?? "");
|
|
14595
|
+
const [kind, setKind] = React25.useState(initialKind);
|
|
14596
|
+
const [route, setRoute] = React25.useState(initialValue?.route ?? {});
|
|
14597
|
+
const [error, setError] = React25.useState(null);
|
|
14598
|
+
const [testing, setTesting] = React25.useState(false);
|
|
14599
|
+
const [testState, setTestState] = React25.useState(null);
|
|
13511
14600
|
const currentTarget = () => {
|
|
13512
14601
|
const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
|
|
13513
14602
|
const raw = String(route[field.key] ?? "").trim();
|
|
@@ -13528,7 +14617,7 @@ function TargetForm({
|
|
|
13528
14617
|
...currentTarget()
|
|
13529
14618
|
});
|
|
13530
14619
|
} catch (caught) {
|
|
13531
|
-
setError(
|
|
14620
|
+
setError(presentError11(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
|
|
13532
14621
|
}
|
|
13533
14622
|
};
|
|
13534
14623
|
const testTarget = async () => {
|
|
@@ -13540,7 +14629,7 @@ function TargetForm({
|
|
|
13540
14629
|
await onTest({ kind: target.kind, route: target.route });
|
|
13541
14630
|
setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
|
|
13542
14631
|
} catch (caught) {
|
|
13543
|
-
setTestState({ tone: "error", message:
|
|
14632
|
+
setTestState({ tone: "error", message: presentError11(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13544
14633
|
} finally {
|
|
13545
14634
|
setTesting(false);
|
|
13546
14635
|
}
|
|
@@ -13724,7 +14813,7 @@ function TargetSuggestionPicker({
|
|
|
13724
14813
|
suggestions.map((suggestion, index) => {
|
|
13725
14814
|
const identity = routeIdentity(definition, suggestion);
|
|
13726
14815
|
const added = configured.has(identity);
|
|
13727
|
-
return
|
|
14816
|
+
return React25.createElement("option", {
|
|
13728
14817
|
key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
|
|
13729
14818
|
value: String(index),
|
|
13730
14819
|
disabled: added
|
|
@@ -13741,11 +14830,11 @@ function TargetSuggestionPicker({
|
|
|
13741
14830
|
);
|
|
13742
14831
|
}
|
|
13743
14832
|
function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
|
|
13744
|
-
const [action, setAction] =
|
|
13745
|
-
const [testState, setTestState] =
|
|
13746
|
-
const [syncFeedback, setSyncFeedback] =
|
|
13747
|
-
const [copyState, setCopyState] =
|
|
13748
|
-
const [confirmDelete, setConfirmDelete] =
|
|
14833
|
+
const [action, setAction] = React25.useState(null);
|
|
14834
|
+
const [testState, setTestState] = React25.useState(null);
|
|
14835
|
+
const [syncFeedback, setSyncFeedback] = React25.useState(null);
|
|
14836
|
+
const [copyState, setCopyState] = React25.useState(null);
|
|
14837
|
+
const [confirmDelete, setConfirmDelete] = React25.useState(false);
|
|
13749
14838
|
const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
|
|
13750
14839
|
const syncDescription = sessionSync.state === "active" ? "\u81EA\u52A8\u8DDF\u968F\u8BE5\u79C1\u804A\u7684\u5F53\u524D\u4F1A\u8BDD" : sessionSync.state === "waiting" ? "\u7B49\u5F85\u8BE5\u79C1\u804A\u5EFA\u7ACB\u65B0\u4F1A\u8BDD" : sessionSync.state === "unavailable" ? "\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807" : "\u5173\u95ED\u65F6\u4E0D\u53D1\u9001 DSH \u4F1A\u8BDD\u6D88\u606F";
|
|
13751
14840
|
const testTarget = async () => {
|
|
@@ -13755,7 +14844,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13755
14844
|
await rpcCall(DELIVERY_ENDPOINTS.test, { botId, targetId: target.targetId });
|
|
13756
14845
|
setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
|
|
13757
14846
|
} catch (error) {
|
|
13758
|
-
setTestState({ tone: "error", message:
|
|
14847
|
+
setTestState({ tone: "error", message: presentError11(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13759
14848
|
} finally {
|
|
13760
14849
|
setAction(null);
|
|
13761
14850
|
}
|
|
@@ -13766,7 +14855,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13766
14855
|
await copyText(JSON.stringify({ botId, targetId: target.targetId }));
|
|
13767
14856
|
setCopyState("\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570");
|
|
13768
14857
|
} catch (error) {
|
|
13769
|
-
setCopyState(
|
|
14858
|
+
setCopyState(presentError11(error, "\u590D\u5236\u5931\u8D25\u3002"));
|
|
13770
14859
|
}
|
|
13771
14860
|
};
|
|
13772
14861
|
const deleteTarget = async () => {
|
|
@@ -13775,7 +14864,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13775
14864
|
await rpcCall(DELIVERY_ENDPOINTS.delete, { botId, targetId: target.targetId });
|
|
13776
14865
|
await onChanged();
|
|
13777
14866
|
} catch (error) {
|
|
13778
|
-
setTestState({ tone: "error", message:
|
|
14867
|
+
setTestState({ tone: "error", message: presentError11(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13779
14868
|
setAction(null);
|
|
13780
14869
|
setConfirmDelete(false);
|
|
13781
14870
|
}
|
|
@@ -13793,7 +14882,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13793
14882
|
} catch (error) {
|
|
13794
14883
|
setSyncFeedback({
|
|
13795
14884
|
tone: "error",
|
|
13796
|
-
message: error?.code === "session-sync-unavailable" ? "\u4F1A\u8BDD\u540C\u6B65\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807\u3002" :
|
|
14885
|
+
message: error?.code === "session-sync-unavailable" ? "\u4F1A\u8BDD\u540C\u6B65\u4EC5\u652F\u6301\u5DF2\u7ECF\u804A\u8FC7\u3001\u5DF2\u5EFA\u7ACB\u5F53\u524D\u4F1A\u8BDD\u4E14\u4F7F\u7528\u5F53\u524D Host Harness \u7684\u79C1\u804A\u76EE\u6807\u3002" : presentError11(error, "\u4F1A\u8BDD\u540C\u6B65\u8BBE\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")
|
|
13797
14886
|
});
|
|
13798
14887
|
} finally {
|
|
13799
14888
|
setAction(null);
|
|
@@ -13808,7 +14897,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13808
14897
|
h2(
|
|
13809
14898
|
"div",
|
|
13810
14899
|
{ className: "dim-targetTitle" },
|
|
13811
|
-
|
|
14900
|
+
React25.createElement("strong", null, target.name || target.targetId),
|
|
13812
14901
|
h2("span", null, kindLabel(definition, target.kind))
|
|
13813
14902
|
),
|
|
13814
14903
|
h2("code", null, `targetId: ${target.targetId}`)
|
|
@@ -13894,26 +14983,26 @@ function DeliveryTargetSettingsPage({
|
|
|
13894
14983
|
onBack
|
|
13895
14984
|
}) {
|
|
13896
14985
|
const definition = CHANNEL_DEFINITIONS[channel4];
|
|
13897
|
-
const [activeTabId, setActiveTabId] =
|
|
13898
|
-
const [phase, setPhase] =
|
|
13899
|
-
const [targets, setTargets] =
|
|
13900
|
-
const [suggestionPhase, setSuggestionPhase] =
|
|
13901
|
-
const [suggestions, setSuggestions] =
|
|
13902
|
-
const [suggestionError, setSuggestionError] =
|
|
13903
|
-
const [error, setError] =
|
|
13904
|
-
const [editor, setEditor] =
|
|
13905
|
-
const [saving, setSaving] =
|
|
13906
|
-
const [botCopyState, setBotCopyState] =
|
|
13907
|
-
const [accessPolicy, setAccessPolicy] =
|
|
13908
|
-
const mounted =
|
|
13909
|
-
|
|
14986
|
+
const [activeTabId, setActiveTabId] = React25.useState(BOT_SETTINGS_TABS[0].id);
|
|
14987
|
+
const [phase, setPhase] = React25.useState("loading");
|
|
14988
|
+
const [targets, setTargets] = React25.useState([]);
|
|
14989
|
+
const [suggestionPhase, setSuggestionPhase] = React25.useState("idle");
|
|
14990
|
+
const [suggestions, setSuggestions] = React25.useState([]);
|
|
14991
|
+
const [suggestionError, setSuggestionError] = React25.useState(null);
|
|
14992
|
+
const [error, setError] = React25.useState(null);
|
|
14993
|
+
const [editor, setEditor] = React25.useState(null);
|
|
14994
|
+
const [saving, setSaving] = React25.useState(false);
|
|
14995
|
+
const [botCopyState, setBotCopyState] = React25.useState(null);
|
|
14996
|
+
const [accessPolicy, setAccessPolicy] = React25.useState(account.accessPolicy);
|
|
14997
|
+
const mounted = React25.useRef(true);
|
|
14998
|
+
React25.useEffect(() => {
|
|
13910
14999
|
setAccessPolicy(account.accessPolicy);
|
|
13911
15000
|
}, [account.botId, account.accessPolicy]);
|
|
13912
|
-
const invoke =
|
|
15001
|
+
const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
|
|
13913
15002
|
if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
13914
|
-
return
|
|
15003
|
+
return unwrapRpcResult12(await rpcCall(endpoint, payload, signal));
|
|
13915
15004
|
}, [rpcCall]);
|
|
13916
|
-
const loadTargets =
|
|
15005
|
+
const loadTargets = React25.useCallback(async ({ signal, silent = false } = {}) => {
|
|
13917
15006
|
if (!silent) setPhase("loading");
|
|
13918
15007
|
setError(null);
|
|
13919
15008
|
try {
|
|
@@ -13923,11 +15012,11 @@ function DeliveryTargetSettingsPage({
|
|
|
13923
15012
|
setPhase("ready");
|
|
13924
15013
|
} catch (caught) {
|
|
13925
15014
|
if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
|
|
13926
|
-
setError(
|
|
15015
|
+
setError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
13927
15016
|
setPhase("error");
|
|
13928
15017
|
}
|
|
13929
15018
|
}, [account.botId, invoke]);
|
|
13930
|
-
const loadSuggestions =
|
|
15019
|
+
const loadSuggestions = React25.useCallback(async () => {
|
|
13931
15020
|
setSuggestionPhase("loading");
|
|
13932
15021
|
setSuggestionError(null);
|
|
13933
15022
|
try {
|
|
@@ -13937,11 +15026,11 @@ function DeliveryTargetSettingsPage({
|
|
|
13937
15026
|
setSuggestionPhase("ready");
|
|
13938
15027
|
} catch (caught) {
|
|
13939
15028
|
if (caught?.name === "AbortError" || !mounted.current) return;
|
|
13940
|
-
setSuggestionError(
|
|
15029
|
+
setSuggestionError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
13941
15030
|
setSuggestionPhase("error");
|
|
13942
15031
|
}
|
|
13943
15032
|
}, [account.botId, definition, invoke]);
|
|
13944
|
-
|
|
15033
|
+
React25.useEffect(() => {
|
|
13945
15034
|
mounted.current = true;
|
|
13946
15035
|
const controller = new AbortController();
|
|
13947
15036
|
void loadTargets({ signal: controller.signal });
|
|
@@ -14009,7 +15098,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14009
15098
|
await copyText(account.botId);
|
|
14010
15099
|
setBotCopyState("\u5DF2\u590D\u5236 Bot ID");
|
|
14011
15100
|
} catch (caught) {
|
|
14012
|
-
setBotCopyState(
|
|
15101
|
+
setBotCopyState(presentError11(caught, "\u590D\u5236\u5931\u8D25\u3002"));
|
|
14013
15102
|
}
|
|
14014
15103
|
};
|
|
14015
15104
|
const settingsTabs = botSettingsTabsForChannel(channel4);
|
|
@@ -14063,7 +15152,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14063
15152
|
account,
|
|
14064
15153
|
rpcCall: accessRpcCall
|
|
14065
15154
|
}) : h2(
|
|
14066
|
-
|
|
15155
|
+
React25.Fragment,
|
|
14067
15156
|
null,
|
|
14068
15157
|
h2(
|
|
14069
15158
|
"section",
|
|
@@ -14174,7 +15263,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14174
15263
|
}
|
|
14175
15264
|
|
|
14176
15265
|
// plugin-src/client/global-settings.js
|
|
14177
|
-
var
|
|
15266
|
+
var React26 = __toESM(require("react"), 1);
|
|
14178
15267
|
|
|
14179
15268
|
// src/channels/shared/inbound-ttl.mjs
|
|
14180
15269
|
var DEFAULT_INBOUND_TTL_HOURS = 168;
|
|
@@ -14203,10 +15292,10 @@ var GLOBAL_SETTINGS_ENDPOINTS = Object.freeze({
|
|
|
14203
15292
|
setTtl: "settings.inbound-ttl.set",
|
|
14204
15293
|
sweep: "settings.inbound-ttl.sweep"
|
|
14205
15294
|
});
|
|
14206
|
-
function
|
|
15295
|
+
function presentError12(error, fallback) {
|
|
14207
15296
|
return error?.message || fallback;
|
|
14208
15297
|
}
|
|
14209
|
-
function
|
|
15298
|
+
function unwrapRpcResult13(result) {
|
|
14210
15299
|
if (result?.ok === true) return result.value;
|
|
14211
15300
|
if (result?.ok === false) {
|
|
14212
15301
|
const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -14236,29 +15325,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
|
|
|
14236
15325
|
}, children);
|
|
14237
15326
|
}
|
|
14238
15327
|
function GlobalSettingsPanel({ rpcCall }) {
|
|
14239
|
-
const [phase, setPhase] =
|
|
14240
|
-
const [loadError, setLoadError] =
|
|
14241
|
-
const [ttlInput, setTtlInput] =
|
|
14242
|
-
const [savedTtl, setSavedTtl] =
|
|
14243
|
-
const [ttlError, setTtlError] =
|
|
14244
|
-
const [saveError, setSaveError] =
|
|
14245
|
-
const [saveSucceeded, setSaveSucceeded] =
|
|
14246
|
-
const [isSaving, setIsSaving] =
|
|
14247
|
-
const [sweepConfirming, setSweepConfirming] =
|
|
14248
|
-
const [sweeping, setSweeping] =
|
|
14249
|
-
const ttlErrorId =
|
|
14250
|
-
const ttlHintsId =
|
|
14251
|
-
const sweepTriggerId =
|
|
14252
|
-
const sweepConfirmId =
|
|
14253
|
-
const sweepConfirmTextId =
|
|
14254
|
-
const sweepConfirmButtonId =
|
|
14255
|
-
const mounted =
|
|
14256
|
-
const saving =
|
|
14257
|
-
const invoke =
|
|
15328
|
+
const [phase, setPhase] = React26.useState("loading");
|
|
15329
|
+
const [loadError, setLoadError] = React26.useState(null);
|
|
15330
|
+
const [ttlInput, setTtlInput] = React26.useState("");
|
|
15331
|
+
const [savedTtl, setSavedTtl] = React26.useState(null);
|
|
15332
|
+
const [ttlError, setTtlError] = React26.useState(false);
|
|
15333
|
+
const [saveError, setSaveError] = React26.useState(null);
|
|
15334
|
+
const [saveSucceeded, setSaveSucceeded] = React26.useState(false);
|
|
15335
|
+
const [isSaving, setIsSaving] = React26.useState(false);
|
|
15336
|
+
const [sweepConfirming, setSweepConfirming] = React26.useState(false);
|
|
15337
|
+
const [sweeping, setSweeping] = React26.useState(false);
|
|
15338
|
+
const ttlErrorId = React26.useId();
|
|
15339
|
+
const ttlHintsId = React26.useId();
|
|
15340
|
+
const sweepTriggerId = React26.useId();
|
|
15341
|
+
const sweepConfirmId = React26.useId();
|
|
15342
|
+
const sweepConfirmTextId = React26.useId();
|
|
15343
|
+
const sweepConfirmButtonId = React26.useId();
|
|
15344
|
+
const mounted = React26.useRef(true);
|
|
15345
|
+
const saving = React26.useRef(false);
|
|
15346
|
+
const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
|
|
14258
15347
|
if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
14259
|
-
return
|
|
15348
|
+
return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
|
|
14260
15349
|
}, [rpcCall]);
|
|
14261
|
-
const loadSettings =
|
|
15350
|
+
const loadSettings = React26.useCallback(async ({ signal } = {}) => {
|
|
14262
15351
|
setPhase("loading");
|
|
14263
15352
|
setLoadError(null);
|
|
14264
15353
|
try {
|
|
@@ -14278,11 +15367,11 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14278
15367
|
setPhase("ready");
|
|
14279
15368
|
} catch (caught) {
|
|
14280
15369
|
if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
|
|
14281
|
-
setLoadError(
|
|
15370
|
+
setLoadError(presentError12(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
14282
15371
|
setPhase("error");
|
|
14283
15372
|
}
|
|
14284
15373
|
}, [invoke]);
|
|
14285
|
-
|
|
15374
|
+
React26.useEffect(() => {
|
|
14286
15375
|
mounted.current = true;
|
|
14287
15376
|
const controller = new AbortController();
|
|
14288
15377
|
void loadSettings({ signal: controller.signal });
|
|
@@ -14291,7 +15380,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14291
15380
|
controller.abort();
|
|
14292
15381
|
};
|
|
14293
15382
|
}, [loadSettings]);
|
|
14294
|
-
|
|
15383
|
+
React26.useEffect(() => {
|
|
14295
15384
|
if (!sweepConfirming) return;
|
|
14296
15385
|
globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
|
|
14297
15386
|
}, [sweepConfirmButtonId, sweepConfirming]);
|
|
@@ -14322,7 +15411,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14322
15411
|
setPhase("ready");
|
|
14323
15412
|
} catch (caught) {
|
|
14324
15413
|
if (mounted.current) {
|
|
14325
|
-
setSaveError(
|
|
15414
|
+
setSaveError(presentError12(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
14326
15415
|
}
|
|
14327
15416
|
} finally {
|
|
14328
15417
|
saving.current = false;
|
|
@@ -14598,7 +15687,7 @@ function replacePageLocation(url, location = globalThis.location) {
|
|
|
14598
15687
|
|
|
14599
15688
|
// plugin-src/client/styles.js
|
|
14600
15689
|
var IM_STYLE_ID = "xmanrui-dsh-im-settings";
|
|
14601
|
-
var
|
|
15690
|
+
var CSS12 = String.raw`
|
|
14602
15691
|
.dim-page {
|
|
14603
15692
|
--dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
|
|
14604
15693
|
--dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
|
|
@@ -14669,9 +15758,7 @@ var CSS11 = String.raw`
|
|
|
14669
15758
|
.dim-generalSettingsAction:hover .dim-generalSettingsTooltip, .dim-generalSettingsButton:focus-visible + .dim-generalSettingsTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
|
14670
15759
|
.dim-generalSettingsButton[aria-current="page"] + .dim-generalSettingsTooltip { opacity: 0; visibility: hidden; transform: translateY(-3px); }
|
|
14671
15760
|
.dim-layout { display: grid; grid-template-columns: 174px 1px minmax(0, 1fr); gap: 24px; align-items: start; }
|
|
14672
|
-
.dim-rail {
|
|
14673
|
-
.dim-rail::-webkit-scrollbar { width: 4px; }
|
|
14674
|
-
.dim-rail::-webkit-scrollbar-thumb { border-radius: 99px; background: var(--dsw-alias-border-l2, #dfe1e5); }
|
|
15761
|
+
.dim-rail { display: grid; align-content: start; gap: 8px; padding: 0 4px 1px 1px; }
|
|
14675
15762
|
.dim-channel { width: 100%; min-height: 48px; display: grid; grid-template-columns: 30px minmax(0, 1fr); align-items: center; gap: 10px; padding: 8px 12px; border: 1px solid var(--dsw-alias-border-l2, #eef0f3); border-radius: 14px; color: inherit; background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 2px 8px rgb(31 35 41 / 3%); font: inherit; text-align: left; cursor: pointer; transition: border-color .16s ease, background .16s ease, box-shadow .16s ease; }
|
|
14676
15763
|
.dim-channel:hover { border-color: color-mix(in srgb, var(--dim-blue) 25%, var(--dsw-alias-border-l2, #eef0f3)); background: color-mix(in srgb, var(--dim-blue) 2%, var(--dsw-alias-bg-layer-3, #fff)); box-shadow: 0 5px 16px rgb(31 35 41 / 5%); }
|
|
14677
15764
|
.dim-channel[aria-selected="true"] { border-color: color-mix(in srgb, var(--dim-blue) 43%, var(--dsw-alias-border-l2, #dfe1e5)); color: var(--dim-blue); background: color-mix(in srgb, var(--dim-blue) 12%, var(--dsw-alias-bg-layer-3, #fff)); box-shadow: 0 3px 12px rgb(51 112 255 / 7%); }
|
|
@@ -14701,7 +15788,7 @@ var CSS11 = String.raw`
|
|
|
14701
15788
|
.dim-channelCopy { min-width: 0; display: grid; }
|
|
14702
15789
|
.dim-channelCopy strong { overflow: hidden; color: inherit; font-size: 14px; line-height: 20px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
|
|
14703
15790
|
.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; }
|
|
14704
|
-
.dim-divider { width: 1px;
|
|
15791
|
+
.dim-divider { width: 1px; align-self: stretch; background: var(--dsw-alias-border-l1, #eef0f3); }
|
|
14705
15792
|
.dim-panel { min-width: 0; container-type: inline-size; }
|
|
14706
15793
|
.dim-loopbackRecovery { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 14px; padding: 14px 16px; border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #d97706) 30%, var(--dsw-alias-border-l2, #dfe1e5)); border-radius: 12px; color: var(--dsw-alias-label-primary, #1f2329); background: color-mix(in srgb, var(--dsw-alias-state-warn-primary, #d97706) 8%, var(--dsw-alias-bg-layer-1, #fff)); }
|
|
14707
15794
|
.dim-loopbackRecoveryCopy { min-width: 0; }
|
|
@@ -14817,6 +15904,24 @@ var CSS11 = String.raw`
|
|
|
14817
15904
|
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
14818
15905
|
.dim-panel .dim-presetSelect { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; height: 30px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 12px; }
|
|
14819
15906
|
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
15907
|
+
.dim-panel .dim-modelSetting { display: block; padding: 8px 4px 4px; }
|
|
15908
|
+
.dim-modelSetting > .dim-presetHeader { padding: 0 6px 6px; }
|
|
15909
|
+
.dim-modelRow { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; padding: 6px 10px; border: 0; border-radius: 10px; background: transparent; color: var(--dsw-alias-label-primary, #1f2329); font: inherit; font-size: 14px; line-height: 22px; text-align: left; cursor: pointer; }
|
|
15910
|
+
.dim-modelRowLabel { flex: none; }
|
|
15911
|
+
.dim-modelValue { flex: 1; min-width: 0; overflow: hidden; color: var(--dsw-alias-label-tertiary, #81858c); text-overflow: ellipsis; white-space: nowrap; text-align: right; }
|
|
15912
|
+
.dim-modelChevron { flex: none; color: var(--dsw-alias-label-tertiary, #81858c); }
|
|
15913
|
+
.dim-modelRow:hover:not(:disabled), .dim-modelOption:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eceef1); }
|
|
15914
|
+
.dim-modelRow:focus-visible, .dim-modelOption:focus-visible { outline: 2px solid var(--dsw-alias-border-l3, #1677ff); outline-offset: -2px; }
|
|
15915
|
+
.dim-modelRow:disabled, .dim-modelOption:disabled { opacity: .55; cursor: default; }
|
|
15916
|
+
/* In-flow lists avoid clipping by collapsed-card and settings scroll containers. */
|
|
15917
|
+
.dim-modelMenu { max-height: 280px; overflow-y: auto; margin: 4px; padding: 4px; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 12px; background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3, #fff)); color: var(--dsw-alias-label-primary, #1f2329); scrollbar-width: thin; }
|
|
15918
|
+
.dim-modelGroupTitle { padding: 7px 8px 3px; color: var(--dsw-alias-label-tertiary, #81858c); font-size: 12px; line-height: 18px; font-weight: 500; }
|
|
15919
|
+
.dim-modelOption { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 38px; padding: 6px 8px; border: 0; border-radius: 10px; background: transparent; color: inherit; text-align: left; font: inherit; cursor: pointer; }
|
|
15920
|
+
.dim-modelOptionCopy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
|
|
15921
|
+
.dim-modelOptionName { font-size: 14px; line-height: 20px; font-weight: 500; overflow-wrap: anywhere; }
|
|
15922
|
+
.dim-modelDescription { color: var(--dsw-alias-label-tertiary, #81858c); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
|
|
15923
|
+
.dim-modelCheck { flex: 0 0 18px; text-align: center; }
|
|
15924
|
+
.dim-modelHint { margin: 4px 10px 6px; color: var(--dsw-alias-label-tertiary, #81858c); font-size: 11px; line-height: 17px; }
|
|
14820
15925
|
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 3; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
|
14821
15926
|
.dim-contextEntry { width: 100%; min-height: 40px; display: grid; grid-template-columns: 16px minmax(0, 1fr) max-content 16px; align-items: center; gap: 9px; margin: 10px 0; padding: 8px 11px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-module-platform, #f7f8fa); font: inherit; font-size: 13px; line-height: 20px; text-align: left; cursor: pointer; }
|
|
14822
15927
|
.dim-contextEntry:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
|
|
@@ -15004,7 +16109,7 @@ var CSS11 = String.raw`
|
|
|
15004
16109
|
.dim-feishuGroupSettings { min-width: 0; display: grid; gap: 14px; }
|
|
15005
16110
|
.dim-feishuGroupControls { min-width: 0; display: grid; gap: 12px; }
|
|
15006
16111
|
.dim-feishuGroupControl { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 16px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 12px; background: var(--dsw-alias-bg-layer-3, #fff); }
|
|
15007
|
-
.dim-feishuGroupControlHeader { min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
16112
|
+
.dim-feishuGroupControlHeader { position: relative; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
15008
16113
|
.dim-feishuGroupControlHeader h3 { min-width: 0; margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 21px; font-weight: 650; }
|
|
15009
16114
|
.dim-feishuGroupControlStatus { flex: none; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 17px; }
|
|
15010
16115
|
.dim-feishuGroupSelect { min-width: 0; width: 100%; height: 38px; padding: 0 34px 0 11px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 13px; line-height: 38px; cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease; }
|
|
@@ -15206,9 +16311,8 @@ var CSS11 = String.raw`
|
|
|
15206
16311
|
@media (max-width: 840px) {
|
|
15207
16312
|
.dim-title { align-items: flex-start; }
|
|
15208
16313
|
.dim-layout { grid-template-columns: minmax(0, 1fr); gap: 18px; }
|
|
15209
|
-
.dim-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
16314
|
+
.dim-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); padding-right: 1px; }
|
|
15210
16315
|
.dim-divider { display: none; }
|
|
15211
|
-
.dim-rail { max-height: none; overflow: visible; padding-right: 1px; }
|
|
15212
16316
|
.dim-channel { min-height: 48px; }
|
|
15213
16317
|
}
|
|
15214
16318
|
@media (max-width: 560px) {
|
|
@@ -15256,13 +16360,261 @@ function installImStyles() {
|
|
|
15256
16360
|
const style = document.createElement("style");
|
|
15257
16361
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
15258
16362
|
style.dataset.pluginCss = IM_STYLE_ID;
|
|
15259
|
-
style.textContent =
|
|
16363
|
+
style.textContent = CSS12;
|
|
15260
16364
|
document.head.appendChild(style);
|
|
15261
16365
|
return () => style.remove();
|
|
15262
16366
|
}
|
|
15263
16367
|
|
|
16368
|
+
// src/channels/shared/session-channel-labels.mjs
|
|
16369
|
+
var SESSION_CHANNEL_LABELS = Object.freeze(Object.fromEntries(Object.entries({
|
|
16370
|
+
weixin: ["\u5FAE\u4FE1", "WeChat"],
|
|
16371
|
+
feishu: ["\u98DE\u4E66", "Feishu"],
|
|
16372
|
+
dingtalk: ["\u9489\u9489", "DingTalk"],
|
|
16373
|
+
wecom: ["\u4F01\u4E1A\u5FAE\u4FE1", "WeCom"],
|
|
16374
|
+
qq: ["QQ", "QQ"],
|
|
16375
|
+
slack: ["Slack", "Slack"],
|
|
16376
|
+
telegram: ["Telegram", "Telegram"],
|
|
16377
|
+
discord: ["Discord", "Discord"],
|
|
16378
|
+
whatsapp: ["WhatsApp", "WhatsApp"],
|
|
16379
|
+
office: ["AI Office", "AI Office"]
|
|
16380
|
+
}).map(([channel4, labels]) => [channel4, Object.freeze(labels)])));
|
|
16381
|
+
function parseSessionChannelTitle(title) {
|
|
16382
|
+
if (typeof title !== "string") return null;
|
|
16383
|
+
for (const [channel4, labels] of Object.entries(SESSION_CHANNEL_LABELS)) {
|
|
16384
|
+
for (const label of labels) {
|
|
16385
|
+
const prefix = `${label} \xB7 `;
|
|
16386
|
+
if (title.startsWith(prefix) && title.slice(prefix.length).trim()) {
|
|
16387
|
+
return { channel: channel4, title: title.slice(prefix.length) };
|
|
16388
|
+
}
|
|
16389
|
+
}
|
|
16390
|
+
}
|
|
16391
|
+
return null;
|
|
16392
|
+
}
|
|
16393
|
+
|
|
16394
|
+
// plugin-src/client/session-channel-logos.js
|
|
16395
|
+
var GLYPHS = Object.freeze({
|
|
16396
|
+
weixin: [WeixinLogoGlyph, "#07c160"],
|
|
16397
|
+
feishu: [FeishuLogoGlyph, "#3370ff"],
|
|
16398
|
+
dingtalk: [DingtalkLogoGlyph, "#1677ff"],
|
|
16399
|
+
wecom: [WecomLogoGlyph, "#3370ff"],
|
|
16400
|
+
qq: [QqLogoGlyph, "#12b7f5"],
|
|
16401
|
+
slack: [SlackLogoGlyph, "#e01e5a"],
|
|
16402
|
+
telegram: [TelegramLogoGlyph, "#229ed9"],
|
|
16403
|
+
discord: [DiscordLogoGlyph, "#5865f2"],
|
|
16404
|
+
whatsapp: [WhatsappLogoGlyph, "#25d366"],
|
|
16405
|
+
office: [OfficeLogoGlyph, "#f97316"]
|
|
16406
|
+
});
|
|
16407
|
+
var CHANNEL_ATTR = "data-dsh-im-session-channel";
|
|
16408
|
+
var TITLE_ATTR = "data-dsh-im-session-text";
|
|
16409
|
+
var MARKED = `[${CHANNEL_ATTR}]`;
|
|
16410
|
+
var ROW = '[role="treeitem"][aria-selected]';
|
|
16411
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
16412
|
+
var installations = /* @__PURE__ */ new WeakMap();
|
|
16413
|
+
function hasClassPart(element, part) {
|
|
16414
|
+
const match = new RegExp(`(?:^|[_-])${part}(?:$|[_-])`, "u");
|
|
16415
|
+
return [...element.classList].some((token) => match.test(token));
|
|
16416
|
+
}
|
|
16417
|
+
function titleOf(row) {
|
|
16418
|
+
if (!row.matches(ROW) || row.closest('input, textarea, [contenteditable]:not([contenteditable="false"])')) return null;
|
|
16419
|
+
let title;
|
|
16420
|
+
if (row.tagName === "DIV" && hasClassPart(row, "sessionRow")) {
|
|
16421
|
+
title = [...row.children].find((child) => child.tagName === "SPAN" && hasClassPart(child, "title"));
|
|
16422
|
+
} else if (row.tagName === "BUTTON" && hasClassPart(row, "searchResultRow")) {
|
|
16423
|
+
const heading = [...row.children].find((child) => hasClassPart(child, "searchResultHeading"));
|
|
16424
|
+
title = heading && [...heading.children].find((child) => child.tagName === "SPAN" && hasClassPart(child, "searchResultTitle"));
|
|
16425
|
+
}
|
|
16426
|
+
return title?.childNodes.length === 1 && title.firstChild.nodeType === 3 ? title : null;
|
|
16427
|
+
}
|
|
16428
|
+
function logoUri(document2, channel4) {
|
|
16429
|
+
const [Glyph, color] = GLYPHS[channel4];
|
|
16430
|
+
const render = (node) => {
|
|
16431
|
+
if (!["svg", "path"].includes(node.type)) throw new Error("Unsupported channel logo element");
|
|
16432
|
+
const element = document2.createElementNS(SVG_NS, node.type);
|
|
16433
|
+
for (const [name2, value] of Object.entries(node.props)) {
|
|
16434
|
+
if (name2 === "children") continue;
|
|
16435
|
+
const attribute = name2.startsWith("stroke") ? name2.replace(/[A-Z]/gu, (letter) => `-${letter.toLowerCase()}`) : name2;
|
|
16436
|
+
element.setAttribute(attribute, String(value));
|
|
16437
|
+
}
|
|
16438
|
+
for (const child of [node.props.children].flat().filter(Boolean)) element.appendChild(render(child));
|
|
16439
|
+
return element;
|
|
16440
|
+
};
|
|
16441
|
+
const svg = render(Glyph({ size: 16 }));
|
|
16442
|
+
svg.setAttribute("xmlns", SVG_NS);
|
|
16443
|
+
svg.setAttribute("color", color);
|
|
16444
|
+
return `data:image/svg+xml,${encodeURIComponent(svg.outerHTML)}`;
|
|
16445
|
+
}
|
|
16446
|
+
function createInstallation(document2) {
|
|
16447
|
+
const view = document2.defaultView;
|
|
16448
|
+
const ready = /* @__PURE__ */ new Set();
|
|
16449
|
+
const owned = /* @__PURE__ */ new Map();
|
|
16450
|
+
const queued = /* @__PURE__ */ new Set();
|
|
16451
|
+
const images = [];
|
|
16452
|
+
let closed = false;
|
|
16453
|
+
let scheduled = false;
|
|
16454
|
+
const style = document2.createElement("style");
|
|
16455
|
+
style.dataset.pluginCss = "dsh-im-session-channel-logos";
|
|
16456
|
+
const uris = Object.fromEntries(Object.keys(GLYPHS).map((channel4) => [channel4, logoUri(document2, channel4)]));
|
|
16457
|
+
style.textContent = `
|
|
16458
|
+
${MARKED}[${TITLE_ATTR}] {
|
|
16459
|
+
position: relative;
|
|
16460
|
+
-webkit-text-fill-color: transparent;
|
|
16461
|
+
text-overflow: clip !important;
|
|
16462
|
+
overflow: hidden;
|
|
16463
|
+
}
|
|
16464
|
+
${MARKED}[${TITLE_ATTR}]::before {
|
|
16465
|
+
content: "";
|
|
16466
|
+
position: absolute;
|
|
16467
|
+
inset-inline-start: 0;
|
|
16468
|
+
top: 50%;
|
|
16469
|
+
transform: translateY(-50%);
|
|
16470
|
+
width: 16px;
|
|
16471
|
+
height: 16px;
|
|
16472
|
+
background: var(--dsh-im-session-logo) center / contain no-repeat;
|
|
16473
|
+
text-indent: 0;
|
|
16474
|
+
pointer-events: none;
|
|
16475
|
+
}
|
|
16476
|
+
${MARKED}[${TITLE_ATTR}]::after {
|
|
16477
|
+
content: attr(${TITLE_ATTR}) / "";
|
|
16478
|
+
position: absolute;
|
|
16479
|
+
inset: 0;
|
|
16480
|
+
inset-inline-start: 22px;
|
|
16481
|
+
-webkit-text-fill-color: currentColor;
|
|
16482
|
+
text-indent: 0;
|
|
16483
|
+
overflow: hidden;
|
|
16484
|
+
white-space: nowrap;
|
|
16485
|
+
text-overflow: ellipsis;
|
|
16486
|
+
pointer-events: none;
|
|
16487
|
+
}
|
|
16488
|
+
${Object.entries(uris).map(([channel4, uri]) => `[${CHANNEL_ATTR}="${channel4}"] { --dsh-im-session-logo: url("${uri}"); }`).join("\n")}
|
|
16489
|
+
`;
|
|
16490
|
+
document2.head.appendChild(style);
|
|
16491
|
+
const restore = (title) => {
|
|
16492
|
+
const previous = owned.get(title);
|
|
16493
|
+
if (!previous) return;
|
|
16494
|
+
owned.delete(title);
|
|
16495
|
+
for (const [attribute, value] of previous) {
|
|
16496
|
+
if (value === null) title.removeAttribute(attribute);
|
|
16497
|
+
else title.setAttribute(attribute, value);
|
|
16498
|
+
}
|
|
16499
|
+
};
|
|
16500
|
+
const update = (row) => {
|
|
16501
|
+
const title = row.isConnected ? titleOf(row) : null;
|
|
16502
|
+
for (const marked of row.querySelectorAll(MARKED)) {
|
|
16503
|
+
if (marked !== title) restore(marked);
|
|
16504
|
+
}
|
|
16505
|
+
if (!title) return;
|
|
16506
|
+
const parsed = parseSessionChannelTitle(title.textContent);
|
|
16507
|
+
if (!parsed || !ready.has(parsed.channel)) {
|
|
16508
|
+
restore(title);
|
|
16509
|
+
return;
|
|
16510
|
+
}
|
|
16511
|
+
if (!owned.has(title)) {
|
|
16512
|
+
owned.set(title, [CHANNEL_ATTR, TITLE_ATTR].map((attribute) => [attribute, title.getAttribute(attribute)]));
|
|
16513
|
+
}
|
|
16514
|
+
title.setAttribute(TITLE_ATTR, parsed.title);
|
|
16515
|
+
title.setAttribute(CHANNEL_ATTR, parsed.channel);
|
|
16516
|
+
};
|
|
16517
|
+
const schedule = () => {
|
|
16518
|
+
if (closed || scheduled || !queued.size) return;
|
|
16519
|
+
scheduled = true;
|
|
16520
|
+
queueMicrotask(() => {
|
|
16521
|
+
scheduled = false;
|
|
16522
|
+
if (closed) return;
|
|
16523
|
+
const rows = [...queued];
|
|
16524
|
+
queued.clear();
|
|
16525
|
+
for (const row of rows) {
|
|
16526
|
+
try {
|
|
16527
|
+
update(row);
|
|
16528
|
+
} catch {
|
|
16529
|
+
for (const marked of row.querySelectorAll(MARKED)) restore(marked);
|
|
16530
|
+
}
|
|
16531
|
+
}
|
|
16532
|
+
});
|
|
16533
|
+
};
|
|
16534
|
+
const collect = (node, descendants = false) => {
|
|
16535
|
+
const element = node.nodeType === 1 ? node : node.parentElement;
|
|
16536
|
+
if (!element) return;
|
|
16537
|
+
const row = element.closest(ROW);
|
|
16538
|
+
if (row) queued.add(row);
|
|
16539
|
+
if (descendants) {
|
|
16540
|
+
for (const child of element.querySelectorAll(ROW)) queued.add(child);
|
|
16541
|
+
const marked = [...element.querySelectorAll(MARKED)];
|
|
16542
|
+
if (owned.has(element)) marked.push(element);
|
|
16543
|
+
for (const title of marked) {
|
|
16544
|
+
const owner = title.closest(ROW);
|
|
16545
|
+
if (owner) queued.add(owner);
|
|
16546
|
+
else restore(title);
|
|
16547
|
+
}
|
|
16548
|
+
}
|
|
16549
|
+
schedule();
|
|
16550
|
+
};
|
|
16551
|
+
const observer = new view.MutationObserver((records) => {
|
|
16552
|
+
if (closed) return;
|
|
16553
|
+
for (const record2 of records) {
|
|
16554
|
+
collect(record2.target, record2.type === "attributes");
|
|
16555
|
+
if (record2.type !== "childList") continue;
|
|
16556
|
+
for (const node of record2.addedNodes) collect(node, true);
|
|
16557
|
+
for (const node of record2.removedNodes) {
|
|
16558
|
+
if (node.nodeType !== 1 || node.isConnected) continue;
|
|
16559
|
+
if (owned.has(node)) restore(node);
|
|
16560
|
+
for (const title of node.querySelectorAll(MARKED)) restore(title);
|
|
16561
|
+
}
|
|
16562
|
+
}
|
|
16563
|
+
});
|
|
16564
|
+
observer.observe(document2.body, {
|
|
16565
|
+
subtree: true,
|
|
16566
|
+
childList: true,
|
|
16567
|
+
characterData: true,
|
|
16568
|
+
attributes: true,
|
|
16569
|
+
attributeFilter: ["class", "role", "aria-selected", "contenteditable"]
|
|
16570
|
+
});
|
|
16571
|
+
for (const [channel4, uri] of Object.entries(uris)) {
|
|
16572
|
+
const image = new view.Image();
|
|
16573
|
+
images.push(image);
|
|
16574
|
+
image.onload = () => {
|
|
16575
|
+
if (closed) return;
|
|
16576
|
+
ready.add(channel4);
|
|
16577
|
+
collect(document2.body, true);
|
|
16578
|
+
};
|
|
16579
|
+
image.src = uri;
|
|
16580
|
+
}
|
|
16581
|
+
return () => {
|
|
16582
|
+
closed = true;
|
|
16583
|
+
observer.disconnect();
|
|
16584
|
+
queued.clear();
|
|
16585
|
+
for (const image of images) image.onload = null;
|
|
16586
|
+
for (const title of [...owned.keys()]) restore(title);
|
|
16587
|
+
style.remove();
|
|
16588
|
+
};
|
|
16589
|
+
}
|
|
16590
|
+
function installSessionChannelLogos(document2 = globalThis.document) {
|
|
16591
|
+
const view = document2?.defaultView;
|
|
16592
|
+
if (!document2?.body || !document2?.head || !view?.MutationObserver || !view?.Image || !view.CSS?.supports?.("content", `attr(${TITLE_ATTR}) / ""`) || !view.CSS.supports("-webkit-text-fill-color", "transparent")) return () => {
|
|
16593
|
+
};
|
|
16594
|
+
let entry = installations.get(document2);
|
|
16595
|
+
if (!entry) {
|
|
16596
|
+
try {
|
|
16597
|
+
entry = { references: 0, close: createInstallation(document2) };
|
|
16598
|
+
} catch {
|
|
16599
|
+
return () => {
|
|
16600
|
+
};
|
|
16601
|
+
}
|
|
16602
|
+
installations.set(document2, entry);
|
|
16603
|
+
}
|
|
16604
|
+
entry.references += 1;
|
|
16605
|
+
let released = false;
|
|
16606
|
+
return () => {
|
|
16607
|
+
if (released) return;
|
|
16608
|
+
released = true;
|
|
16609
|
+
entry.references -= 1;
|
|
16610
|
+
if (entry.references > 0) return;
|
|
16611
|
+
entry.close();
|
|
16612
|
+
installations.delete(document2);
|
|
16613
|
+
};
|
|
16614
|
+
}
|
|
16615
|
+
|
|
15264
16616
|
// plugin-src/client/update-panel.js
|
|
15265
|
-
var
|
|
16617
|
+
var React27 = __toESM(require("react"), 1);
|
|
15266
16618
|
var import_react_dom3 = require("react-dom");
|
|
15267
16619
|
var import_valid = __toESM(require_valid(), 1);
|
|
15268
16620
|
var import_rcompare = __toESM(require_rcompare(), 1);
|
|
@@ -15309,7 +16661,7 @@ function unwrapSnapshot(result) {
|
|
|
15309
16661
|
}
|
|
15310
16662
|
return value;
|
|
15311
16663
|
}
|
|
15312
|
-
function
|
|
16664
|
+
function presentError13(error) {
|
|
15313
16665
|
const code = error?.rpcError?.code ?? error?.code ?? "";
|
|
15314
16666
|
const message = error?.rpcError?.message ?? error?.message ?? "";
|
|
15315
16667
|
if (code === "update-unavailable" || /(?:not[-_ ]found|unimplemented|unknown[-_ ](?:endpoint|channel)|no[-_ ]handler)/i.test(code) || /(?:not found|unknown (?:endpoint|channel)|not registered|no .*handler|HTTP 404)/i.test(message)) {
|
|
@@ -15352,11 +16704,11 @@ function manualUpdateCommand(snapshot) {
|
|
|
15352
16704
|
return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
|
|
15353
16705
|
}
|
|
15354
16706
|
function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
15355
|
-
const [copyState, setCopyState] =
|
|
15356
|
-
const commandRef =
|
|
15357
|
-
const mounted =
|
|
15358
|
-
const copying =
|
|
15359
|
-
|
|
16707
|
+
const [copyState, setCopyState] = React27.useState("idle");
|
|
16708
|
+
const commandRef = React27.useRef(null);
|
|
16709
|
+
const mounted = React27.useRef(false);
|
|
16710
|
+
const copying = React27.useRef(false);
|
|
16711
|
+
React27.useEffect(() => {
|
|
15360
16712
|
mounted.current = true;
|
|
15361
16713
|
return () => {
|
|
15362
16714
|
mounted.current = false;
|
|
@@ -15388,7 +16740,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15388
16740
|
{ className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
|
|
15389
16741
|
h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
|
|
15390
16742
|
command ? h2(
|
|
15391
|
-
|
|
16743
|
+
React27.Fragment,
|
|
15392
16744
|
null,
|
|
15393
16745
|
h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
|
|
15394
16746
|
h2(
|
|
@@ -15424,7 +16776,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15424
16776
|
"aria-hidden": "true",
|
|
15425
16777
|
focusable: "false"
|
|
15426
16778
|
}, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
|
|
15427
|
-
|
|
16779
|
+
React27.Fragment,
|
|
15428
16780
|
null,
|
|
15429
16781
|
h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
|
|
15430
16782
|
h2("path", { d: "M5 13H3.5A1.5 1.5 0 0 1 2 11.5v-8A1.5 1.5 0 0 1 3.5 2h8A1.5 1.5 0 0 1 13 3.5V5" })
|
|
@@ -15449,10 +16801,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15449
16801
|
);
|
|
15450
16802
|
}
|
|
15451
16803
|
function UpdateDialog({ children, onClose }) {
|
|
15452
|
-
const dialogRef =
|
|
15453
|
-
const titleId =
|
|
15454
|
-
const descriptionId =
|
|
15455
|
-
|
|
16804
|
+
const dialogRef = React27.useRef(null);
|
|
16805
|
+
const titleId = React27.useId();
|
|
16806
|
+
const descriptionId = React27.useId();
|
|
16807
|
+
React27.useEffect(() => {
|
|
15456
16808
|
const previous = globalThis.document?.activeElement;
|
|
15457
16809
|
dialogRef.current?.focus?.();
|
|
15458
16810
|
return () => {
|
|
@@ -15510,19 +16862,19 @@ function UpdateDialog({ children, onClose }) {
|
|
|
15510
16862
|
return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
|
|
15511
16863
|
}
|
|
15512
16864
|
function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
15513
|
-
const [snapshot, setSnapshot] =
|
|
15514
|
-
const [action, setAction] =
|
|
15515
|
-
const [error, setError] =
|
|
15516
|
-
const [open, setOpen] =
|
|
15517
|
-
const [uncertainInstall, setUncertainInstall] =
|
|
15518
|
-
const mounted =
|
|
15519
|
-
const busy =
|
|
15520
|
-
const readController =
|
|
15521
|
-
const pollReadController =
|
|
15522
|
-
const installRequest =
|
|
15523
|
-
const onStatusRef =
|
|
16865
|
+
const [snapshot, setSnapshot] = React27.useState(null);
|
|
16866
|
+
const [action, setAction] = React27.useState("status");
|
|
16867
|
+
const [error, setError] = React27.useState(null);
|
|
16868
|
+
const [open, setOpen] = React27.useState(false);
|
|
16869
|
+
const [uncertainInstall, setUncertainInstall] = React27.useState(false);
|
|
16870
|
+
const mounted = React27.useRef(false);
|
|
16871
|
+
const busy = React27.useRef(false);
|
|
16872
|
+
const readController = React27.useRef(null);
|
|
16873
|
+
const pollReadController = React27.useRef(null);
|
|
16874
|
+
const installRequest = React27.useRef(null);
|
|
16875
|
+
const onStatusRef = React27.useRef(onStatus);
|
|
15524
16876
|
onStatusRef.current = onStatus;
|
|
15525
|
-
const accept =
|
|
16877
|
+
const accept = React27.useCallback((next) => {
|
|
15526
16878
|
setSnapshot(next);
|
|
15527
16879
|
onStatusRef.current?.(next);
|
|
15528
16880
|
}, []);
|
|
@@ -15531,7 +16883,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15531
16883
|
setUncertainInstall(false);
|
|
15532
16884
|
accept(next);
|
|
15533
16885
|
};
|
|
15534
|
-
const invoke =
|
|
16886
|
+
const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
|
|
15535
16887
|
if (typeof rpcCall !== "function") {
|
|
15536
16888
|
const unavailable = new Error("\u5F53\u524D Host \u4E0D\u652F\u6301\u66F4\u65B0\u63A5\u53E3\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u5E76\u91CD\u542F\u3002");
|
|
15537
16889
|
unavailable.code = "update-unavailable";
|
|
@@ -15539,14 +16891,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15539
16891
|
}
|
|
15540
16892
|
return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
|
|
15541
16893
|
}, [rpcCall]);
|
|
15542
|
-
|
|
16894
|
+
React27.useEffect(() => {
|
|
15543
16895
|
mounted.current = true;
|
|
15544
16896
|
busy.current = true;
|
|
15545
16897
|
const controller = new AbortController();
|
|
15546
16898
|
void invoke("update.status", {}, controller.signal).then((next) => {
|
|
15547
16899
|
if (!controller.signal.aborted) accept(next);
|
|
15548
16900
|
}).catch((cause) => {
|
|
15549
|
-
if (!controller.signal.aborted) setError(
|
|
16901
|
+
if (!controller.signal.aborted) setError(presentError13(cause));
|
|
15550
16902
|
}).finally(() => {
|
|
15551
16903
|
if (!controller.signal.aborted) {
|
|
15552
16904
|
busy.current = false;
|
|
@@ -15562,7 +16914,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15562
16914
|
const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
|
|
15563
16915
|
const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
|
|
15564
16916
|
const shouldPoll = activeJob || uncertainInstall;
|
|
15565
|
-
|
|
16917
|
+
React27.useEffect(() => {
|
|
15566
16918
|
if (!shouldPoll) return void 0;
|
|
15567
16919
|
let controller;
|
|
15568
16920
|
const scheduler = createPollScheduler({
|
|
@@ -15583,7 +16935,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15583
16935
|
keepPolling = ACTIVE_STATES4.has(next.job?.state);
|
|
15584
16936
|
}
|
|
15585
16937
|
} catch (cause) {
|
|
15586
|
-
if (!pendingController.signal.aborted) setError(
|
|
16938
|
+
if (!pendingController.signal.aborted) setError(presentError13(cause));
|
|
15587
16939
|
} finally {
|
|
15588
16940
|
if (pollReadController.current === pendingController) pollReadController.current = null;
|
|
15589
16941
|
}
|
|
@@ -15614,7 +16966,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15614
16966
|
else acceptAuthoritative(next);
|
|
15615
16967
|
}
|
|
15616
16968
|
} catch (cause) {
|
|
15617
|
-
if (!controller.signal.aborted && mounted.current) setError(
|
|
16969
|
+
if (!controller.signal.aborted && mounted.current) setError(presentError13(cause));
|
|
15618
16970
|
} finally {
|
|
15619
16971
|
if (!controller.signal.aborted && mounted.current) {
|
|
15620
16972
|
busy.current = false;
|
|
@@ -15640,7 +16992,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15640
16992
|
if (mounted.current) acceptAuthoritative(next);
|
|
15641
16993
|
} catch (cause) {
|
|
15642
16994
|
if (mounted.current) {
|
|
15643
|
-
setError(
|
|
16995
|
+
setError(presentError13(cause));
|
|
15644
16996
|
setUncertainInstall(true);
|
|
15645
16997
|
}
|
|
15646
16998
|
} finally {
|
|
@@ -15660,7 +17012,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15660
17012
|
const manualCommand = manualUpdateCommand(snapshot);
|
|
15661
17013
|
const buttonLabel = action === "checking" ? "\u68C0\u67E5\u4E2D\u2026" : action === "starting" || activeJob ? "\u6B63\u5728\u66F4\u65B0\u2026" : restartRequired ? "\u5F85\u624B\u52A8\u91CD\u542F" : snapshot?.canInstall ? "\u66F4\u65B0\u81F3" : "\u68C0\u67E5\u66F4\u65B0";
|
|
15662
17014
|
return h2(
|
|
15663
|
-
|
|
17015
|
+
React27.Fragment,
|
|
15664
17016
|
null,
|
|
15665
17017
|
h2("button", {
|
|
15666
17018
|
type: "button",
|
|
@@ -15685,13 +17037,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15685
17037
|
h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
|
|
15686
17038
|
h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
|
|
15687
17039
|
snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
|
|
15688
|
-
|
|
17040
|
+
React27.Fragment,
|
|
15689
17041
|
null,
|
|
15690
17042
|
h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
|
|
15691
17043
|
h2("dd", null, `v${snapshot.installedVersion}`)
|
|
15692
17044
|
) : null,
|
|
15693
17045
|
targetVersion ? h2(
|
|
15694
|
-
|
|
17046
|
+
React27.Fragment,
|
|
15695
17047
|
null,
|
|
15696
17048
|
h2("dt", null, "\u76EE\u6807\u7248\u672C"),
|
|
15697
17049
|
h2("dd", null, `v${targetVersion}`)
|
|
@@ -15781,6 +17133,7 @@ var CHANNELS = Object.freeze([
|
|
|
15781
17133
|
{ id: "telegram", label: "Telegram" },
|
|
15782
17134
|
{ id: "discord", label: "Discord" },
|
|
15783
17135
|
{ id: "whatsapp", label: "WhatsApp" },
|
|
17136
|
+
{ id: "wecomApp", label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
|
|
15784
17137
|
{ id: "office", label: "AI Office", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" }
|
|
15785
17138
|
]);
|
|
15786
17139
|
function WeixinLogo() {
|
|
@@ -15810,6 +17163,9 @@ function QqLogo() {
|
|
|
15810
17163
|
function WecomLogo() {
|
|
15811
17164
|
return h2("span", { className: "dim-logo dim-logoWecom", "aria-hidden": "true" }, h2(WecomLogoGlyph));
|
|
15812
17165
|
}
|
|
17166
|
+
function WecomAppLogo() {
|
|
17167
|
+
return h2("span", { className: "dim-logo dim-logoWecomApp", "aria-hidden": "true" }, h2(WecomLogoGlyph));
|
|
17168
|
+
}
|
|
15813
17169
|
function TelegramLogo() {
|
|
15814
17170
|
return h2(
|
|
15815
17171
|
"span",
|
|
@@ -15850,6 +17206,7 @@ function ChannelLogo({ channel: channel4 }) {
|
|
|
15850
17206
|
if (channel4 === "feishu") return h2(FeishuLogo);
|
|
15851
17207
|
if (channel4 === "dingtalk") return h2(DingtalkLogo);
|
|
15852
17208
|
if (channel4 === "wecom") return h2(WecomLogo);
|
|
17209
|
+
if (channel4 === "wecomApp") return h2(WecomAppLogo);
|
|
15853
17210
|
if (channel4 === "qq") return h2(QqLogo);
|
|
15854
17211
|
if (channel4 === "slack") return h2(SlackLogo);
|
|
15855
17212
|
if (channel4 === "telegram") return h2(TelegramLogo);
|
|
@@ -15886,6 +17243,7 @@ function IMSettingsTab({
|
|
|
15886
17243
|
slackRpcCall,
|
|
15887
17244
|
telegramRpcCall,
|
|
15888
17245
|
wecomRpcCall,
|
|
17246
|
+
wecomAppRpcCall,
|
|
15889
17247
|
weixinRpcCall,
|
|
15890
17248
|
whatsappRpcCall,
|
|
15891
17249
|
officeRpcCall,
|
|
@@ -15896,23 +17254,23 @@ function IMSettingsTab({
|
|
|
15896
17254
|
browserLocation = globalThis.location,
|
|
15897
17255
|
navigateToRecoveryUrl = replacePageLocation
|
|
15898
17256
|
}) {
|
|
15899
|
-
const [selected, setSelected] =
|
|
15900
|
-
const [loopbackRecovery, setLoopbackRecovery] =
|
|
15901
|
-
const [runningVersion, setRunningVersion] =
|
|
15902
|
-
const [deliverySettings, setDeliverySettings] =
|
|
15903
|
-
const githubTooltipId =
|
|
15904
|
-
const generalSettingsTooltipId =
|
|
17257
|
+
const [selected, setSelected] = React28.useState("weixin");
|
|
17258
|
+
const [loopbackRecovery, setLoopbackRecovery] = React28.useState(null);
|
|
17259
|
+
const [runningVersion, setRunningVersion] = React28.useState(IM_PLUGIN_VERSION);
|
|
17260
|
+
const [deliverySettings, setDeliverySettings] = React28.useState(null);
|
|
17261
|
+
const githubTooltipId = React28.useId();
|
|
17262
|
+
const generalSettingsTooltipId = React28.useId();
|
|
15905
17263
|
const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
|
|
15906
17264
|
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
|
15907
17265
|
const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
|
|
15908
17266
|
const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
|
|
15909
|
-
const reportLoopbackRecovery =
|
|
17267
|
+
const reportLoopbackRecovery = React28.useCallback((recovery) => {
|
|
15910
17268
|
setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
|
|
15911
17269
|
}, []);
|
|
15912
|
-
const reportUpdateStatus =
|
|
17270
|
+
const reportUpdateStatus = React28.useCallback((snapshot) => {
|
|
15913
17271
|
setRunningVersion(snapshot.runningVersion);
|
|
15914
17272
|
}, []);
|
|
15915
|
-
const rpcCalls =
|
|
17273
|
+
const rpcCalls = React28.useMemo(() => createLoopbackAwareRpcCalls({
|
|
15916
17274
|
dingtalkRpcCall,
|
|
15917
17275
|
discordRpcCall,
|
|
15918
17276
|
feishuRpcCall,
|
|
@@ -15920,6 +17278,7 @@ function IMSettingsTab({
|
|
|
15920
17278
|
slackRpcCall,
|
|
15921
17279
|
telegramRpcCall,
|
|
15922
17280
|
wecomRpcCall,
|
|
17281
|
+
wecomAppRpcCall,
|
|
15923
17282
|
weixinRpcCall,
|
|
15924
17283
|
whatsappRpcCall,
|
|
15925
17284
|
officeRpcCall,
|
|
@@ -15943,10 +17302,11 @@ function IMSettingsTab({
|
|
|
15943
17302
|
telegramRpcCall,
|
|
15944
17303
|
updateRpcCall,
|
|
15945
17304
|
wecomRpcCall,
|
|
17305
|
+
wecomAppRpcCall,
|
|
15946
17306
|
weixinRpcCall,
|
|
15947
17307
|
whatsappRpcCall
|
|
15948
17308
|
]);
|
|
15949
|
-
const botSettingsContext =
|
|
17309
|
+
const botSettingsContext = React28.useMemo(() => Object.freeze({
|
|
15950
17310
|
openBotSettings: setDeliverySettings
|
|
15951
17311
|
}), []);
|
|
15952
17312
|
return h2(
|
|
@@ -16075,7 +17435,7 @@ function IMSettingsTab({
|
|
|
16075
17435
|
rpcCall: rpcCalls.deliveryRpcCall,
|
|
16076
17436
|
accessRpcCall: rpcCalls[`${active.id}RpcCall`],
|
|
16077
17437
|
onBack: () => setDeliverySettings(null)
|
|
16078
|
-
}) : active.id === "weixin" ? h2(WeixinSettingsTab, { rpcCall: rpcCalls.weixinRpcCall }) : active.id === "feishu" ? h2(FeishuSettingsTab, { rpcCall: rpcCalls.feishuRpcCall }) : active.id === "dingtalk" ? h2(DingtalkSettingsTab, { rpcCall: rpcCalls.dingtalkRpcCall }) : active.id === "wecom" ? h2(WecomSettingsTab, { rpcCall: rpcCalls.wecomRpcCall }) : active.id === "qq" ? h2(QqSettingsTab, { rpcCall: rpcCalls.qqRpcCall }) : active.id === "slack" ? h2(SlackSettingsTab, { rpcCall: rpcCalls.slackRpcCall }) : active.id === "telegram" ? h2(TelegramSettingsTab, { rpcCall: rpcCalls.telegramRpcCall }) : active.id === "discord" ? h2(DiscordSettingsTab, { rpcCall: rpcCalls.discordRpcCall }) : active.id === "whatsapp" ? h2(WhatsappSettingsTab, { rpcCall: rpcCalls.whatsappRpcCall }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
|
|
17438
|
+
}) : active.id === "weixin" ? h2(WeixinSettingsTab, { rpcCall: rpcCalls.weixinRpcCall }) : active.id === "feishu" ? h2(FeishuSettingsTab, { rpcCall: rpcCalls.feishuRpcCall }) : active.id === "dingtalk" ? h2(DingtalkSettingsTab, { rpcCall: rpcCalls.dingtalkRpcCall }) : active.id === "wecom" ? h2(WecomSettingsTab, { rpcCall: rpcCalls.wecomRpcCall }) : active.id === "wecomApp" ? h2(WecomAppSettingsTab, { rpcCall: rpcCalls.wecomAppRpcCall }) : active.id === "qq" ? h2(QqSettingsTab, { rpcCall: rpcCalls.qqRpcCall }) : active.id === "slack" ? h2(SlackSettingsTab, { rpcCall: rpcCalls.slackRpcCall }) : active.id === "telegram" ? h2(TelegramSettingsTab, { rpcCall: rpcCalls.telegramRpcCall }) : active.id === "discord" ? h2(DiscordSettingsTab, { rpcCall: rpcCalls.discordRpcCall }) : active.id === "whatsapp" ? h2(WhatsappSettingsTab, { rpcCall: rpcCalls.whatsappRpcCall }) : h2(OfficeSettingsTab, { rpcCall: rpcCalls.officeRpcCall })
|
|
16079
17439
|
)
|
|
16080
17440
|
)
|
|
16081
17441
|
)
|
|
@@ -16089,11 +17449,13 @@ function apply(ctx) {
|
|
|
16089
17449
|
);
|
|
16090
17450
|
const t = ctx.locale.bind(IM_LOCALE_NAMESPACE);
|
|
16091
17451
|
setImTranslator(t);
|
|
17452
|
+
ctx.effect(() => installSessionChannelLogos(), "im-settings: Session channel logos");
|
|
16092
17453
|
ctx.effect(() => {
|
|
16093
17454
|
const disposers = [
|
|
16094
17455
|
installFeishuStyles(),
|
|
16095
17456
|
installWeixinStyles(),
|
|
16096
17457
|
installWecomStyles(),
|
|
17458
|
+
installWecomAppStyles(),
|
|
16097
17459
|
installQqStyles(),
|
|
16098
17460
|
installSlackStyles(),
|
|
16099
17461
|
installTelegramStyles(),
|
|
@@ -16111,6 +17473,7 @@ function apply(ctx) {
|
|
|
16111
17473
|
const dingtalkRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
|
|
16112
17474
|
const qqRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(QQ_RPC_CHANNEL, endpoint, payload, signal);
|
|
16113
17475
|
const wecomRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_RPC_CHANNEL, endpoint, payload, signal);
|
|
17476
|
+
const wecomAppRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_APP_RPC_CHANNEL, endpoint, payload, signal);
|
|
16114
17477
|
const telegramRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
|
|
16115
17478
|
const discordRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DISCORD_RPC_CHANNEL, endpoint, payload, signal);
|
|
16116
17479
|
const whatsappRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
|
|
@@ -16137,6 +17500,7 @@ function apply(ctx) {
|
|
|
16137
17500
|
slackRpcCall,
|
|
16138
17501
|
telegramRpcCall,
|
|
16139
17502
|
wecomRpcCall,
|
|
17503
|
+
wecomAppRpcCall,
|
|
16140
17504
|
weixinRpcCall,
|
|
16141
17505
|
whatsappRpcCall,
|
|
16142
17506
|
officeRpcCall,
|