@xmanrui/dsh-im 4.15.0 → 4.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -1
- package/README.md +9 -5
- package/lib/client.js +1731 -612
- package/lib/index.js +303 -293
- package/package.json +10 -2
- package/plugin-src/client/access-policy-settings.js +6 -0
- package/plugin-src/client/channels/feishu/index.js +15 -3
- 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 +63 -0
- package/plugin-src/client/index.js +18 -0
- package/plugin-src/client/model-setting.js +135 -69
- 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 +7 -2
- package/scripts/verify-model-setting.mjs +54 -0
- package/src/channels/dingtalk/dingtalk-api.mjs +41 -48
- package/src/channels/dingtalk/dingtalk-bridge.mjs +5 -1
- package/src/channels/feishu/bridge.mjs +295 -9
- package/src/channels/feishu/feishu-cards.mjs +38 -0
- package/src/channels/feishu/feishu-channel.mjs +88 -20
- 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 +12 -0
- 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/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.1",
|
|
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,14 @@ 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"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
name: "masucc",
|
|
616
|
+
url: "https://github.com/masucc"
|
|
609
617
|
}
|
|
610
618
|
],
|
|
611
619
|
license: "MIT",
|
|
@@ -1075,6 +1083,7 @@ var EN = Object.freeze({
|
|
|
1075
1083
|
"\u5F00\u542F\uFF08\u81EA\u52A8\u5F00\u542F\u72EC\u7ACB\u98DE\u4E66\u8BDD\u9898\uFF09": "On (auto-open a dedicated Feishu topic)",
|
|
1076
1084
|
"\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
1085
|
"\u5206\u6B65\u76F4\u63A8": "Step push",
|
|
1086
|
+
"\u67E5\u770B\u5206\u6B65\u76F4\u63A8\u8BF4\u660E": "View step push help",
|
|
1078
1087
|
"\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
1088
|
"\u5173\u95ED\uFF08\u4FDD\u6301\u6D41\u5F0F\u5361\u6A21\u5F0F\uFF09": "Off (keep the streaming card)",
|
|
1080
1089
|
"\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 +1222,14 @@ var EN = Object.freeze({
|
|
|
1213
1222
|
"Agent Preset \u65E0\u6548\u3002": "The Agent Preset is invalid.",
|
|
1214
1223
|
"Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002": "The Agent Preset does not exist or is unavailable.",
|
|
1215
1224
|
"\u6A21\u578B": "Model",
|
|
1225
|
+
"\u6A21\u578B\u4E0E\u601D\u8003\u5F3A\u5EA6": "Model and reasoning effort",
|
|
1226
|
+
"\u601D\u8003\u5F3A\u5EA6": "Reasoning effort",
|
|
1227
|
+
"\u8DDF\u968F\u6A21\u578B\u9ED8\u8BA4": "Model default",
|
|
1228
|
+
"\u5148\u9009\u62E9\u6A21\u578B\uFF0C\u518D\u8BBE\u7F6E\u601D\u8003\u5F3A\u5EA6\u3002": "Select a model to configure its reasoning effort.",
|
|
1229
|
+
"\u8BE5\u6A21\u578B\u672A\u63D0\u4F9B\u53EF\u8C03\u8282\u7684\u601D\u8003\u5F3A\u5EA6\u3002": "This model does not provide adjustable reasoning effort.",
|
|
1230
|
+
"\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.",
|
|
1231
|
+
"\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.",
|
|
1232
|
+
"\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
1233
|
"\u67E5\u770B\u6A21\u578B\u8BBE\u7F6E\u8BF4\u660E": "View model setting help",
|
|
1217
1234
|
"\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B": "Follow the default model",
|
|
1218
1235
|
"\u6A21\u578B\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the model. Try again.",
|
|
@@ -1744,7 +1761,61 @@ var EN = Object.freeze({
|
|
|
1744
1761
|
"\u786E\u8BA4\u6E05\u7406\u8FC7\u671F\u9644\u4EF6": "Confirm expired attachment cleanup",
|
|
1745
1762
|
"\u786E\u8BA4\u6E05\u7406\u5F53\u524D\u5DF2\u8FC7\u671F\u7684\u9644\u4EF6\uFF1F": "Clean up the attachments that are currently expired?",
|
|
1746
1763
|
"\u786E\u8BA4\u6E05\u7406": "Confirm cleanup",
|
|
1747
|
-
"\u6B63\u5728\u6E05\u7406\u2026": "Cleaning up\u2026"
|
|
1764
|
+
"\u6B63\u5728\u6E05\u7406\u2026": "Cleaning up\u2026",
|
|
1765
|
+
"\u6B63\u5728\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001\u2026": "Loading WeCom app status\u2026",
|
|
1766
|
+
"\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "Add WeCom app",
|
|
1767
|
+
"\u6536\u8D77\u8868\u5355": "Collapse form",
|
|
1768
|
+
"\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528": "Add a WeCom self-built app",
|
|
1769
|
+
"\u6B63\u5728\u586B\u5199": "Filling in details",
|
|
1770
|
+
"\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "No WeCom app connected yet",
|
|
1771
|
+
"\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",
|
|
1772
|
+
"\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.",
|
|
1773
|
+
"\u586B\u5199\u5E94\u7528\u53C2\u6570": "Fill in app parameters",
|
|
1774
|
+
"\u4F01\u4E1A ID\uFF08CorpID\uFF09": "Corp ID",
|
|
1775
|
+
"\u4F8B\u5982 ww1234567890abcdef": "for example ww1234567890abcdef",
|
|
1776
|
+
"\u5E94\u7528 AgentId": "AgentId",
|
|
1777
|
+
"\u4F8B\u5982 1000002": "for example 1000002",
|
|
1778
|
+
"\u5E94\u7528 Secret": "App Secret",
|
|
1779
|
+
"\u5E94\u7528\u8BE6\u60C5\u9875\u7684 Secret": "The Secret from the app details page",
|
|
1780
|
+
"\u56DE\u8C03 Token": "Callback Token",
|
|
1781
|
+
"\u63A5\u6536\u6D88\u606F \u2192 API \u63A5\u6536\u4E2D\u7684 Token": "The Token from Receive messages \u2192 API receive",
|
|
1782
|
+
"43 \u4F4D\u5B57\u6BCD\u6216\u6570\u5B57": "43 alphanumeric characters",
|
|
1783
|
+
"\u4EE3\u7406\u5730\u5740\uFF08\u53EF\u9009\uFF09": "API proxy (optional)",
|
|
1784
|
+
"\u7559\u7A7A\u76F4\u8FDE qyapi.weixin.qq.com": "leave empty to reach qyapi.weixin.qq.com directly",
|
|
1785
|
+
"\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF08\u53EF\u9009\uFF09": "Public callback base URL (optional)",
|
|
1786
|
+
"\u4F8B\u5982 https://im.example.com": "for example https://im.example.com",
|
|
1787
|
+
"\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00": "Streaming replies: on",
|
|
1788
|
+
"\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173": "Streaming replies: off",
|
|
1789
|
+
"\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",
|
|
1790
|
+
"\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528": "Bind a WeCom self-built app",
|
|
1791
|
+
"\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)",
|
|
1792
|
+
"\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",
|
|
1793
|
+
"\u91CD\u7F6E\u5BC6\u94A5": "Reset secret",
|
|
1794
|
+
"\u91CD\u7F6E\u4E2D\u2026": "Resetting\u2026",
|
|
1795
|
+
"\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.",
|
|
1796
|
+
"\u4FDD\u5B58\u8BBE\u7F6E": "Save settings",
|
|
1797
|
+
"\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.",
|
|
1798
|
+
"\u4FDD\u7559\u5E94\u7528": "Keep app",
|
|
1799
|
+
"\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "Connected WeCom apps",
|
|
1800
|
+
"HTTP \u56DE\u8C03\u901A\u9053": "HTTP callback channel",
|
|
1801
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528": "WeCom app",
|
|
1802
|
+
"\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58": "Corp ID saved securely",
|
|
1803
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u56DE\u8C03\u901A\u9053\u5C31\u7EEA": "WeCom app callback channel is ready",
|
|
1804
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA": "WeCom app connection is not ready",
|
|
1805
|
+
"\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.",
|
|
1806
|
+
"\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002": "Connection check finished.",
|
|
1807
|
+
"\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002": "Connection check finished; the test message was sent.",
|
|
1808
|
+
"\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.",
|
|
1809
|
+
"\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.",
|
|
1810
|
+
"\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.",
|
|
1811
|
+
"\u56DE\u8C03\u5BC6\u94A5\u91CD\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002": "The callback secret reset failed; try again later.",
|
|
1812
|
+
"\u65E0\u6CD5\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001": "Could not load WeCom app status",
|
|
1813
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E": "WeCom app settings",
|
|
1814
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5": "The WeCom app settings page is missing the RPC connection",
|
|
1815
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25": "The WeCom app operation failed",
|
|
1816
|
+
"\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5": "The WeCom app operation failed; try again later",
|
|
1817
|
+
"\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",
|
|
1818
|
+
"\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
1819
|
});
|
|
1749
1820
|
var en = EN;
|
|
1750
1821
|
var zh = Object.freeze(Object.fromEntries(
|
|
@@ -1760,78 +1831,78 @@ function isEnglish() {
|
|
|
1760
1831
|
function channelName(value) {
|
|
1761
1832
|
return localizeText(value);
|
|
1762
1833
|
}
|
|
1763
|
-
function translateDynamic(
|
|
1764
|
-
const guidanceLimit = /^增强提示词不得超过 (\d+) 个字符。$/.exec(
|
|
1834
|
+
function translateDynamic(text7) {
|
|
1835
|
+
const guidanceLimit = /^增强提示词不得超过 (\d+) 个字符。$/.exec(text7);
|
|
1765
1836
|
if (guidanceLimit) return `Guidance must not exceed ${guidanceLimit[1]} characters.`;
|
|
1766
|
-
let match = /^(\d+) \/ (\d+) 在线$/.exec(
|
|
1837
|
+
let match = /^(\d+) \/ (\d+) 在线$/.exec(text7);
|
|
1767
1838
|
if (match) return `${match[1]}/${match[2]} online`;
|
|
1768
|
-
match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(
|
|
1839
|
+
match = /^已接入 (\d+) 个机器人,其中 (\d+) 个在线$/.exec(text7);
|
|
1769
1840
|
if (match) return `${match[2]} of ${match[1]} bots online`;
|
|
1770
|
-
match = /^请输入 -1、0 或 1~(\d+) 之间的整数。$/.exec(
|
|
1841
|
+
match = /^请输入 -1、0 或 1~(\d+) 之间的整数。$/.exec(text7);
|
|
1771
1842
|
if (match) return `Enter -1, 0, or an integer from 1 to ${match[1]}.`;
|
|
1772
|
-
match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(
|
|
1843
|
+
match = /^正在读取\s*(.+?)\s*机器人状态…$/.exec(text7);
|
|
1773
1844
|
if (match) return `Loading ${channelName(match[1])} bot status\u2026`;
|
|
1774
|
-
match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(
|
|
1845
|
+
match = /^无法读取\s*(.+?)\s*机器人状态$/.exec(text7);
|
|
1775
1846
|
if (match) return `Could not load ${channelName(match[1])} bot status`;
|
|
1776
|
-
match = /^尚未接入\s*(.+?)\s*机器人$/.exec(
|
|
1847
|
+
match = /^尚未接入\s*(.+?)\s*机器人$/.exec(text7);
|
|
1777
1848
|
if (match) return `No ${channelName(match[1])} bot connected yet`;
|
|
1778
|
-
match = /^已接入的\s*(.+?)\s*机器人$/.exec(
|
|
1849
|
+
match = /^已接入的\s*(.+?)\s*机器人$/.exec(text7);
|
|
1779
1850
|
if (match) return `Connected ${channelName(match[1])} bots`;
|
|
1780
|
-
match = /^手动接入(.+)机器人$/.exec(
|
|
1851
|
+
match = /^手动接入(.+)机器人$/.exec(text7);
|
|
1781
1852
|
if (match) return `Connect ${channelName(match[1])} bot manually`;
|
|
1782
|
-
match = /^(.+) 设置$/.exec(
|
|
1853
|
+
match = /^(.+) 设置$/.exec(text7);
|
|
1783
1854
|
if (match) return `${channelName(match[1])} settings`;
|
|
1784
|
-
match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(
|
|
1855
|
+
match = /^从 DeepSeek Harness 移除“(.+)”?$/.exec(text7);
|
|
1785
1856
|
if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
|
|
1786
|
-
match = /^从 DeepSeek Harness 移除(.+)$/.exec(
|
|
1857
|
+
match = /^从 DeepSeek Harness 移除(.+)$/.exec(text7);
|
|
1787
1858
|
if (match) return `Remove ${match[1]} from DeepSeek Harness`;
|
|
1788
|
-
match = /^(.+)的飞书授权流程$/.exec(
|
|
1859
|
+
match = /^(.+)的飞书授权流程$/.exec(text7);
|
|
1789
1860
|
if (match) return `Feishu authorization flow for ${match[1]}`;
|
|
1790
|
-
match = /^用于为(.+)补全权限与回调的一次性授权二维码$/.exec(
|
|
1861
|
+
match = /^用于为(.+)补全权限与回调的一次性授权二维码$/.exec(text7);
|
|
1791
1862
|
if (match) return `One-time QR code for completing permissions and the callback for ${match[1]}`;
|
|
1792
|
-
match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(
|
|
1863
|
+
match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text7);
|
|
1793
1864
|
if (match) return `One-time QR code for granting group-message permission to ${match[1]}`;
|
|
1794
|
-
match = /^正在为「(.+)」补全权限与回调$/.exec(
|
|
1865
|
+
match = /^正在为「(.+)」补全权限与回调$/.exec(text7);
|
|
1795
1866
|
if (match) return `Completing permissions and the callback for \u201C${match[1]}\u201D`;
|
|
1796
|
-
match = /^正在为「(.+)」开通群消息权限$/.exec(
|
|
1867
|
+
match = /^正在为「(.+)」开通群消息权限$/.exec(text7);
|
|
1797
1868
|
if (match) return `Granting group-message permission to \u201C${match[1]}\u201D`;
|
|
1798
|
-
match = /^为(.+)补全权限与回调$/.exec(
|
|
1869
|
+
match = /^为(.+)补全权限与回调$/.exec(text7);
|
|
1799
1870
|
if (match) return `Complete permissions and the callback for ${match[1]}`;
|
|
1800
|
-
match = /^(.+)的权限补全二维码已生成,请使用飞书扫码。$/.exec(
|
|
1871
|
+
match = /^(.+)的权限补全二维码已生成,请使用飞书扫码。$/.exec(text7);
|
|
1801
1872
|
if (match) return `Permission-completion QR code generated for ${match[1]}. Scan it with Feishu.`;
|
|
1802
|
-
match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(
|
|
1873
|
+
match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text7);
|
|
1803
1874
|
if (match) return `Group-message permission QR code generated for ${match[1]}. Confirm it with Feishu.`;
|
|
1804
|
-
match = /^(.+)的权限与回调已补全。$/.exec(
|
|
1875
|
+
match = /^(.+)的权限与回调已补全。$/.exec(text7);
|
|
1805
1876
|
if (match) return `Permissions and the callback completed for ${match[1]}.`;
|
|
1806
|
-
match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(
|
|
1877
|
+
match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text7);
|
|
1807
1878
|
if (match) return `${match[1]} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.`;
|
|
1808
|
-
match = /^(检查连接|重试连接)(.+)$/.exec(
|
|
1879
|
+
match = /^(检查连接|重试连接)(.+)$/.exec(text7);
|
|
1809
1880
|
if (match) return `${localizeText(match[1])} ${match[2]}`;
|
|
1810
|
-
match = /^移除(.+)$/.exec(
|
|
1881
|
+
match = /^移除(.+)$/.exec(text7);
|
|
1811
1882
|
if (match) return `Remove ${match[1]}`;
|
|
1812
|
-
match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(
|
|
1883
|
+
match = /^这会停止消息连接,并删除本机保存的 (.+)、机器人配置及会话映射。(.+)中的机器人不会被自动删除。$/.exec(text7);
|
|
1813
1884
|
if (match) {
|
|
1814
1885
|
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
1886
|
}
|
|
1816
|
-
match = /^二维码剩余 (.+)$/.exec(
|
|
1887
|
+
match = /^二维码剩余 (.+)$/.exec(text7);
|
|
1817
1888
|
if (match) return `QR code expires in ${match[1]}`;
|
|
1818
|
-
match = /^最近一条消息处理失败:(.+)$/.exec(
|
|
1889
|
+
match = /^最近一条消息处理失败:(.+)$/.exec(text7);
|
|
1819
1890
|
if (match) return `Latest message failed: ${localizeText(match[1])}`;
|
|
1820
|
-
match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(
|
|
1891
|
+
match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(text7);
|
|
1821
1892
|
if (match) return `The image download failed (HTTP ${match[1]}). Send it again.`;
|
|
1822
|
-
match = /^一次最多只能处理 (\d+) 张图片。$/.exec(
|
|
1893
|
+
match = /^一次最多只能处理 (\d+) 张图片。$/.exec(text7);
|
|
1823
1894
|
if (match) return `A message can contain at most ${match[1]} images.`;
|
|
1824
|
-
match = /^状态刷新失败:(.+)$/.exec(
|
|
1895
|
+
match = /^状态刷新失败:(.+)$/.exec(text7);
|
|
1825
1896
|
if (match) return `Status refresh failed: ${match[1]}`;
|
|
1826
|
-
match = /^状态自动刷新失败:(.+)$/.exec(
|
|
1897
|
+
match = /^状态自动刷新失败:(.+)$/.exec(text7);
|
|
1827
1898
|
if (match) return `Automatic status refresh failed: ${match[1]}`;
|
|
1828
|
-
match = /^操作失败:(.+)$/.exec(
|
|
1899
|
+
match = /^操作失败:(.+)$/.exec(text7);
|
|
1829
1900
|
if (match) return `Operation failed: ${match[1]}`;
|
|
1830
|
-
match = /^连接检查失败:(.+)(参考号:(.+))$/.exec(
|
|
1901
|
+
match = /^连接检查失败:(.+)(参考号:(.+))$/.exec(text7);
|
|
1831
1902
|
if (match) return `Connection check failed: ${localizeText(match[1])} (reference: ${match[2]})`;
|
|
1832
|
-
match = /^连接检查失败:(.+)$/.exec(
|
|
1903
|
+
match = /^连接检查失败:(.+)$/.exec(text7);
|
|
1833
1904
|
if (match) return `Connection check failed: ${match[1]}`;
|
|
1834
|
-
match = /^移除失败:(.+)$/.exec(
|
|
1905
|
+
match = /^移除失败:(.+)$/.exec(text7);
|
|
1835
1906
|
if (match) return `Removal failed: ${match[1]}`;
|
|
1836
1907
|
const phrases = [
|
|
1837
1908
|
["\u4F01\u4E1A\u5FAE\u4FE1", "WeCom"],
|
|
@@ -1868,7 +1939,7 @@ function translateDynamic(text6) {
|
|
|
1868
1939
|
["\u8FDE\u63A5\u72B6\u6001", "connection status"],
|
|
1869
1940
|
["\u4E8C\u7EF4\u7801", "QR code"]
|
|
1870
1941
|
];
|
|
1871
|
-
let output =
|
|
1942
|
+
let output = text7;
|
|
1872
1943
|
for (const [source, target] of phrases) output = output.replaceAll(source, target);
|
|
1873
1944
|
return output;
|
|
1874
1945
|
}
|
|
@@ -1912,8 +1983,8 @@ var EMPTY_AGENT_PRESET_CATALOG = Object.freeze({
|
|
|
1912
1983
|
var AgentPresetCatalogContext = React3.createContext(EMPTY_AGENT_PRESET_CATALOG);
|
|
1913
1984
|
function normalizeAgentPresetId(value) {
|
|
1914
1985
|
if (typeof value !== "string") return "";
|
|
1915
|
-
const
|
|
1916
|
-
return PRESET_ID.test(
|
|
1986
|
+
const id6 = value.trim();
|
|
1987
|
+
return PRESET_ID.test(id6) ? id6 : "";
|
|
1917
1988
|
}
|
|
1918
1989
|
function normalizeAgentPresetCatalog(value) {
|
|
1919
1990
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -1922,11 +1993,11 @@ function normalizeAgentPresetCatalog(value) {
|
|
|
1922
1993
|
const items = [];
|
|
1923
1994
|
const seen = /* @__PURE__ */ new Set();
|
|
1924
1995
|
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:
|
|
1996
|
+
const id6 = typeof entry === "string" ? normalizeAgentPresetId(entry) : normalizeAgentPresetId(entry?.id);
|
|
1997
|
+
if (!id6 || seen.has(id6)) continue;
|
|
1998
|
+
seen.add(id6);
|
|
1999
|
+
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;
|
|
2000
|
+
items.push({ id: id6, label });
|
|
1930
2001
|
}
|
|
1931
2002
|
return {
|
|
1932
2003
|
defaultId: normalizeAgentPresetId(value.defaultId),
|
|
@@ -2022,14 +2093,15 @@ var React4 = __toESM(require("react"), 1);
|
|
|
2022
2093
|
// src/channels/shared/model-setting.mjs
|
|
2023
2094
|
var MAX_PROVIDER_ID_LENGTH = 256;
|
|
2024
2095
|
var MAX_MODEL_ID_LENGTH = 1024;
|
|
2096
|
+
var MAX_EFFORT_ID_LENGTH = 256;
|
|
2025
2097
|
var MAX_LABEL_LENGTH = 256;
|
|
2026
2098
|
var UNSAFE_DISPLAY_TEXT = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]+/gu;
|
|
2027
2099
|
var UNSAFE_ID_TEXT = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u;
|
|
2028
2100
|
function cleanId(value, maxLength) {
|
|
2029
2101
|
if (typeof value !== "string") return "";
|
|
2030
|
-
const
|
|
2031
|
-
if (!
|
|
2032
|
-
return
|
|
2102
|
+
const id6 = value.trim();
|
|
2103
|
+
if (!id6 || id6.length > maxLength || UNSAFE_ID_TEXT.test(id6)) return "";
|
|
2104
|
+
return id6;
|
|
2033
2105
|
}
|
|
2034
2106
|
function cleanLabel(value, fallback) {
|
|
2035
2107
|
if (typeof value !== "string") return fallback;
|
|
@@ -2045,7 +2117,27 @@ function normalizeModelSelection(value) {
|
|
|
2045
2117
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2046
2118
|
const provider = cleanId(value.provider, MAX_PROVIDER_ID_LENGTH);
|
|
2047
2119
|
const model = cleanId(value.model, MAX_MODEL_ID_LENGTH);
|
|
2048
|
-
|
|
2120
|
+
const reasoningEffort = value.reasoningEffort === void 0 ? void 0 : cleanId(value.reasoningEffort, MAX_EFFORT_ID_LENGTH);
|
|
2121
|
+
if (!provider || !model || reasoningEffort === "") return null;
|
|
2122
|
+
return { provider, model, ...reasoningEffort === void 0 ? {} : { reasoningEffort } };
|
|
2123
|
+
}
|
|
2124
|
+
function sameModelSelection(left, right) {
|
|
2125
|
+
return left?.provider === right?.provider && left?.model === right?.model && left?.reasoningEffort === right?.reasoningEffort;
|
|
2126
|
+
}
|
|
2127
|
+
function normalizeReasoning(value) {
|
|
2128
|
+
if (!value || typeof value !== "object" || !Array.isArray(value.efforts)) return void 0;
|
|
2129
|
+
const efforts = [];
|
|
2130
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2131
|
+
for (const entry of value.efforts) {
|
|
2132
|
+
const id6 = cleanId(entry?.id, MAX_EFFORT_ID_LENGTH);
|
|
2133
|
+
if (!id6 || seen.has(id6)) continue;
|
|
2134
|
+
seen.add(id6);
|
|
2135
|
+
const description = cleanLabel(entry.description, "");
|
|
2136
|
+
efforts.push({ id: id6, name: cleanLabel(entry.name, id6), ...description ? { description } : {} });
|
|
2137
|
+
}
|
|
2138
|
+
if (!efforts.length) return void 0;
|
|
2139
|
+
const defaultEffort = cleanId(value.defaultEffort, MAX_EFFORT_ID_LENGTH);
|
|
2140
|
+
return { efforts, ...seen.has(defaultEffort) ? { defaultEffort } : {} };
|
|
2049
2141
|
}
|
|
2050
2142
|
function modelSelectionId(value) {
|
|
2051
2143
|
const selection = normalizeModelSelection(value);
|
|
@@ -2069,9 +2161,13 @@ function normalizeModelCatalog(value) {
|
|
|
2069
2161
|
const key = `${provider}\0${model}`;
|
|
2070
2162
|
if (seen.has(key)) continue;
|
|
2071
2163
|
seen.add(key);
|
|
2164
|
+
const description = cleanLabel(entry.description, "");
|
|
2165
|
+
const reasoning = normalizeReasoning(entry.reasoning);
|
|
2072
2166
|
models.push({
|
|
2073
2167
|
id: model,
|
|
2074
|
-
name: cleanLabel(entry.name, model)
|
|
2168
|
+
name: cleanLabel(entry.name, model),
|
|
2169
|
+
...description ? { description } : {},
|
|
2170
|
+
...reasoning ? { reasoning } : {}
|
|
2075
2171
|
});
|
|
2076
2172
|
}
|
|
2077
2173
|
if (models.length > 0) {
|
|
@@ -2085,109 +2181,244 @@ function normalizeModelCatalog(value) {
|
|
|
2085
2181
|
const failures = [];
|
|
2086
2182
|
for (const candidate of Array.isArray(value.failures) ? value.failures : []) {
|
|
2087
2183
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
2088
|
-
const
|
|
2089
|
-
if (!
|
|
2090
|
-
failures.push({ id:
|
|
2184
|
+
const id6 = cleanId(candidate.id, MAX_PROVIDER_ID_LENGTH);
|
|
2185
|
+
if (!id6) continue;
|
|
2186
|
+
failures.push({ id: id6, name: cleanLabel(candidate.name, id6) });
|
|
2091
2187
|
}
|
|
2092
2188
|
return { groups, failures };
|
|
2093
2189
|
}
|
|
2190
|
+
function modelCatalogEntry(catalog, selection) {
|
|
2191
|
+
const normalized = normalizeModelSelection(selection);
|
|
2192
|
+
if (!normalized) return void 0;
|
|
2193
|
+
return normalizeModelCatalog(catalog).groups.filter((group) => group.id === normalized.provider).flatMap((group) => group.models).find((model) => model.id === normalized.model);
|
|
2194
|
+
}
|
|
2094
2195
|
|
|
2095
2196
|
// plugin-src/client/model-setting.js
|
|
2096
2197
|
var SET_MODEL_ENDPOINT = "bot.model.set";
|
|
2097
2198
|
var ModelCatalogContext = React4.createContext(EMPTY_MODEL_CATALOG);
|
|
2098
|
-
function
|
|
2099
|
-
return
|
|
2199
|
+
function chevron(open = false) {
|
|
2200
|
+
return h2(
|
|
2201
|
+
"svg",
|
|
2202
|
+
{
|
|
2203
|
+
width: 14,
|
|
2204
|
+
height: 14,
|
|
2205
|
+
viewBox: "0 0 16 16",
|
|
2206
|
+
"aria-hidden": true,
|
|
2207
|
+
className: "dim-modelChevron",
|
|
2208
|
+
style: open ? { transform: "rotate(90deg)" } : void 0
|
|
2209
|
+
},
|
|
2210
|
+
h2("path", { d: "m6 4 4 4-4 4", fill: "none", stroke: "currentColor", strokeWidth: 1.5 })
|
|
2211
|
+
);
|
|
2100
2212
|
}
|
|
2101
2213
|
function ModelEditor({ model = null, disabled = false, onSave }) {
|
|
2102
|
-
const catalog = normalizeModelCatalog(
|
|
2103
|
-
|
|
2104
|
-
);
|
|
2105
|
-
const
|
|
2106
|
-
const
|
|
2214
|
+
const catalog = normalizeModelCatalog(React4.useContext(ModelCatalogContext));
|
|
2215
|
+
const id6 = React4.useId();
|
|
2216
|
+
const rootRef = React4.useRef(null);
|
|
2217
|
+
const menuRef = React4.useRef(null);
|
|
2218
|
+
const triggerRef = React4.useRef(null);
|
|
2219
|
+
const restoreFocusRef = React4.useRef(false);
|
|
2220
|
+
const savingRef = React4.useRef(false);
|
|
2221
|
+
const [pane, setPane] = React4.useState(null);
|
|
2107
2222
|
const [saving, setSaving] = React4.useState(false);
|
|
2108
2223
|
const [error, setError] = React4.useState(null);
|
|
2109
|
-
const
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
const
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2224
|
+
const current = normalizeModelSelection(model);
|
|
2225
|
+
const entry = modelCatalogEntry(catalog, current);
|
|
2226
|
+
const currentAvailable = !current || Boolean(entry);
|
|
2227
|
+
const reasoning = entry?.reasoning;
|
|
2228
|
+
const effort = current?.reasoningEffort;
|
|
2229
|
+
const effectiveEffort = effort ?? reasoning?.defaultEffort;
|
|
2230
|
+
const effortEntry = reasoning?.efforts.find((level) => level.id === effectiveEffort);
|
|
2231
|
+
const effortUnavailable = effort !== void 0 && !reasoning?.efforts.some((level) => level.id === effort);
|
|
2232
|
+
const defaultName = reasoning?.efforts.find((level) => level.id === reasoning.defaultEffort)?.name;
|
|
2233
|
+
const defaultLabel = localizeText("\u8DDF\u968F\u6A21\u578B\u9ED8\u8BA4") + (defaultName ? ` \xB7 ${defaultName}` : "");
|
|
2234
|
+
const effortLabel = !current ? localizeText("\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B") : effort === void 0 ? defaultLabel : effortEntry?.name ?? effort;
|
|
2235
|
+
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;
|
|
2236
|
+
const effortDisabled = !current || !currentAvailable || !reasoning && effort === void 0;
|
|
2237
|
+
const close = (restoreFocus = false) => {
|
|
2238
|
+
restoreFocusRef.current = restoreFocus;
|
|
2239
|
+
setPane(null);
|
|
2240
|
+
};
|
|
2241
|
+
React4.useEffect(() => {
|
|
2242
|
+
if (!pane && !saving && !disabled && restoreFocusRef.current) {
|
|
2243
|
+
restoreFocusRef.current = false;
|
|
2244
|
+
triggerRef.current?.focus();
|
|
2118
2245
|
}
|
|
2119
|
-
}
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2246
|
+
}, [pane, saving, disabled]);
|
|
2247
|
+
React4.useEffect(() => {
|
|
2248
|
+
if (!pane) return void 0;
|
|
2249
|
+
const options = menuRef.current?.querySelectorAll('[role="menuitemradio"]');
|
|
2250
|
+
const selected = menuRef.current?.querySelector('[aria-checked="true"]');
|
|
2251
|
+
(selected ?? options?.[0])?.focus();
|
|
2252
|
+
const outside = (event) => {
|
|
2253
|
+
if (!rootRef.current?.contains(event.target)) setPane(null);
|
|
2254
|
+
};
|
|
2255
|
+
globalThis.document?.addEventListener("mousedown", outside);
|
|
2256
|
+
return () => globalThis.document?.removeEventListener("mousedown", outside);
|
|
2257
|
+
}, [pane]);
|
|
2258
|
+
const save = async (next) => {
|
|
2259
|
+
if (savingRef.current || disabled) return;
|
|
2260
|
+
if (sameModelSelection(current, next)) {
|
|
2261
|
+
close(true);
|
|
2262
|
+
return;
|
|
2263
|
+
}
|
|
2264
|
+
savingRef.current = true;
|
|
2126
2265
|
setSaving(true);
|
|
2127
2266
|
setError(null);
|
|
2128
2267
|
try {
|
|
2129
2268
|
await onSave?.(next);
|
|
2269
|
+
close(true);
|
|
2130
2270
|
} catch (cause) {
|
|
2131
2271
|
setError(cause?.message ?? "\u6A21\u578B\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
2132
2272
|
} finally {
|
|
2273
|
+
savingRef.current = false;
|
|
2133
2274
|
setSaving(false);
|
|
2134
2275
|
}
|
|
2135
2276
|
};
|
|
2277
|
+
const option = (key, label, description, selected, next) => h2(
|
|
2278
|
+
"button",
|
|
2279
|
+
{
|
|
2280
|
+
key,
|
|
2281
|
+
type: "button",
|
|
2282
|
+
role: "menuitemradio",
|
|
2283
|
+
"aria-checked": selected,
|
|
2284
|
+
className: "dim-modelOption",
|
|
2285
|
+
disabled: disabled || saving,
|
|
2286
|
+
onClick: () => {
|
|
2287
|
+
void save(next);
|
|
2288
|
+
}
|
|
2289
|
+
},
|
|
2290
|
+
h2(
|
|
2291
|
+
"span",
|
|
2292
|
+
{ className: "dim-modelOptionCopy" },
|
|
2293
|
+
h2("span", { className: "dim-modelOptionName" }, label),
|
|
2294
|
+
description ? h2("span", { className: "dim-modelDescription" }, description) : null
|
|
2295
|
+
),
|
|
2296
|
+
h2("span", { className: "dim-modelCheck", "aria-hidden": true }, selected ? "\u2713" : "")
|
|
2297
|
+
);
|
|
2298
|
+
const row = (key, label, value, blocked = false) => h2(
|
|
2299
|
+
"button",
|
|
2300
|
+
{
|
|
2301
|
+
type: "button",
|
|
2302
|
+
className: "dim-modelRow",
|
|
2303
|
+
disabled: disabled || saving || blocked,
|
|
2304
|
+
"aria-label": label,
|
|
2305
|
+
"aria-haspopup": "menu",
|
|
2306
|
+
"aria-expanded": pane === key,
|
|
2307
|
+
"aria-controls": pane === key ? `${id6}-menu` : void 0,
|
|
2308
|
+
"aria-describedby": key === "effort" && effortHint ? `${id6}-hint` : void 0,
|
|
2309
|
+
onClick: (event) => {
|
|
2310
|
+
triggerRef.current = event.currentTarget;
|
|
2311
|
+
setPane(pane === key ? null : key);
|
|
2312
|
+
}
|
|
2313
|
+
},
|
|
2314
|
+
h2("span", { className: "dim-modelRowLabel" }, label),
|
|
2315
|
+
h2("span", { className: "dim-modelValue", title: value }, value),
|
|
2316
|
+
chevron(pane === key)
|
|
2317
|
+
);
|
|
2136
2318
|
return h2(
|
|
2137
2319
|
"div",
|
|
2138
|
-
{
|
|
2320
|
+
{
|
|
2321
|
+
ref: rootRef,
|
|
2322
|
+
className: "dim-preset dim-modelSetting",
|
|
2323
|
+
onBlur: (event) => {
|
|
2324
|
+
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) close();
|
|
2325
|
+
},
|
|
2326
|
+
onKeyDown: (event) => {
|
|
2327
|
+
if (!pane) return;
|
|
2328
|
+
if (event.key === "Escape") {
|
|
2329
|
+
event.preventDefault();
|
|
2330
|
+
event.stopPropagation();
|
|
2331
|
+
close(true);
|
|
2332
|
+
}
|
|
2333
|
+
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
|
|
2334
|
+
const items = [...menuRef.current?.querySelectorAll('[role="menuitemradio"]:not(:disabled)') ?? []];
|
|
2335
|
+
if (!items.length) return;
|
|
2336
|
+
event.preventDefault();
|
|
2337
|
+
const at = items.indexOf(globalThis.document?.activeElement);
|
|
2338
|
+
const next = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : (at + (event.key === "ArrowDown" ? 1 : -1) + items.length) % items.length;
|
|
2339
|
+
items[next]?.focus();
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2139
2342
|
h2(
|
|
2140
2343
|
"div",
|
|
2141
2344
|
{ className: "dim-presetHeader" },
|
|
2142
2345
|
h2(
|
|
2143
2346
|
"span",
|
|
2144
2347
|
{ className: "dim-presetTitle" },
|
|
2145
|
-
|
|
2348
|
+
"\u6A21\u578B\u4E0E\u601D\u8003\u5F3A\u5EA6",
|
|
2146
2349
|
h2(
|
|
2147
2350
|
"span",
|
|
2148
2351
|
{ className: "dim-presetHelp" },
|
|
2149
|
-
h2(
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2352
|
+
h2(
|
|
2353
|
+
"button",
|
|
2354
|
+
{
|
|
2355
|
+
type: "button",
|
|
2356
|
+
className: "dim-presetHelpButton",
|
|
2357
|
+
"aria-label": "\u67E5\u770B\u6A21\u578B\u8BBE\u7F6E\u8BF4\u660E",
|
|
2358
|
+
"aria-describedby": `${id6}-help`
|
|
2359
|
+
},
|
|
2360
|
+
h2("span", { "aria-hidden": true }, "?")
|
|
2361
|
+
),
|
|
2362
|
+
h2(
|
|
2363
|
+
"span",
|
|
2364
|
+
{ id: `${id6}-help`, className: "dim-presetTooltip", role: "tooltip" },
|
|
2365
|
+
"\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"
|
|
2366
|
+
)
|
|
2160
2367
|
)
|
|
2161
2368
|
),
|
|
2162
|
-
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
2369
|
+
saving ? h2("span", { className: "dim-presetStatus", role: "status" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
2163
2370
|
),
|
|
2164
|
-
|
|
2165
|
-
|
|
2371
|
+
row("model", "\u6A21\u578B", entry?.name ?? (current ? modelSelectionId(current) : localizeText("\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B"))),
|
|
2372
|
+
row("effort", "\u601D\u8003\u5F3A\u5EA6", effortLabel, effortDisabled),
|
|
2373
|
+
pane ? h2(
|
|
2374
|
+
"div",
|
|
2166
2375
|
{
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
"aria-label": "\u6A21\u578B",
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
}
|
|
2376
|
+
ref: menuRef,
|
|
2377
|
+
id: `${id6}-menu`,
|
|
2378
|
+
role: "menu",
|
|
2379
|
+
"aria-label": pane === "model" ? "\u6A21\u578B" : "\u601D\u8003\u5F3A\u5EA6",
|
|
2380
|
+
"aria-busy": saving,
|
|
2381
|
+
className: "dim-modelMenu"
|
|
2174
2382
|
},
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2383
|
+
pane === "model" ? [
|
|
2384
|
+
option("default", "\u8DDF\u968F\u9ED8\u8BA4\u6A21\u578B", null, !current, null),
|
|
2385
|
+
...catalog.groups.map((group) => h2(
|
|
2386
|
+
"section",
|
|
2387
|
+
{ key: group.id, role: "group", "aria-label": group.name },
|
|
2388
|
+
h2("div", { className: "dim-modelGroupTitle" }, group.name),
|
|
2389
|
+
...group.models.map((choice) => {
|
|
2390
|
+
const selected = current?.provider === group.id && current?.model === choice.id;
|
|
2391
|
+
return option(
|
|
2392
|
+
choice.id,
|
|
2393
|
+
choice.name,
|
|
2394
|
+
choice.description ?? `${group.id}/${choice.id}`,
|
|
2395
|
+
selected,
|
|
2396
|
+
selected ? current : { provider: group.id, model: choice.id }
|
|
2397
|
+
);
|
|
2398
|
+
})
|
|
2399
|
+
))
|
|
2400
|
+
] : [
|
|
2401
|
+
option(
|
|
2402
|
+
"provider-default",
|
|
2403
|
+
defaultLabel,
|
|
2404
|
+
"\u4F7F\u7528\u6A21\u578B\u6216\u670D\u52A1\u63D0\u4F9B\u65B9\u7684\u9ED8\u8BA4\u601D\u8003\u5F3A\u5EA6\u3002",
|
|
2405
|
+
effort === void 0,
|
|
2406
|
+
current ? { provider: current.provider, model: current.model } : null
|
|
2407
|
+
),
|
|
2408
|
+
...(reasoning?.efforts ?? []).map((level) => option(
|
|
2409
|
+
`effort:${level.id}`,
|
|
2410
|
+
level.name,
|
|
2411
|
+
level.description,
|
|
2412
|
+
effort === level.id,
|
|
2413
|
+
{ ...current, reasoningEffort: level.id }
|
|
2414
|
+
))
|
|
2415
|
+
]
|
|
2416
|
+
) : null,
|
|
2417
|
+
effortHint ? h2("p", {
|
|
2418
|
+
id: `${id6}-hint`,
|
|
2419
|
+
className: "dim-modelHint",
|
|
2420
|
+
role: effortUnavailable ? "status" : void 0
|
|
2421
|
+
}, effortHint) : null,
|
|
2191
2422
|
error || !currentAvailable ? h2(
|
|
2192
2423
|
"p",
|
|
2193
2424
|
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
|
@@ -2238,11 +2469,11 @@ function normalizeAccessPolicyUserId(value) {
|
|
|
2238
2469
|
value = String(value);
|
|
2239
2470
|
}
|
|
2240
2471
|
if (typeof value !== "string") throw invalidAccessPolicy("\u7528\u6237\u6807\u8BC6\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u3002");
|
|
2241
|
-
const
|
|
2242
|
-
if (!
|
|
2472
|
+
const id6 = value.trim();
|
|
2473
|
+
if (!id6 || id6.length > ACCESS_POLICY_USER_ID_MAX_LENGTH || CONTROL_CHARACTERS.test(id6)) {
|
|
2243
2474
|
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
2475
|
}
|
|
2245
|
-
return
|
|
2476
|
+
return id6;
|
|
2246
2477
|
}
|
|
2247
2478
|
function validateAccessPolicyUser(input) {
|
|
2248
2479
|
if (!hasExactKeys(input, USER_KEYS)) {
|
|
@@ -2259,7 +2490,7 @@ function validateAccessPolicyUser(input) {
|
|
|
2259
2490
|
function validateUsers(input, { listMessage, duplicateMessage }) {
|
|
2260
2491
|
if (!Array.isArray(input)) throw invalidAccessPolicy(listMessage);
|
|
2261
2492
|
const users = input.map(validateAccessPolicyUser);
|
|
2262
|
-
if (new Set(users.map(({ id:
|
|
2493
|
+
if (new Set(users.map(({ id: id6 }) => id6)).size !== users.length) {
|
|
2263
2494
|
throw invalidAccessPolicy(duplicateMessage);
|
|
2264
2495
|
}
|
|
2265
2496
|
return Object.freeze(users);
|
|
@@ -2481,8 +2712,8 @@ function optionalString(value, maxLength = 240) {
|
|
|
2481
2712
|
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
2482
2713
|
}
|
|
2483
2714
|
function opaqueId(value) {
|
|
2484
|
-
const
|
|
2485
|
-
return
|
|
2715
|
+
const id6 = optionalString(value, 128);
|
|
2716
|
+
return id6 && /^[a-z\d_-]+$/i.test(id6) ? id6 : void 0;
|
|
2486
2717
|
}
|
|
2487
2718
|
function timestamp(value) {
|
|
2488
2719
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -2813,13 +3044,13 @@ function CollapsibleAccountSection({
|
|
|
2813
3044
|
defaultOpen = false,
|
|
2814
3045
|
open: controlledOpen,
|
|
2815
3046
|
onToggle,
|
|
2816
|
-
id:
|
|
3047
|
+
id: id6,
|
|
2817
3048
|
className = "",
|
|
2818
3049
|
children
|
|
2819
3050
|
}) {
|
|
2820
3051
|
const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
|
|
2821
3052
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
2822
|
-
const contentId =
|
|
3053
|
+
const contentId = id6 ? `${id6}-content` : void 0;
|
|
2823
3054
|
const toggle = () => {
|
|
2824
3055
|
if (controlledOpen === void 0) setUncontrolledOpen((value) => !value);
|
|
2825
3056
|
onToggle?.(!open);
|
|
@@ -3492,7 +3723,7 @@ function ContextEnhancementScopeEditor({
|
|
|
3492
3723
|
)
|
|
3493
3724
|
);
|
|
3494
3725
|
}
|
|
3495
|
-
function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id:
|
|
3726
|
+
function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id6 }) {
|
|
3496
3727
|
const [draft, setDraft] = React9.useState(() => {
|
|
3497
3728
|
const normalized = normalizeContextEnhancementConfig(config);
|
|
3498
3729
|
return {
|
|
@@ -3584,7 +3815,7 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
|
|
|
3584
3815
|
}, h2(
|
|
3585
3816
|
"section",
|
|
3586
3817
|
{
|
|
3587
|
-
id:
|
|
3818
|
+
id: id6,
|
|
3588
3819
|
ref: dialogRef,
|
|
3589
3820
|
className: "dim-contextDialog",
|
|
3590
3821
|
role: "dialog",
|
|
@@ -3850,7 +4081,7 @@ function messageErrorTime(value) {
|
|
|
3850
4081
|
return null;
|
|
3851
4082
|
}
|
|
3852
4083
|
}
|
|
3853
|
-
function ChannelListHeading({ className = "", id:
|
|
4084
|
+
function ChannelListHeading({ className = "", id: id6, title, connectionLabel }) {
|
|
3854
4085
|
const helpId = React11.useId();
|
|
3855
4086
|
return h2(
|
|
3856
4087
|
"div",
|
|
@@ -3858,7 +4089,7 @@ function ChannelListHeading({ className = "", id: id5, title, connectionLabel })
|
|
|
3858
4089
|
h2(
|
|
3859
4090
|
"div",
|
|
3860
4091
|
{ className: "dim-listTitle" },
|
|
3861
|
-
h2("h3",
|
|
4092
|
+
h2("h3", id6 ? { id: id6 } : null, title),
|
|
3862
4093
|
h2(
|
|
3863
4094
|
"span",
|
|
3864
4095
|
{ className: "dim-channelHelp" },
|
|
@@ -5117,7 +5348,7 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
5117
5348
|
function createTokenChannelApi(channel4, connectionSummary, {
|
|
5118
5349
|
normalizeBotExtension = () => ({})
|
|
5119
5350
|
} = {}) {
|
|
5120
|
-
const
|
|
5351
|
+
const unwrapRpcResult14 = (result) => {
|
|
5121
5352
|
if (!isRecord2(result) || typeof result.ok !== "boolean") {
|
|
5122
5353
|
throw new Error(`${channel4} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
|
|
5123
5354
|
}
|
|
@@ -5128,7 +5359,7 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5128
5359
|
}
|
|
5129
5360
|
return result.value;
|
|
5130
5361
|
};
|
|
5131
|
-
const
|
|
5362
|
+
const normalizeBot8 = (value) => {
|
|
5132
5363
|
if (!isRecord2(value) || !id(value.botId)) return void 0;
|
|
5133
5364
|
const connected = value.connected === true;
|
|
5134
5365
|
const state = ACCOUNT_STATES2.has(value.state) ? value.state : "offline";
|
|
@@ -5162,12 +5393,12 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5162
5393
|
...isRecord2(extension) ? extension : {}
|
|
5163
5394
|
};
|
|
5164
5395
|
};
|
|
5165
|
-
const
|
|
5396
|
+
const normalizeSnapshot10 = (value) => {
|
|
5166
5397
|
const source = isRecord2(value?.snapshot) ? value.snapshot : value;
|
|
5167
5398
|
if (!isRecord2(source) || !Array.isArray(source.bots)) {
|
|
5168
5399
|
throw new Error(`${channel4} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
|
|
5169
5400
|
}
|
|
5170
|
-
const bots = source.bots.map(
|
|
5401
|
+
const bots = source.bots.map(normalizeBot8).filter(Boolean);
|
|
5171
5402
|
return {
|
|
5172
5403
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
5173
5404
|
bots,
|
|
@@ -5176,11 +5407,11 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
5176
5407
|
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
5177
5408
|
};
|
|
5178
5409
|
};
|
|
5179
|
-
const
|
|
5410
|
+
const presentError14 = (error) => ({
|
|
5180
5411
|
code: text2(error?.code, `${channel4.toUpperCase()}_ERROR`, 80),
|
|
5181
5412
|
message: text2(error?.message, `${channel4}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
|
|
5182
5413
|
});
|
|
5183
|
-
return Object.freeze({ unwrapRpcResult:
|
|
5414
|
+
return Object.freeze({ unwrapRpcResult: unwrapRpcResult14, normalizeSnapshot: normalizeSnapshot10, presentError: presentError14 });
|
|
5184
5415
|
}
|
|
5185
5416
|
|
|
5186
5417
|
// plugin-src/client/channels/discord/api.js
|
|
@@ -5245,7 +5476,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5245
5476
|
AccountSettings = null,
|
|
5246
5477
|
accountSettingsEndpoint = null
|
|
5247
5478
|
} = definition;
|
|
5248
|
-
function
|
|
5479
|
+
function AccountCard6({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onModelSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
5249
5480
|
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
5250
5481
|
const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
|
|
5251
5482
|
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
@@ -5536,7 +5767,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5536
5767
|
title: `\u5DF2\u63A5\u5165\u7684 ${channel4} \u673A\u5668\u4EBA`,
|
|
5537
5768
|
connectionLabel
|
|
5538
5769
|
}),
|
|
5539
|
-
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(
|
|
5770
|
+
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard6, {
|
|
5540
5771
|
account,
|
|
5541
5772
|
busy: busyByBot[account.botId],
|
|
5542
5773
|
testNotice: testNoticeByBot[account.botId],
|
|
@@ -5698,7 +5929,7 @@ function createTokenChannelSettings(definition) {
|
|
|
5698
5929
|
)
|
|
5699
5930
|
)));
|
|
5700
5931
|
}
|
|
5701
|
-
return { SettingsTab, AccountCard:
|
|
5932
|
+
return { SettingsTab, AccountCard: AccountCard6 };
|
|
5702
5933
|
}
|
|
5703
5934
|
|
|
5704
5935
|
// plugin-src/client/channels/discord/styles.js
|
|
@@ -6428,14 +6659,14 @@ var HEALTH_LABELS = {
|
|
|
6428
6659
|
offline: "\u8FDE\u63A5\u4E2D\u65AD",
|
|
6429
6660
|
error: "\u9700\u8981\u5904\u7406"
|
|
6430
6661
|
};
|
|
6431
|
-
function formatCheckedTime(
|
|
6432
|
-
if (!
|
|
6662
|
+
function formatCheckedTime(timestamp8) {
|
|
6663
|
+
if (!timestamp8) return "\u5C1A\u672A\u68C0\u67E5";
|
|
6433
6664
|
try {
|
|
6434
6665
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
6435
6666
|
hour: "2-digit",
|
|
6436
6667
|
minute: "2-digit",
|
|
6437
6668
|
second: "2-digit"
|
|
6438
|
-
}).format(new Date(
|
|
6669
|
+
}).format(new Date(timestamp8));
|
|
6439
6670
|
} catch {
|
|
6440
6671
|
return "\u521A\u521A";
|
|
6441
6672
|
}
|
|
@@ -6489,6 +6720,7 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
|
6489
6720
|
}
|
|
6490
6721
|
function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
6491
6722
|
const titleId = React15.useId();
|
|
6723
|
+
const helpId = `${titleId}-help`;
|
|
6492
6724
|
const current = value === true ? "on" : "off";
|
|
6493
6725
|
const [saving, setSaving] = React15.useState(false);
|
|
6494
6726
|
const [error, setError] = React15.useState(null);
|
|
@@ -6514,7 +6746,26 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
6514
6746
|
h2(
|
|
6515
6747
|
"div",
|
|
6516
6748
|
{ className: "dim-feishuGroupControlHeader" },
|
|
6517
|
-
h2(
|
|
6749
|
+
h2(
|
|
6750
|
+
"div",
|
|
6751
|
+
{ className: "dim-presetTitle" },
|
|
6752
|
+
h2("h3", { id: titleId }, "\u5206\u6B65\u76F4\u63A8"),
|
|
6753
|
+
h2(
|
|
6754
|
+
"span",
|
|
6755
|
+
{ className: "dim-presetHelp" },
|
|
6756
|
+
h2("button", {
|
|
6757
|
+
type: "button",
|
|
6758
|
+
className: "dim-presetHelpButton",
|
|
6759
|
+
"aria-label": "\u67E5\u770B\u5206\u6B65\u76F4\u63A8\u8BF4\u660E",
|
|
6760
|
+
"aria-describedby": helpId
|
|
6761
|
+
}, h2("span", { "aria-hidden": "true" }, "?")),
|
|
6762
|
+
h2("span", {
|
|
6763
|
+
id: helpId,
|
|
6764
|
+
className: "dim-presetTooltip",
|
|
6765
|
+
role: "tooltip"
|
|
6766
|
+
}, "\u5F00\u542F\u540E\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E")
|
|
6767
|
+
)
|
|
6768
|
+
),
|
|
6518
6769
|
saving ? h2("span", { className: "dim-feishuGroupControlStatus", role: "status" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
6519
6770
|
),
|
|
6520
6771
|
h2(
|
|
@@ -6531,11 +6782,6 @@ function StepPushEditor({ value = false, disabled = false, onSave }) {
|
|
|
6531
6782
|
h2("option", { value: "off" }, "\u5173\u95ED\uFF08\u4FDD\u6301\u6D41\u5F0F\u5361\u6A21\u5F0F\uFF09"),
|
|
6532
6783
|
h2("option", { value: "on" }, "\u5F00\u542F\uFF08\u9010\u6B65\u63A8\u9001\u5DE5\u5177\u8C03\u7528\u4E0E\u8FC7\u7A0B\u8BF4\u660E\uFF09")
|
|
6533
6784
|
),
|
|
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
6785
|
error ? h2("p", {
|
|
6540
6786
|
className: "dim-feishuGroupError",
|
|
6541
6787
|
role: "alert"
|
|
@@ -6993,15 +7239,15 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
6993
7239
|
if (targetedUpdate && (provision2.operation !== operation || provision2.botId !== botId)) {
|
|
6994
7240
|
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
7241
|
}
|
|
6996
|
-
const
|
|
6997
|
-
setNow(
|
|
7242
|
+
const timestamp8 = Date.now();
|
|
7243
|
+
setNow(timestamp8);
|
|
6998
7244
|
setModel((current) => ({
|
|
6999
7245
|
...current,
|
|
7000
7246
|
provisioning: {
|
|
7001
7247
|
phase: "qr",
|
|
7002
7248
|
...provision2,
|
|
7003
7249
|
...botName ? { botName } : {},
|
|
7004
|
-
durationMs: Math.max(1, provision2.expiresAt -
|
|
7250
|
+
durationMs: Math.max(1, provision2.expiresAt - timestamp8),
|
|
7005
7251
|
expired: false
|
|
7006
7252
|
}
|
|
7007
7253
|
}));
|
|
@@ -7118,9 +7364,9 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
7118
7364
|
React15.useEffect(() => {
|
|
7119
7365
|
if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
|
|
7120
7366
|
const tick = () => {
|
|
7121
|
-
const
|
|
7122
|
-
setNow(
|
|
7123
|
-
if (
|
|
7367
|
+
const timestamp8 = Date.now();
|
|
7368
|
+
setNow(timestamp8);
|
|
7369
|
+
if (timestamp8 >= countdownExpiresAt) {
|
|
7124
7370
|
setModel((current) => current.provisioning?.attemptId === countdownAttemptId ? { ...current, provisioning: { ...current.provisioning, expired: true } } : current);
|
|
7125
7371
|
}
|
|
7126
7372
|
};
|
|
@@ -10353,17 +10599,13 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
10353
10599
|
)));
|
|
10354
10600
|
}
|
|
10355
10601
|
|
|
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({
|
|
10602
|
+
// plugin-src/client/channels/wecom-app/api.js
|
|
10603
|
+
var WECOM_APP_RPC_CHANNEL = "/wecom-app";
|
|
10604
|
+
var WECOM_APP_ENDPOINTS = Object.freeze({
|
|
10362
10605
|
status: "connection.status",
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
cancelProvisioning: "provision.cancel",
|
|
10606
|
+
bindApp: "bot.bind",
|
|
10607
|
+
updateSettings: "bot.settings.update",
|
|
10608
|
+
resetCallbackSecret: "bot.callback-secret.reset",
|
|
10367
10609
|
reconnectBot: "bot.reconnect",
|
|
10368
10610
|
deleteBot: "bot.delete",
|
|
10369
10611
|
setWorkspace: "bot.workspace.set",
|
|
@@ -10373,25 +10615,24 @@ var WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
10373
10615
|
setAccessPolicy: "bot.access-policy.set"
|
|
10374
10616
|
});
|
|
10375
10617
|
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
10618
|
function isRecord6(value) {
|
|
10388
10619
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
10389
10620
|
}
|
|
10390
|
-
function
|
|
10391
|
-
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
10621
|
+
function text5(value, fallback, max = 240) {
|
|
10622
|
+
return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
|
|
10623
|
+
}
|
|
10624
|
+
function id4(value) {
|
|
10625
|
+
const result = text5(value, "", 128);
|
|
10626
|
+
return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
|
|
10627
|
+
}
|
|
10628
|
+
function optionalUrl(value) {
|
|
10629
|
+
const raw = text5(value, "", 512);
|
|
10630
|
+
return /^https?:\/\//iu.test(raw) ? raw : null;
|
|
10392
10631
|
}
|
|
10393
10632
|
function timestamp5(value) {
|
|
10394
|
-
|
|
10633
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
10634
|
+
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
10635
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
10395
10636
|
}
|
|
10396
10637
|
function normalizeTestMessage4(value) {
|
|
10397
10638
|
if (!isRecord6(value)) return null;
|
|
@@ -10401,145 +10642,984 @@ function normalizeTestMessage4(value) {
|
|
|
10401
10642
|
return { sent: false, code };
|
|
10402
10643
|
}
|
|
10403
10644
|
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
|
-
}
|
|
10645
|
+
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
10646
|
if (!result.ok) {
|
|
10408
|
-
const error = new Error(
|
|
10409
|
-
error.code =
|
|
10647
|
+
const error = new Error(text5(result.error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25"));
|
|
10648
|
+
error.code = text5(result.error?.code, "WECOM_APP_RPC_ERROR", 80);
|
|
10410
10649
|
throw error;
|
|
10411
10650
|
}
|
|
10412
10651
|
return result.value;
|
|
10413
10652
|
}
|
|
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
10653
|
function normalizeBot5(value) {
|
|
10454
|
-
if (!isRecord6(value) || !
|
|
10455
|
-
const state = ACCOUNT_STATES5.has(value.state) ? value.state : "error";
|
|
10654
|
+
if (!isRecord6(value) || !id4(value.botId)) return void 0;
|
|
10456
10655
|
const connected = value.connected === true;
|
|
10656
|
+
const state = ACCOUNT_STATES5.has(value.state) ? value.state : "offline";
|
|
10457
10657
|
return {
|
|
10458
|
-
botId:
|
|
10459
|
-
state: connected ? "connected" : state,
|
|
10658
|
+
botId: id4(value.botId),
|
|
10460
10659
|
connected,
|
|
10461
|
-
|
|
10462
|
-
workspace:
|
|
10660
|
+
state: connected ? "connected" : state,
|
|
10661
|
+
workspace: text5(value.workspace, "", 4096),
|
|
10463
10662
|
model: normalizeModelSelection(value.model),
|
|
10464
10663
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
10465
10664
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
10466
10665
|
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
10467
10666
|
bot: {
|
|
10468
|
-
name:
|
|
10469
|
-
|
|
10667
|
+
name: text5(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", 100),
|
|
10668
|
+
corpIdMasked: text5(value.bot?.corpIdMasked, "\u4F01\u4E1A ID \u5DF2\u4FDD\u5B58", 140),
|
|
10669
|
+
agentId: text5(value.bot?.agentId, "", 32),
|
|
10670
|
+
apiBaseUrl: optionalUrl(value.bot?.apiBaseUrl) ?? "",
|
|
10671
|
+
callbackBaseUrl: optionalUrl(value.bot?.callbackBaseUrl) ?? "",
|
|
10672
|
+
streamEnabled: value.bot?.streamEnabled !== false,
|
|
10673
|
+
callbackUrl: optionalUrl(value.bot?.callbackUrl) ?? ""
|
|
10470
10674
|
},
|
|
10471
10675
|
health: {
|
|
10472
|
-
|
|
10473
|
-
summary: string(value.health?.summary, connected ? "\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38" : "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA"),
|
|
10676
|
+
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
10677
|
lastCheckedAt: timestamp5(value.health?.lastCheckedAt)
|
|
10475
10678
|
},
|
|
10476
|
-
stats: {
|
|
10477
|
-
messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
|
|
10478
|
-
messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
|
|
10479
|
-
},
|
|
10480
10679
|
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
10481
10680
|
error: isRecord6(value.error) ? {
|
|
10482
|
-
code:
|
|
10483
|
-
message:
|
|
10681
|
+
code: text5(value.error.code, "WECOM_APP_ACCOUNT_ERROR", 80),
|
|
10682
|
+
message: text5(value.error.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
|
|
10484
10683
|
} : null
|
|
10485
10684
|
};
|
|
10486
10685
|
}
|
|
10487
10686
|
function normalizeSnapshot7(value) {
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
const bots = value.bots.map(normalizeBot5).filter(Boolean);
|
|
10687
|
+
const source = isRecord6(value?.snapshot) ? value.snapshot : value;
|
|
10688
|
+
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");
|
|
10689
|
+
const bots = source.bots.map(normalizeBot5).filter(Boolean);
|
|
10492
10690
|
return {
|
|
10493
|
-
|
|
10494
|
-
revision: Number(value.revision) || 0,
|
|
10495
|
-
state: string(value.state, "offline"),
|
|
10691
|
+
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
10496
10692
|
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)
|
|
10693
|
+
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
10694
|
+
testMessage: normalizeTestMessage4(source.testMessage),
|
|
10695
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
10696
|
+
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
10505
10697
|
};
|
|
10506
10698
|
}
|
|
10507
10699
|
function presentError8(error) {
|
|
10508
10700
|
return {
|
|
10509
|
-
code:
|
|
10510
|
-
message:
|
|
10701
|
+
code: text5(error?.code, "WECOM_APP_ERROR", 80),
|
|
10702
|
+
message: text5(error?.message, "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
10511
10703
|
};
|
|
10512
10704
|
}
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10705
|
+
|
|
10706
|
+
// plugin-src/client/channels/wecom-app/index.js
|
|
10707
|
+
var React20 = __toESM(require("react"), 1);
|
|
10708
|
+
|
|
10709
|
+
// plugin-src/client/channels/wecom-app/styles.js
|
|
10710
|
+
var WECOM_APP_STYLE_ID = "xmanrui-dsh-im-wecom-app-settings";
|
|
10711
|
+
var CSS9 = String.raw`
|
|
10712
|
+
.dwecomapp-page { --ddt-accent: #07c160; --ddt-accent-deep: #059a4c; --ddt-accent-wash: #eefaf3; }
|
|
10713
|
+
.dwecomapp-avatar, .dwecomapp-brand { color: #07c160; background: #fff; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); }
|
|
10714
|
+
.dwecomapp-avatar svg, .dwecomapp-brand svg { display: block; }
|
|
10715
|
+
.dim-appFieldGrid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
|
|
10716
|
+
.dim-callbackBox { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border: 1px dashed var(--dsw-alias-border-l2, #e5e6eb); border-radius: 8px; }
|
|
10717
|
+
.dim-callbackBox strong { font-size: 12px; color: var(--dsw-alias-text-secondary, #646a73); }
|
|
10718
|
+
.dim-callbackRow { display: flex; gap: 8px; align-items: center; }
|
|
10719
|
+
.dim-callbackRow input { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
|
|
10720
|
+
.dim-appSwitchRow { display: flex; align-items: center; gap: 8px; font-size: 13px; }
|
|
10721
|
+
`;
|
|
10722
|
+
function installWecomAppStyles() {
|
|
10723
|
+
if (typeof document === "undefined") return () => {
|
|
10724
|
+
};
|
|
10725
|
+
const existing = document.querySelector(`style[data-plugin-css="${WECOM_APP_STYLE_ID}"]`);
|
|
10726
|
+
if (existing) return () => {
|
|
10727
|
+
};
|
|
10728
|
+
const style = document.createElement("style");
|
|
10729
|
+
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
10730
|
+
style.dataset.pluginCss = WECOM_APP_STYLE_ID;
|
|
10731
|
+
style.textContent = CSS9;
|
|
10732
|
+
document.head.appendChild(style);
|
|
10733
|
+
return () => style.remove();
|
|
10516
10734
|
}
|
|
10517
10735
|
|
|
10518
|
-
// plugin-src/client/channels/
|
|
10736
|
+
// plugin-src/client/channels/wecom-app/index.js
|
|
10519
10737
|
var Button12 = React20.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
10520
10738
|
return h2("button", {
|
|
10521
10739
|
...props,
|
|
10522
10740
|
ref,
|
|
10523
10741
|
type: "button",
|
|
10524
|
-
className: `
|
|
10742
|
+
className: `ddt-button ${className}`.trim(),
|
|
10525
10743
|
"data-kind": kind
|
|
10526
10744
|
}, children);
|
|
10527
10745
|
});
|
|
10746
|
+
function checkedTime5(value) {
|
|
10747
|
+
if (!value) return "\u5C1A\u672A\u68C0\u67E5";
|
|
10748
|
+
try {
|
|
10749
|
+
return new Intl.DateTimeFormat("zh-CN", {
|
|
10750
|
+
hour: "2-digit",
|
|
10751
|
+
minute: "2-digit",
|
|
10752
|
+
second: "2-digit"
|
|
10753
|
+
}).format(new Date(value));
|
|
10754
|
+
} catch {
|
|
10755
|
+
return "\u521A\u521A";
|
|
10756
|
+
}
|
|
10757
|
+
}
|
|
10528
10758
|
function Heading5({ totals, adding, busy, onAdd, addButtonRef }) {
|
|
10529
10759
|
return h2(
|
|
10530
10760
|
"div",
|
|
10531
|
-
{ className: "
|
|
10761
|
+
{ className: "ddt-heading" },
|
|
10532
10762
|
h2(
|
|
10533
10763
|
"div",
|
|
10534
|
-
{ className: "
|
|
10535
|
-
h2(
|
|
10536
|
-
|
|
10537
|
-
className: "dim-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10764
|
+
{ className: "ddt-tools" },
|
|
10765
|
+
h2(
|
|
10766
|
+
"div",
|
|
10767
|
+
{ className: "dim-bindActions" },
|
|
10768
|
+
h2(Button12, {
|
|
10769
|
+
kind: "primary",
|
|
10770
|
+
className: "dim-scanButton",
|
|
10771
|
+
onClick: onAdd,
|
|
10772
|
+
disabled: adding || busy,
|
|
10773
|
+
ref: addButtonRef,
|
|
10774
|
+
"aria-label": "\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528"
|
|
10775
|
+
}, adding ? "\u6536\u8D77\u8868\u5355" : "\u6DFB\u52A0\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528")
|
|
10776
|
+
),
|
|
10777
|
+
totals.configured > 0 ? h2(
|
|
10778
|
+
"div",
|
|
10779
|
+
{ className: "ddt-badge dim-onlineBadge" },
|
|
10780
|
+
h2("span", null, `${totals.connected} / ${totals.configured} \u5728\u7EBF`)
|
|
10781
|
+
) : null
|
|
10782
|
+
)
|
|
10783
|
+
);
|
|
10784
|
+
}
|
|
10785
|
+
function LoadingView5() {
|
|
10786
|
+
return h2(
|
|
10787
|
+
"div",
|
|
10788
|
+
{ className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView", "aria-busy": "true" },
|
|
10789
|
+
h2("div", { className: "ddt-spinner dim-spinner" }),
|
|
10790
|
+
h2("span", null, "\u6B63\u5728\u8BFB\u53D6\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u72B6\u6001\u2026")
|
|
10791
|
+
);
|
|
10792
|
+
}
|
|
10793
|
+
function EmptyView5({ busy, onStart }) {
|
|
10794
|
+
return h2(
|
|
10795
|
+
"div",
|
|
10796
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
10797
|
+
h2(
|
|
10798
|
+
"div",
|
|
10799
|
+
{ className: "ddt-cardBody ddt-empty dim-surfaceBody dim-emptyView" },
|
|
10800
|
+
h2(
|
|
10801
|
+
"div",
|
|
10802
|
+
{ className: "dim-emptyCopy" },
|
|
10803
|
+
h2(
|
|
10804
|
+
"div",
|
|
10805
|
+
{ className: "ddt-stateLabel dim-stateLabel" },
|
|
10806
|
+
h2("span", { className: "ddt-dot dim-stateDot" }),
|
|
10807
|
+
h2("span", null, "\u5C1A\u672A\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528")
|
|
10808
|
+
),
|
|
10809
|
+
h2("h3", null, "\u5728\u4F01\u4E1A\u5FAE\u4FE1\u4E2D\u521B\u5EFA\u81EA\u5EFA\u5E94\u7528\uFF0C\u5373\u53EF\u5728\u5FAE\u4FE1\u91CC\u4F7F\u7528"),
|
|
10810
|
+
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"),
|
|
10811
|
+
h2(
|
|
10812
|
+
"div",
|
|
10813
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
10814
|
+
h2(Button12, { kind: "primary", onClick: onStart, disabled: busy }, "\u586B\u5199\u5E94\u7528\u53C2\u6570")
|
|
10815
|
+
)
|
|
10816
|
+
),
|
|
10817
|
+
h2(
|
|
10818
|
+
"div",
|
|
10819
|
+
{ className: "ddt-brandMark dim-emptyBrand dwecomapp-brand", "aria-hidden": "true" },
|
|
10820
|
+
h2(WecomLogoGlyph, { size: 64 })
|
|
10821
|
+
)
|
|
10822
|
+
)
|
|
10823
|
+
);
|
|
10824
|
+
}
|
|
10825
|
+
function Field({ label, value, onChange, placeholder, busy, required = false, type = "text" }) {
|
|
10826
|
+
return h2(
|
|
10827
|
+
"label",
|
|
10828
|
+
{ className: "dim-credentialField" },
|
|
10829
|
+
h2("span", null, label),
|
|
10830
|
+
h2("input", {
|
|
10831
|
+
value,
|
|
10832
|
+
onChange: (event) => onChange(event.target.value),
|
|
10833
|
+
placeholder,
|
|
10834
|
+
type,
|
|
10835
|
+
autoCapitalize: "none",
|
|
10836
|
+
autoCorrect: "off",
|
|
10837
|
+
spellCheck: false,
|
|
10838
|
+
autoComplete: "off",
|
|
10839
|
+
disabled: busy,
|
|
10840
|
+
required
|
|
10841
|
+
})
|
|
10842
|
+
);
|
|
10843
|
+
}
|
|
10844
|
+
function BindForm({ busy, error, onSubmit, onCancel }) {
|
|
10845
|
+
const [corpId, setCorpId] = React20.useState("");
|
|
10846
|
+
const [agentId, setAgentId] = React20.useState("");
|
|
10847
|
+
const [secret, setSecret] = React20.useState("");
|
|
10848
|
+
const [token, setToken] = React20.useState("");
|
|
10849
|
+
const [aesKey, setAesKey] = React20.useState("");
|
|
10850
|
+
const [apiBaseUrl, setApiBaseUrl] = React20.useState("");
|
|
10851
|
+
const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState("");
|
|
10852
|
+
const [streamEnabled, setStreamEnabled] = React20.useState(true);
|
|
10853
|
+
const headingId = React20.useId();
|
|
10854
|
+
const formRef = React20.useRef(null);
|
|
10855
|
+
const submit = (event) => {
|
|
10856
|
+
event.preventDefault();
|
|
10857
|
+
if (busy) return;
|
|
10858
|
+
void onSubmit?.({
|
|
10859
|
+
corpId: corpId.trim(),
|
|
10860
|
+
agentId: agentId.trim(),
|
|
10861
|
+
secret: secret.trim(),
|
|
10862
|
+
token: token.trim(),
|
|
10863
|
+
encodingAESKey: aesKey.trim(),
|
|
10864
|
+
apiBaseUrl: apiBaseUrl.trim() || void 0,
|
|
10865
|
+
callbackBaseUrl: callbackBaseUrl.trim() || void 0,
|
|
10866
|
+
streamEnabled
|
|
10867
|
+
});
|
|
10868
|
+
};
|
|
10869
|
+
return h2(
|
|
10870
|
+
"section",
|
|
10871
|
+
{
|
|
10872
|
+
className: "ddt-card dim-surfaceCard dim-credentialPanel",
|
|
10873
|
+
"aria-labelledby": headingId
|
|
10874
|
+
},
|
|
10875
|
+
h2("h3", { id: headingId, className: "dim-credentialTitle" }, "\u7ED1\u5B9A\u4F01\u4E1A\u5FAE\u4FE1\u81EA\u5EFA\u5E94\u7528"),
|
|
10876
|
+
h2(
|
|
10877
|
+
"form",
|
|
10878
|
+
{ ref: formRef, className: "dim-credentialForm", onSubmit: submit },
|
|
10879
|
+
h2(
|
|
10880
|
+
"div",
|
|
10881
|
+
{ className: "dim-appFieldGrid" },
|
|
10882
|
+
h2(Field, { label: "\u4F01\u4E1A ID\uFF08CorpID\uFF09", value: corpId, onChange: setCorpId, placeholder: "\u4F8B\u5982 ww1234567890abcdef", busy, required: true }),
|
|
10883
|
+
h2(Field, { label: "\u5E94\u7528 AgentId", value: agentId, onChange: setAgentId, placeholder: "\u4F8B\u5982 1000002", busy, required: true }),
|
|
10884
|
+
h2(Field, { label: "\u5E94\u7528 Secret", value: secret, onChange: setSecret, placeholder: "\u5E94\u7528\u8BE6\u60C5\u9875\u7684 Secret", busy, required: true, type: "password" }),
|
|
10885
|
+
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" }),
|
|
10886
|
+
h2(Field, { label: "EncodingAESKey", value: aesKey, onChange: setAesKey, placeholder: "43 \u4F4D\u5B57\u6BCD\u6216\u6570\u5B57", busy, required: true, type: "password" }),
|
|
10887
|
+
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 })
|
|
10888
|
+
),
|
|
10889
|
+
h2(
|
|
10890
|
+
"div",
|
|
10891
|
+
{ className: "dim-appFieldGrid" },
|
|
10892
|
+
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 }),
|
|
10893
|
+
h2(
|
|
10894
|
+
"div",
|
|
10895
|
+
{ className: "dim-appSwitchRow" },
|
|
10896
|
+
h2("button", {
|
|
10897
|
+
type: "button",
|
|
10898
|
+
className: "ddt-button dim-streamToggle",
|
|
10899
|
+
"aria-pressed": streamEnabled ? "true" : "false",
|
|
10900
|
+
onClick: () => setStreamEnabled((value) => !value),
|
|
10901
|
+
disabled: busy
|
|
10902
|
+
}, streamEnabled ? "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00" : "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173"),
|
|
10903
|
+
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")
|
|
10904
|
+
)
|
|
10905
|
+
),
|
|
10906
|
+
error ? h2("div", { className: "ddt-inlineError dim-inlineError", role: "alert" }, h2("p", null, error.message)) : null,
|
|
10907
|
+
h2(
|
|
10908
|
+
"div",
|
|
10909
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
10910
|
+
h2(Button12, { kind: "primary", onClick: () => formRef.current?.requestSubmit(), disabled: busy }, busy ? "\u6B63\u5728\u7ED1\u5B9A\u2026" : "\u4FDD\u5B58\u5E76\u8FDE\u63A5"),
|
|
10911
|
+
h2(Button12, { kind: "quiet", onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10912
|
+
)
|
|
10913
|
+
)
|
|
10914
|
+
);
|
|
10915
|
+
}
|
|
10916
|
+
function CallbackUrlBox({ url, busy, resetBusy, onCopy, onReset }) {
|
|
10917
|
+
const [copied, setCopied] = React20.useState(false);
|
|
10918
|
+
const copy = async () => {
|
|
10919
|
+
try {
|
|
10920
|
+
await navigator.clipboard.writeText(url);
|
|
10921
|
+
setCopied(true);
|
|
10922
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
10923
|
+
} catch {
|
|
10924
|
+
setCopied(false);
|
|
10925
|
+
}
|
|
10926
|
+
onCopy?.();
|
|
10927
|
+
};
|
|
10928
|
+
return h2(
|
|
10929
|
+
"div",
|
|
10930
|
+
{ className: "dim-callbackBox" },
|
|
10931
|
+
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"),
|
|
10932
|
+
h2(
|
|
10933
|
+
"div",
|
|
10934
|
+
{ className: "dim-callbackRow" },
|
|
10935
|
+
h2("input", {
|
|
10936
|
+
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",
|
|
10937
|
+
readOnly: true,
|
|
10938
|
+
onFocus: (event) => event.target.select?.()
|
|
10939
|
+
}),
|
|
10940
|
+
url ? h2(Button12, { onClick: copy, disabled: busy, small: true }, copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236") : null,
|
|
10941
|
+
h2(Button12, { kind: "danger", onClick: onReset, disabled: busy || resetBusy }, resetBusy ? "\u91CD\u7F6E\u4E2D\u2026" : "\u91CD\u7F6E\u5BC6\u94A5")
|
|
10942
|
+
),
|
|
10943
|
+
h2(
|
|
10944
|
+
"span",
|
|
10945
|
+
{ className: "dim-callbackHint" },
|
|
10946
|
+
"\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"
|
|
10947
|
+
)
|
|
10948
|
+
);
|
|
10949
|
+
}
|
|
10950
|
+
function AppSettingsEditor({ bot, busy, onSave }) {
|
|
10951
|
+
const [apiBaseUrl, setApiBaseUrl] = React20.useState(bot.apiBaseUrl ?? "");
|
|
10952
|
+
const [callbackBaseUrl, setCallbackBaseUrl] = React20.useState(bot.callbackBaseUrl ?? "");
|
|
10953
|
+
const [streamEnabled, setStreamEnabled] = React20.useState(bot.streamEnabled !== false);
|
|
10954
|
+
const [dirty, setDirty] = React20.useState(false);
|
|
10955
|
+
const formRef = React20.useRef(null);
|
|
10956
|
+
React20.useEffect(() => {
|
|
10957
|
+
setApiBaseUrl(bot.apiBaseUrl ?? "");
|
|
10958
|
+
setCallbackBaseUrl(bot.callbackBaseUrl ?? "");
|
|
10959
|
+
setStreamEnabled(bot.streamEnabled !== false);
|
|
10960
|
+
setDirty(false);
|
|
10961
|
+
}, [bot.apiBaseUrl, bot.callbackBaseUrl, bot.streamEnabled]);
|
|
10962
|
+
const touch = () => setDirty(true);
|
|
10963
|
+
const save = (event) => {
|
|
10964
|
+
event.preventDefault();
|
|
10965
|
+
if (!dirty || busy) return;
|
|
10966
|
+
void onSave({
|
|
10967
|
+
apiBaseUrl: apiBaseUrl.trim() || null,
|
|
10968
|
+
callbackBaseUrl: callbackBaseUrl.trim() || null,
|
|
10969
|
+
streamEnabled
|
|
10970
|
+
});
|
|
10971
|
+
setDirty(false);
|
|
10972
|
+
};
|
|
10973
|
+
return h2(
|
|
10974
|
+
"form",
|
|
10975
|
+
{ ref: formRef, className: "dim-appFieldGrid", onSubmit: save },
|
|
10976
|
+
h2(Field, { label: "\u4EE3\u7406\u5730\u5740\uFF08\u53EF\u9009\uFF09", value: apiBaseUrl, onChange: (value) => {
|
|
10977
|
+
setApiBaseUrl(value);
|
|
10978
|
+
touch();
|
|
10979
|
+
}, placeholder: "\u7559\u7A7A\u76F4\u8FDE qyapi.weixin.qq.com", busy }),
|
|
10980
|
+
h2(Field, { label: "\u516C\u7F51\u56DE\u8C03\u57FA\u5740\uFF08\u53EF\u9009\uFF09", value: callbackBaseUrl, onChange: (value) => {
|
|
10981
|
+
setCallbackBaseUrl(value);
|
|
10982
|
+
touch();
|
|
10983
|
+
}, placeholder: "\u4F8B\u5982 https://im.example.com", busy }),
|
|
10984
|
+
h2(
|
|
10985
|
+
"div",
|
|
10986
|
+
{ className: "dim-appSwitchRow" },
|
|
10987
|
+
h2("button", {
|
|
10988
|
+
type: "button",
|
|
10989
|
+
className: "ddt-button dim-streamToggle",
|
|
10990
|
+
"aria-pressed": streamEnabled ? "true" : "false",
|
|
10991
|
+
onClick: () => {
|
|
10992
|
+
setStreamEnabled((value) => !value);
|
|
10993
|
+
touch();
|
|
10994
|
+
},
|
|
10995
|
+
disabled: busy
|
|
10996
|
+
}, streamEnabled ? "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5F00" : "\u6D41\u5F0F\u56DE\u590D\uFF1A\u5173")
|
|
10997
|
+
),
|
|
10998
|
+
h2(
|
|
10999
|
+
"div",
|
|
11000
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
11001
|
+
h2(Button12, { onClick: () => formRef.current?.requestSubmit(), disabled: busy || !dirty }, busy ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u8BBE\u7F6E")
|
|
11002
|
+
)
|
|
11003
|
+
);
|
|
11004
|
+
}
|
|
11005
|
+
function RemoveConfirmation5({ account, busy, onConfirm, onCancel }) {
|
|
11006
|
+
return h2(
|
|
11007
|
+
"div",
|
|
11008
|
+
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
11009
|
+
h2("strong", null, `\u4ECE DeepSeek Harness \u79FB\u9664\u201C${account.bot.name}\u201D\uFF1F`),
|
|
11010
|
+
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"),
|
|
11011
|
+
h2(
|
|
11012
|
+
"div",
|
|
11013
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
11014
|
+
h2(Button12, { onClick: onCancel, disabled: busy }, "\u4FDD\u7559\u5E94\u7528"),
|
|
11015
|
+
h2(Button12, { kind: "danger", onClick: onConfirm, disabled: busy }, busy ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664\u63A5\u5165")
|
|
11016
|
+
)
|
|
11017
|
+
);
|
|
11018
|
+
}
|
|
11019
|
+
function AccountCard4({
|
|
11020
|
+
account,
|
|
11021
|
+
busy,
|
|
11022
|
+
feedback,
|
|
11023
|
+
removing,
|
|
11024
|
+
onReconnect,
|
|
11025
|
+
onSettingsSave,
|
|
11026
|
+
onSecretReset,
|
|
11027
|
+
onWorkspaceSave,
|
|
11028
|
+
onModelSave,
|
|
11029
|
+
onAgentPresetSave,
|
|
11030
|
+
onContextEnhancementSave,
|
|
11031
|
+
onRequestRemove,
|
|
11032
|
+
onConfirmRemove,
|
|
11033
|
+
onCancelRemove
|
|
11034
|
+
}) {
|
|
11035
|
+
const tone = account.connected ? "success" : account.state === "error" ? "error" : "warning";
|
|
11036
|
+
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : account.state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
11037
|
+
const summary2 = account.error?.message ?? (account.connected ? null : account.health.summary);
|
|
11038
|
+
const elementId = `wecomapp-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
11039
|
+
return h2(
|
|
11040
|
+
"article",
|
|
11041
|
+
{ className: "ddt-card dim-botCard", "data-bot-id": account.botId },
|
|
11042
|
+
h2(
|
|
11043
|
+
"div",
|
|
11044
|
+
{ className: "ddt-cardBody dim-botCardBody" },
|
|
11045
|
+
h2(
|
|
11046
|
+
CollapsibleAccountSection,
|
|
11047
|
+
{
|
|
11048
|
+
id: elementId,
|
|
11049
|
+
header: h2(
|
|
11050
|
+
"div",
|
|
11051
|
+
{ className: "ddt-accountTop dim-botCardTop" },
|
|
11052
|
+
h2(
|
|
11053
|
+
"div",
|
|
11054
|
+
{ className: "ddt-accountIdentity dim-botIdentity" },
|
|
11055
|
+
h2("div", { className: "ddt-avatar dim-botAvatar dwecomapp-avatar", "aria-hidden": "true" }, h2(WecomLogoGlyph, { size: 29 })),
|
|
11056
|
+
h2(
|
|
11057
|
+
"div",
|
|
11058
|
+
{ className: "dim-botName" },
|
|
11059
|
+
h2("h3", null, account.bot.name),
|
|
11060
|
+
h2("p", null, `${account.bot.corpIdMasked} \xB7 AgentId ${account.bot.agentId}`)
|
|
11061
|
+
)
|
|
11062
|
+
),
|
|
11063
|
+
h2(
|
|
11064
|
+
"div",
|
|
11065
|
+
{
|
|
11066
|
+
className: "dim-botCardTools",
|
|
11067
|
+
onClick: (event) => {
|
|
11068
|
+
event.stopPropagation();
|
|
11069
|
+
},
|
|
11070
|
+
onKeyDown: (event) => {
|
|
11071
|
+
if (event.key === "Enter" || event.key === " ") event.stopPropagation();
|
|
11072
|
+
}
|
|
11073
|
+
},
|
|
11074
|
+
h2(BotStatusMeta, {
|
|
11075
|
+
className: "ddt-health",
|
|
11076
|
+
dotClassName: "ddt-dot",
|
|
11077
|
+
tone,
|
|
11078
|
+
stateLabel: stateLabel2,
|
|
11079
|
+
lastCheckedAt: account.health.lastCheckedAt,
|
|
11080
|
+
formatCheckedTime: checkedTime5
|
|
11081
|
+
}),
|
|
11082
|
+
h2(BotSettingsButton, {
|
|
11083
|
+
channel: "wecomApp",
|
|
11084
|
+
botId: account.botId,
|
|
11085
|
+
botName: account.bot.name,
|
|
11086
|
+
connected: account.connected,
|
|
11087
|
+
accessPolicy: account.accessPolicy
|
|
11088
|
+
})
|
|
11089
|
+
)
|
|
11090
|
+
)
|
|
11091
|
+
},
|
|
11092
|
+
h2(CallbackUrlBox, {
|
|
11093
|
+
url: account.bot.callbackUrl,
|
|
11094
|
+
busy: Boolean(busy),
|
|
11095
|
+
resetBusy: busy === "reset",
|
|
11096
|
+
onReset: onSecretReset
|
|
11097
|
+
}),
|
|
11098
|
+
h2(AppSettingsEditor, {
|
|
11099
|
+
bot: account.bot,
|
|
11100
|
+
busy: Boolean(busy),
|
|
11101
|
+
onSave: onSettingsSave
|
|
11102
|
+
}),
|
|
11103
|
+
h2(WorkspaceEditor, {
|
|
11104
|
+
workspace: account.workspace,
|
|
11105
|
+
disabled: Boolean(busy),
|
|
11106
|
+
onSave: onWorkspaceSave
|
|
11107
|
+
}),
|
|
11108
|
+
h2(ModelEditor, {
|
|
11109
|
+
model: account.model,
|
|
11110
|
+
disabled: Boolean(busy),
|
|
11111
|
+
onSave: onModelSave
|
|
11112
|
+
}),
|
|
11113
|
+
h2(AgentPresetEditor, {
|
|
11114
|
+
agentPreset: account.agentPreset,
|
|
11115
|
+
disabled: Boolean(busy),
|
|
11116
|
+
onSave: onAgentPresetSave
|
|
11117
|
+
}),
|
|
11118
|
+
h2(ContextEnhancementEditor, {
|
|
11119
|
+
config: account.contextEnhancement,
|
|
11120
|
+
disabled: Boolean(busy),
|
|
11121
|
+
onSave: onContextEnhancementSave
|
|
11122
|
+
}),
|
|
11123
|
+
h2(
|
|
11124
|
+
"div",
|
|
11125
|
+
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
11126
|
+
h2(
|
|
11127
|
+
"div",
|
|
11128
|
+
{ className: "dim-cardFooterLayout" },
|
|
11129
|
+
h2(
|
|
11130
|
+
"div",
|
|
11131
|
+
{ className: "ddt-actions dim-cardActions" },
|
|
11132
|
+
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"),
|
|
11133
|
+
h2(Button12, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
|
|
11134
|
+
),
|
|
11135
|
+
summary2 ? h2("div", { className: "ddt-summary dim-cardSummary" }, summary2) : null,
|
|
11136
|
+
account.lastMessageError ? h2(LastMessageErrorSummary, {
|
|
11137
|
+
className: "ddt-summary",
|
|
11138
|
+
error: account.lastMessageError
|
|
11139
|
+
}) : null,
|
|
11140
|
+
feedback ? h2("div", {
|
|
11141
|
+
className: "ddt-summary dim-cardFeedback",
|
|
11142
|
+
role: "status",
|
|
11143
|
+
"aria-live": "polite"
|
|
11144
|
+
}, feedback) : null
|
|
11145
|
+
)
|
|
11146
|
+
)
|
|
11147
|
+
)
|
|
11148
|
+
),
|
|
11149
|
+
removing ? h2(RemoveConfirmation5, {
|
|
11150
|
+
account,
|
|
11151
|
+
busy: busy === "delete",
|
|
11152
|
+
onConfirm: onConfirmRemove,
|
|
11153
|
+
onCancel: onCancelRemove
|
|
11154
|
+
}) : null
|
|
11155
|
+
);
|
|
11156
|
+
}
|
|
11157
|
+
function WecomAppSettingsTab({ rpcCall }) {
|
|
11158
|
+
const [model, setModel] = React20.useState({
|
|
11159
|
+
phase: "loading",
|
|
11160
|
+
bots: [],
|
|
11161
|
+
totals: { configured: 0, connected: 0 },
|
|
11162
|
+
error: null,
|
|
11163
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
11164
|
+
modelCatalog: EMPTY_MODEL_CATALOG
|
|
11165
|
+
});
|
|
11166
|
+
const [bindOpen, setBindOpen] = React20.useState(false);
|
|
11167
|
+
const [bindError, setBindError] = React20.useState(null);
|
|
11168
|
+
const [busy, setBusy] = React20.useState(false);
|
|
11169
|
+
const [busyByBot, setBusyByBot] = React20.useState({});
|
|
11170
|
+
const [feedbackByBot, setFeedbackByBot] = React20.useState({});
|
|
11171
|
+
const [removeTarget, setRemoveTarget] = React20.useState(null);
|
|
11172
|
+
const [notice, setNotice] = React20.useState("");
|
|
11173
|
+
const mounted = React20.useRef(true);
|
|
11174
|
+
const workspaceFence = useWorkspaceSnapshotFence();
|
|
11175
|
+
const addButtonRef = React20.useRef(null);
|
|
11176
|
+
const noticeFrameRef = React20.useRef(null);
|
|
11177
|
+
const announce = React20.useCallback((message) => {
|
|
11178
|
+
if (!mounted.current) return;
|
|
11179
|
+
if (noticeFrameRef.current !== null) {
|
|
11180
|
+
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
11181
|
+
noticeFrameRef.current = null;
|
|
11182
|
+
}
|
|
11183
|
+
setNotice("");
|
|
11184
|
+
if (message) {
|
|
11185
|
+
noticeFrameRef.current = window.requestAnimationFrame(() => {
|
|
11186
|
+
noticeFrameRef.current = null;
|
|
11187
|
+
if (mounted.current) setNotice(message);
|
|
11188
|
+
});
|
|
11189
|
+
}
|
|
11190
|
+
}, []);
|
|
11191
|
+
React20.useEffect(() => {
|
|
11192
|
+
const disposeDingtalk = installDingtalkStyles();
|
|
11193
|
+
const disposeWecomApp = installWecomAppStyles();
|
|
11194
|
+
mounted.current = true;
|
|
11195
|
+
return () => {
|
|
11196
|
+
mounted.current = false;
|
|
11197
|
+
if (noticeFrameRef.current !== null) {
|
|
11198
|
+
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
11199
|
+
noticeFrameRef.current = null;
|
|
11200
|
+
}
|
|
11201
|
+
disposeWecomApp();
|
|
11202
|
+
disposeDingtalk();
|
|
11203
|
+
};
|
|
11204
|
+
}, []);
|
|
11205
|
+
const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
|
|
11206
|
+
if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
11207
|
+
return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
|
|
11208
|
+
}, [rpcCall]);
|
|
11209
|
+
const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
11210
|
+
const workspaceVersion = workspaceFence.beginStatus();
|
|
11211
|
+
if (workspaceVersion === null) return void 0;
|
|
11212
|
+
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
11213
|
+
try {
|
|
11214
|
+
const snapshot = normalizeSnapshot7(await invoke(WECOM_APP_ENDPOINTS.status, {}, signal));
|
|
11215
|
+
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
11216
|
+
setModel({
|
|
11217
|
+
phase: "ready",
|
|
11218
|
+
bots: snapshot.bots,
|
|
11219
|
+
totals: snapshot.totals,
|
|
11220
|
+
error: null,
|
|
11221
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11222
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11223
|
+
});
|
|
11224
|
+
if (restore && snapshot.bots.length > 0) setBindOpen(false);
|
|
11225
|
+
return snapshot;
|
|
11226
|
+
} catch (error) {
|
|
11227
|
+
if (error?.name !== "AbortError" && mounted.current && !signal?.aborted && workspaceFence.canCommitStatus(workspaceVersion)) {
|
|
11228
|
+
setModel((current) => ({ ...current, phase: silent ? current.phase : "error", error: presentError8(error) }));
|
|
11229
|
+
}
|
|
11230
|
+
return void 0;
|
|
11231
|
+
}
|
|
11232
|
+
}, [invoke, workspaceFence]);
|
|
11233
|
+
React20.useEffect(() => {
|
|
11234
|
+
const controller = new AbortController();
|
|
11235
|
+
void loadStatus({ signal: controller.signal, restore: true });
|
|
11236
|
+
return () => controller.abort();
|
|
11237
|
+
}, [loadStatus]);
|
|
11238
|
+
React20.useEffect(() => {
|
|
11239
|
+
if (model.phase !== "ready") return void 0;
|
|
11240
|
+
const controller = new AbortController();
|
|
11241
|
+
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
11242
|
+
return () => {
|
|
11243
|
+
controller.abort();
|
|
11244
|
+
window.clearInterval(timer);
|
|
11245
|
+
};
|
|
11246
|
+
}, [loadStatus, model.phase]);
|
|
11247
|
+
const bindApp = React20.useCallback(async (payload) => {
|
|
11248
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
11249
|
+
setBusy(true);
|
|
11250
|
+
setBindError(null);
|
|
11251
|
+
try {
|
|
11252
|
+
const snapshot = normalizeSnapshot7(await invoke(WECOM_APP_ENDPOINTS.bindApp, payload));
|
|
11253
|
+
if (!mounted.current) return;
|
|
11254
|
+
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
11255
|
+
setModel({
|
|
11256
|
+
phase: "ready",
|
|
11257
|
+
bots: snapshot.bots,
|
|
11258
|
+
totals: snapshot.totals,
|
|
11259
|
+
error: null,
|
|
11260
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11261
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11262
|
+
});
|
|
11263
|
+
}
|
|
11264
|
+
setBindOpen(false);
|
|
11265
|
+
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");
|
|
11266
|
+
} catch (error) {
|
|
11267
|
+
if (mounted.current) setBindError(presentError8(error));
|
|
11268
|
+
} finally {
|
|
11269
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
11270
|
+
if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
|
|
11271
|
+
if (mounted.current) setBusy(false);
|
|
11272
|
+
}
|
|
11273
|
+
}, [announce, invoke, loadStatus, workspaceFence]);
|
|
11274
|
+
const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
|
|
11275
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
11276
|
+
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
11277
|
+
try {
|
|
11278
|
+
const snapshot = normalizeSnapshot7(await invoke(endpoint, payload));
|
|
11279
|
+
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
11280
|
+
setModel({
|
|
11281
|
+
phase: "ready",
|
|
11282
|
+
bots: snapshot.bots,
|
|
11283
|
+
totals: snapshot.totals,
|
|
11284
|
+
error: null,
|
|
11285
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
|
11286
|
+
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11287
|
+
});
|
|
11288
|
+
}
|
|
11289
|
+
return snapshot;
|
|
11290
|
+
} finally {
|
|
11291
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
11292
|
+
if (shouldRefresh && mounted.current) void loadStatus({ silent: true });
|
|
11293
|
+
if (mounted.current) setBusyByBot((current) => {
|
|
11294
|
+
const next = { ...current };
|
|
11295
|
+
delete next[account.botId];
|
|
11296
|
+
return next;
|
|
11297
|
+
});
|
|
11298
|
+
}
|
|
11299
|
+
}, [invoke, loadStatus, workspaceFence]);
|
|
11300
|
+
const reconnect = React20.useCallback(async (account) => {
|
|
11301
|
+
setFeedbackByBot((current) => {
|
|
11302
|
+
const next = { ...current };
|
|
11303
|
+
delete next[account.botId];
|
|
11304
|
+
return next;
|
|
11305
|
+
});
|
|
11306
|
+
try {
|
|
11307
|
+
const snapshot = await botAction(
|
|
11308
|
+
account,
|
|
11309
|
+
"reconnect",
|
|
11310
|
+
WECOM_APP_ENDPOINTS.reconnectBot,
|
|
11311
|
+
{ botId: account.botId, sendTest: true }
|
|
11312
|
+
);
|
|
11313
|
+
if (!snapshot) return;
|
|
11314
|
+
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
11315
|
+
let feedback;
|
|
11316
|
+
if (!refreshed?.connected) {
|
|
11317
|
+
feedback = "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u4ECD\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u7EE7\u7EED\u81EA\u52A8\u91CD\u8BD5\u3002";
|
|
11318
|
+
} else if (snapshot.testMessage?.sent) {
|
|
11319
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002";
|
|
11320
|
+
} else if (snapshot.testMessage?.code === "test-target-unavailable") {
|
|
11321
|
+
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";
|
|
11322
|
+
} else if (snapshot.testMessage) {
|
|
11323
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002";
|
|
11324
|
+
} else {
|
|
11325
|
+
feedback = "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
|
|
11326
|
+
}
|
|
11327
|
+
if (mounted.current) {
|
|
11328
|
+
setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
|
|
11329
|
+
}
|
|
11330
|
+
announce(feedback);
|
|
11331
|
+
} catch {
|
|
11332
|
+
const feedback = "\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
|
|
11333
|
+
if (mounted.current) {
|
|
11334
|
+
setFeedbackByBot((current) => ({ ...current, [account.botId]: feedback }));
|
|
11335
|
+
}
|
|
11336
|
+
announce(feedback);
|
|
11337
|
+
}
|
|
11338
|
+
}, [announce, botAction]);
|
|
11339
|
+
const botList = model.bots.length > 0 ? h2(
|
|
11340
|
+
"section",
|
|
11341
|
+
{ className: "dim-listSection" },
|
|
11342
|
+
h2(ChannelListHeading, {
|
|
11343
|
+
className: "ddt-listHeading",
|
|
11344
|
+
title: "\u5DF2\u7ED1\u5B9A\u7684\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528",
|
|
11345
|
+
connectionLabel: "HTTP \u56DE\u8C03\u901A\u9053"
|
|
11346
|
+
}),
|
|
11347
|
+
h2("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h2("li", { key: account.botId }, h2(AccountCard4, {
|
|
11348
|
+
account,
|
|
11349
|
+
busy: busyByBot[account.botId],
|
|
11350
|
+
feedback: feedbackByBot[account.botId],
|
|
11351
|
+
removing: removeTarget === account.botId,
|
|
11352
|
+
onReconnect: () => void reconnect(account),
|
|
11353
|
+
onSettingsSave: (settings) => botAction(
|
|
11354
|
+
account,
|
|
11355
|
+
"settings",
|
|
11356
|
+
WECOM_APP_ENDPOINTS.updateSettings,
|
|
11357
|
+
{ botId: account.botId, ...settings }
|
|
11358
|
+
),
|
|
11359
|
+
onSecretReset: async () => {
|
|
11360
|
+
try {
|
|
11361
|
+
await botAction(account, "reset", WECOM_APP_ENDPOINTS.resetCallbackSecret, { botId: account.botId });
|
|
11362
|
+
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");
|
|
11363
|
+
} catch {
|
|
11364
|
+
announce("\u56DE\u8C03\u5BC6\u94A5\u91CD\u7F6E\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
11365
|
+
}
|
|
11366
|
+
},
|
|
11367
|
+
onWorkspaceSave: (workspace) => botAction(
|
|
11368
|
+
account,
|
|
11369
|
+
"workspace",
|
|
11370
|
+
WECOM_APP_ENDPOINTS.setWorkspace,
|
|
11371
|
+
{ botId: account.botId, workspace }
|
|
11372
|
+
),
|
|
11373
|
+
onModelSave: (selectedModel) => botAction(
|
|
11374
|
+
account,
|
|
11375
|
+
"model",
|
|
11376
|
+
WECOM_APP_ENDPOINTS.setModel,
|
|
11377
|
+
{ botId: account.botId, model: selectedModel }
|
|
11378
|
+
),
|
|
11379
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
11380
|
+
account,
|
|
11381
|
+
"preset",
|
|
11382
|
+
WECOM_APP_ENDPOINTS.setAgentPreset,
|
|
11383
|
+
{ botId: account.botId, agentPreset }
|
|
11384
|
+
),
|
|
11385
|
+
onContextEnhancementSave: (config) => botAction(
|
|
11386
|
+
account,
|
|
11387
|
+
"context-enhancement",
|
|
11388
|
+
WECOM_APP_ENDPOINTS.setContextEnhancement,
|
|
11389
|
+
{ botId: account.botId, config }
|
|
11390
|
+
),
|
|
11391
|
+
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
11392
|
+
onCancelRemove: () => setRemoveTarget(null),
|
|
11393
|
+
onConfirmRemove: async () => {
|
|
11394
|
+
await botAction(account, "delete", WECOM_APP_ENDPOINTS.deleteBot, { botId: account.botId, confirm: true });
|
|
11395
|
+
if (mounted.current) setRemoveTarget(null);
|
|
11396
|
+
}
|
|
11397
|
+
}))))
|
|
11398
|
+
) : null;
|
|
11399
|
+
const bindView = bindOpen ? h2(BindForm, {
|
|
11400
|
+
busy,
|
|
11401
|
+
error: bindError,
|
|
11402
|
+
onSubmit: bindApp,
|
|
11403
|
+
onCancel: () => {
|
|
11404
|
+
setBindOpen(false);
|
|
11405
|
+
setBindError(null);
|
|
11406
|
+
}
|
|
11407
|
+
}) : null;
|
|
11408
|
+
return h2(ModelCatalogContext.Provider, {
|
|
11409
|
+
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG
|
|
11410
|
+
}, h2(AgentPresetCatalogContext.Provider, {
|
|
11411
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
11412
|
+
}, h2(
|
|
11413
|
+
"section",
|
|
11414
|
+
{ className: "ddt-page dwecomapp-page dim-channelPage", "aria-label": "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528\u8BBE\u7F6E" },
|
|
11415
|
+
h2(Heading5, {
|
|
11416
|
+
totals: model.totals,
|
|
11417
|
+
adding: bindOpen,
|
|
11418
|
+
busy,
|
|
11419
|
+
onAdd: () => {
|
|
11420
|
+
setBindOpen((value) => !value);
|
|
11421
|
+
setBindError(null);
|
|
11422
|
+
},
|
|
11423
|
+
addButtonRef
|
|
11424
|
+
}),
|
|
11425
|
+
h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
11426
|
+
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(
|
|
11427
|
+
React20.Fragment,
|
|
11428
|
+
null,
|
|
11429
|
+
bindView,
|
|
11430
|
+
model.bots.length === 0 && !bindOpen ? h2(EmptyView5, { busy, onStart: () => setBindOpen(true) }) : null,
|
|
11431
|
+
botList
|
|
11432
|
+
)
|
|
11433
|
+
)));
|
|
11434
|
+
}
|
|
11435
|
+
|
|
11436
|
+
// plugin-src/client/channels/weixin/index.js
|
|
11437
|
+
var React21 = __toESM(require("react"), 1);
|
|
11438
|
+
|
|
11439
|
+
// plugin-src/client/channels/weixin/api.js
|
|
11440
|
+
var WEIXIN_RPC_CHANNEL = "/weixin";
|
|
11441
|
+
var WEIXIN_ENDPOINTS = Object.freeze({
|
|
11442
|
+
status: "connection.status",
|
|
11443
|
+
beginProvisioning: "provision.begin",
|
|
11444
|
+
pollProvisioning: "provision.poll",
|
|
11445
|
+
submitVerification: "provision.verify",
|
|
11446
|
+
cancelProvisioning: "provision.cancel",
|
|
11447
|
+
reconnectBot: "bot.reconnect",
|
|
11448
|
+
deleteBot: "bot.delete",
|
|
11449
|
+
setWorkspace: "bot.workspace.set",
|
|
11450
|
+
setModel: SET_MODEL_ENDPOINT,
|
|
11451
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
11452
|
+
setContextEnhancement: "bot.context-enhancement.set",
|
|
11453
|
+
setAccessPolicy: "bot.access-policy.set"
|
|
11454
|
+
});
|
|
11455
|
+
var ACCOUNT_STATES6 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
11456
|
+
var PROVISION_STATES4 = /* @__PURE__ */ new Set([
|
|
11457
|
+
"starting",
|
|
11458
|
+
"pending",
|
|
11459
|
+
"scanned",
|
|
11460
|
+
"needs_verification",
|
|
11461
|
+
"connecting",
|
|
11462
|
+
"connected",
|
|
11463
|
+
"expired",
|
|
11464
|
+
"failed",
|
|
11465
|
+
"cancelled"
|
|
11466
|
+
]);
|
|
11467
|
+
function isRecord7(value) {
|
|
11468
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11469
|
+
}
|
|
11470
|
+
function string(value, fallback = "") {
|
|
11471
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
11472
|
+
}
|
|
11473
|
+
function timestamp6(value) {
|
|
11474
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
11475
|
+
}
|
|
11476
|
+
function normalizeTestMessage5(value) {
|
|
11477
|
+
if (!isRecord7(value)) return null;
|
|
11478
|
+
if (value.sent === true) return { sent: true };
|
|
11479
|
+
if (value.sent !== false) return null;
|
|
11480
|
+
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
11481
|
+
return { sent: false, code };
|
|
11482
|
+
}
|
|
11483
|
+
function unwrapRpcResult9(result) {
|
|
11484
|
+
if (!isRecord7(result) || typeof result.ok !== "boolean") {
|
|
11485
|
+
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
11486
|
+
}
|
|
11487
|
+
if (!result.ok) {
|
|
11488
|
+
const error = new Error(string(result.error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25"));
|
|
11489
|
+
error.code = string(result.error?.code, "WEIXIN_RPC_ERROR");
|
|
11490
|
+
throw error;
|
|
11491
|
+
}
|
|
11492
|
+
return result.value;
|
|
11493
|
+
}
|
|
11494
|
+
function safeQrSource5(value) {
|
|
11495
|
+
return typeof value === "string" && /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
|
|
11496
|
+
}
|
|
11497
|
+
function safeVerificationUrl(value) {
|
|
11498
|
+
if (typeof value !== "string") return void 0;
|
|
11499
|
+
try {
|
|
11500
|
+
const url = new URL(value);
|
|
11501
|
+
const host = url.hostname.toLowerCase();
|
|
11502
|
+
return url.protocol === "https:" && (host === "weixin.qq.com" || host.endsWith(".weixin.qq.com") || host === "wechat.com" || host.endsWith(".wechat.com")) ? url.toString() : void 0;
|
|
11503
|
+
} catch {
|
|
11504
|
+
return void 0;
|
|
11505
|
+
}
|
|
11506
|
+
}
|
|
11507
|
+
function normalizeProvisioning5(value) {
|
|
11508
|
+
if (!isRecord7(value) || !string(value.attemptId)) {
|
|
11509
|
+
throw new Error("\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
11510
|
+
}
|
|
11511
|
+
const status = PROVISION_STATES4.has(value.status) ? value.status : "failed";
|
|
11512
|
+
const result = {
|
|
11513
|
+
attemptId: string(value.attemptId),
|
|
11514
|
+
status,
|
|
11515
|
+
expiresAt: timestamp6(value.expiresAt) ?? Date.now(),
|
|
11516
|
+
pollIntervalMs: Math.min(5e3, Math.max(500, Number(value.pollIntervalMs) || 1e3)),
|
|
11517
|
+
verificationRequired: value.verificationRequired === true || status === "needs_verification"
|
|
11518
|
+
};
|
|
11519
|
+
const verificationUrl = safeVerificationUrl(value.verificationUrl);
|
|
11520
|
+
const qrCodeDataUrl = safeQrSource5(value.qrCodeDataUrl);
|
|
11521
|
+
if (verificationUrl) result.verificationUrl = verificationUrl;
|
|
11522
|
+
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
11523
|
+
if (string(value.botId)) result.botId = string(value.botId);
|
|
11524
|
+
if (value.alreadyConnected === true) result.alreadyConnected = true;
|
|
11525
|
+
if (isRecord7(value.error)) {
|
|
11526
|
+
result.error = {
|
|
11527
|
+
code: string(value.error.code, "WEIXIN_PROVISION_FAILED"),
|
|
11528
|
+
message: string(value.error.message, "\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210")
|
|
11529
|
+
};
|
|
11530
|
+
}
|
|
11531
|
+
return result;
|
|
11532
|
+
}
|
|
11533
|
+
function normalizeBot6(value) {
|
|
11534
|
+
if (!isRecord7(value) || !string(value.botId) || !isRecord7(value.bot)) return null;
|
|
11535
|
+
const state = ACCOUNT_STATES6.has(value.state) ? value.state : "error";
|
|
11536
|
+
const connected = value.connected === true;
|
|
11537
|
+
return {
|
|
11538
|
+
botId: string(value.botId),
|
|
11539
|
+
state: connected ? "connected" : state,
|
|
11540
|
+
connected,
|
|
11541
|
+
configured: value.configured === true,
|
|
11542
|
+
workspace: string(value.workspace).slice(0, 4096),
|
|
11543
|
+
model: normalizeModelSelection(value.model),
|
|
11544
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
11545
|
+
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
11546
|
+
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
11547
|
+
bot: {
|
|
11548
|
+
name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
|
|
11549
|
+
accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
|
|
11550
|
+
},
|
|
11551
|
+
health: {
|
|
11552
|
+
status: string(value.health?.status, connected ? "healthy" : "offline"),
|
|
11553
|
+
summary: string(value.health?.summary, connected ? "\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38" : "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA"),
|
|
11554
|
+
lastCheckedAt: timestamp6(value.health?.lastCheckedAt)
|
|
11555
|
+
},
|
|
11556
|
+
stats: {
|
|
11557
|
+
messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
|
|
11558
|
+
messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
|
|
11559
|
+
},
|
|
11560
|
+
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
11561
|
+
error: isRecord7(value.error) ? {
|
|
11562
|
+
code: string(value.error.code, "WEIXIN_ACCOUNT_ERROR"),
|
|
11563
|
+
message: string(value.error.message, "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA")
|
|
11564
|
+
} : null
|
|
11565
|
+
};
|
|
11566
|
+
}
|
|
11567
|
+
function normalizeSnapshot8(value) {
|
|
11568
|
+
if (!isRecord7(value) || !Array.isArray(value.bots)) {
|
|
11569
|
+
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868");
|
|
11570
|
+
}
|
|
11571
|
+
const bots = value.bots.map(normalizeBot6).filter(Boolean);
|
|
11572
|
+
return {
|
|
11573
|
+
schemaVersion: Number(value.schemaVersion) || 1,
|
|
11574
|
+
revision: Number(value.revision) || 0,
|
|
11575
|
+
state: string(value.state, "offline"),
|
|
11576
|
+
bots,
|
|
11577
|
+
totals: {
|
|
11578
|
+
configured: bots.length,
|
|
11579
|
+
connected: bots.filter((bot) => bot.connected).length
|
|
11580
|
+
},
|
|
11581
|
+
provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
|
|
11582
|
+
testMessage: normalizeTestMessage5(value.testMessage),
|
|
11583
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
|
|
11584
|
+
modelCatalog: normalizeModelCatalog(value.modelCatalog)
|
|
11585
|
+
};
|
|
11586
|
+
}
|
|
11587
|
+
function presentError9(error) {
|
|
11588
|
+
return {
|
|
11589
|
+
code: string(error?.code, "WEIXIN_ERROR"),
|
|
11590
|
+
message: string(error?.message, "\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
11591
|
+
};
|
|
11592
|
+
}
|
|
11593
|
+
function formatRemaining5(milliseconds) {
|
|
11594
|
+
const seconds = Math.max(0, Math.ceil(milliseconds / 1e3));
|
|
11595
|
+
return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
|
|
11596
|
+
}
|
|
11597
|
+
|
|
11598
|
+
// plugin-src/client/channels/weixin/index.js
|
|
11599
|
+
var Button14 = React21.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
11600
|
+
return h2("button", {
|
|
11601
|
+
...props,
|
|
11602
|
+
ref,
|
|
11603
|
+
type: "button",
|
|
11604
|
+
className: `dxw-button ${className}`.trim(),
|
|
11605
|
+
"data-kind": kind
|
|
11606
|
+
}, children);
|
|
11607
|
+
});
|
|
11608
|
+
function Heading6({ totals, adding, busy, onAdd, addButtonRef }) {
|
|
11609
|
+
return h2(
|
|
11610
|
+
"div",
|
|
11611
|
+
{ className: "dxw-heading" },
|
|
11612
|
+
h2(
|
|
11613
|
+
"div",
|
|
11614
|
+
{ className: "dxw-tools" },
|
|
11615
|
+
h2(Button14, {
|
|
11616
|
+
kind: "primary",
|
|
11617
|
+
className: "dim-scanButton",
|
|
11618
|
+
onClick: onAdd,
|
|
11619
|
+
disabled: adding || busy,
|
|
11620
|
+
ref: addButtonRef,
|
|
11621
|
+
"aria-label": "\u626B\u7801\u63A5\u5165\u5FAE\u4FE1\u673A\u5668\u4EBA"
|
|
11622
|
+
}, h2(QrActionIcon), adding ? "\u6B63\u5728\u63A5\u5165" : "\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA"),
|
|
10543
11623
|
totals.configured > 0 ? h2(
|
|
10544
11624
|
"div",
|
|
10545
11625
|
{ className: "dxw-badge dim-onlineBadge" },
|
|
@@ -10548,7 +11628,7 @@ function Heading5({ totals, adding, busy, onAdd, addButtonRef }) {
|
|
|
10548
11628
|
)
|
|
10549
11629
|
);
|
|
10550
11630
|
}
|
|
10551
|
-
function
|
|
11631
|
+
function LoadingView6() {
|
|
10552
11632
|
return h2(
|
|
10553
11633
|
"div",
|
|
10554
11634
|
{ className: "dxw-card dxw-loading dim-surfaceCard dim-loadingView", "aria-busy": "true" },
|
|
@@ -10556,7 +11636,7 @@ function LoadingView5() {
|
|
|
10556
11636
|
h2("span", null, "\u6B63\u5728\u8BFB\u53D6\u5FAE\u4FE1\u8FDE\u63A5\u72B6\u6001\u2026")
|
|
10557
11637
|
);
|
|
10558
11638
|
}
|
|
10559
|
-
function
|
|
11639
|
+
function EmptyView6({ onStart, busy }) {
|
|
10560
11640
|
return h2(
|
|
10561
11641
|
"div",
|
|
10562
11642
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10578,7 +11658,7 @@ function EmptyView5({ onStart, busy }) {
|
|
|
10578
11658
|
"div",
|
|
10579
11659
|
{ className: "dxw-actions dim-viewActions" },
|
|
10580
11660
|
h2(
|
|
10581
|
-
|
|
11661
|
+
Button14,
|
|
10582
11662
|
{ kind: "primary", onClick: onStart, disabled: busy },
|
|
10583
11663
|
busy ? "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" : "\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801"
|
|
10584
11664
|
)
|
|
@@ -10589,14 +11669,14 @@ function EmptyView5({ onStart, busy }) {
|
|
|
10589
11669
|
);
|
|
10590
11670
|
}
|
|
10591
11671
|
function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
10592
|
-
const [imageFailed, setImageFailed] =
|
|
11672
|
+
const [imageFailed, setImageFailed] = React21.useState(false);
|
|
10593
11673
|
const source = safeQrSource5(provision.qrCodeDataUrl);
|
|
10594
11674
|
const href = safeVerificationUrl(provision.verificationUrl);
|
|
10595
11675
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
10596
11676
|
const expired = remaining === 0 || provision.status === "expired";
|
|
10597
11677
|
const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
|
|
10598
11678
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
10599
|
-
|
|
11679
|
+
React21.useEffect(() => setImageFailed(false), [source]);
|
|
10600
11680
|
return h2(
|
|
10601
11681
|
"div",
|
|
10602
11682
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10648,24 +11728,24 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
10648
11728
|
h2(
|
|
10649
11729
|
"div",
|
|
10650
11730
|
{ className: "dxw-actions dim-viewActions" },
|
|
10651
|
-
expired ? h2(
|
|
11731
|
+
expired ? h2(Button14, { kind: "primary", onClick: onRefresh, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801") : null,
|
|
10652
11732
|
href ? h2("a", {
|
|
10653
11733
|
className: "dxw-button",
|
|
10654
11734
|
href,
|
|
10655
11735
|
target: "_blank",
|
|
10656
11736
|
rel: "noopener noreferrer"
|
|
10657
11737
|
}, "\u6253\u5F00\u5907\u7528\u94FE\u63A5") : null,
|
|
10658
|
-
!expired ? h2(
|
|
10659
|
-
h2(
|
|
11738
|
+
!expired ? h2(Button14, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
|
|
11739
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10660
11740
|
)
|
|
10661
11741
|
)
|
|
10662
11742
|
)
|
|
10663
11743
|
);
|
|
10664
11744
|
}
|
|
10665
11745
|
function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
10666
|
-
const [code, setCode] =
|
|
11746
|
+
const [code, setCode] = React21.useState("");
|
|
10667
11747
|
const valid = /^\d{4,8}$/.test(code);
|
|
10668
|
-
|
|
11748
|
+
React21.useEffect(() => setCode(""), [provision.attemptId]);
|
|
10669
11749
|
return h2(
|
|
10670
11750
|
"div",
|
|
10671
11751
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -10706,7 +11786,7 @@ function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
|
10706
11786
|
disabled: !valid || busy
|
|
10707
11787
|
}, busy ? "\u6B63\u5728\u9A8C\u8BC1\u2026" : "\u7EE7\u7EED\u8FDE\u63A5")
|
|
10708
11788
|
),
|
|
10709
|
-
h2(
|
|
11789
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88\u7ED1\u5B9A")
|
|
10710
11790
|
)
|
|
10711
11791
|
);
|
|
10712
11792
|
}
|
|
@@ -10720,7 +11800,7 @@ function ProgressPanel2({ scanned, onCancel, busy }) {
|
|
|
10720
11800
|
onCancel ? h2(
|
|
10721
11801
|
"div",
|
|
10722
11802
|
{ className: "dxw-actions dim-viewActions", style: { justifyContent: "center", marginTop: 14 } },
|
|
10723
|
-
h2(
|
|
11803
|
+
h2(Button14, { onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
10724
11804
|
) : null
|
|
10725
11805
|
);
|
|
10726
11806
|
}
|
|
@@ -10738,25 +11818,25 @@ function ProvisionError3({ provision, busy, onRetry, onClose }) {
|
|
|
10738
11818
|
h2(
|
|
10739
11819
|
"div",
|
|
10740
11820
|
{ className: "dxw-actions dim-viewActions" },
|
|
10741
|
-
h2(
|
|
10742
|
-
h2(
|
|
11821
|
+
h2(Button14, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
11822
|
+
h2(Button14, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
|
|
10743
11823
|
)
|
|
10744
11824
|
)
|
|
10745
11825
|
);
|
|
10746
11826
|
}
|
|
10747
|
-
function
|
|
10748
|
-
if (!
|
|
11827
|
+
function checkedTime6(timestamp8) {
|
|
11828
|
+
if (!timestamp8) return "\u5C1A\u672A\u68C0\u67E5";
|
|
10749
11829
|
try {
|
|
10750
11830
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
10751
11831
|
hour: "2-digit",
|
|
10752
11832
|
minute: "2-digit",
|
|
10753
11833
|
second: "2-digit"
|
|
10754
|
-
}).format(new Date(
|
|
11834
|
+
}).format(new Date(timestamp8));
|
|
10755
11835
|
} catch {
|
|
10756
11836
|
return "\u521A\u521A";
|
|
10757
11837
|
}
|
|
10758
11838
|
}
|
|
10759
|
-
function
|
|
11839
|
+
function AccountCard5({
|
|
10760
11840
|
account,
|
|
10761
11841
|
busy,
|
|
10762
11842
|
feedback,
|
|
@@ -10810,7 +11890,7 @@ function AccountCard4({
|
|
|
10810
11890
|
tone,
|
|
10811
11891
|
stateLabel: account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA",
|
|
10812
11892
|
lastCheckedAt: account.health.lastCheckedAt,
|
|
10813
|
-
formatCheckedTime:
|
|
11893
|
+
formatCheckedTime: checkedTime6
|
|
10814
11894
|
}),
|
|
10815
11895
|
h2(BotSettingsButton, {
|
|
10816
11896
|
channel: "weixin",
|
|
@@ -10853,11 +11933,11 @@ function AccountCard4({
|
|
|
10853
11933
|
"div",
|
|
10854
11934
|
{ className: "dxw-actions dim-cardActions" },
|
|
10855
11935
|
h2(
|
|
10856
|
-
|
|
11936
|
+
Button14,
|
|
10857
11937
|
{ className: "dim-cardAction", onClick: onReconnect, disabled: Boolean(busy) },
|
|
10858
11938
|
busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"
|
|
10859
11939
|
),
|
|
10860
|
-
h2(
|
|
11940
|
+
h2(Button14, { className: "dim-cardAction", kind: "danger", onClick: onRequestRemove, disabled: Boolean(busy) }, "\u79FB\u9664\u63A5\u5165")
|
|
10861
11941
|
),
|
|
10862
11942
|
summary2 ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary2) : null,
|
|
10863
11943
|
account.lastMessageError ? h2(LastMessageErrorSummary, {
|
|
@@ -10881,9 +11961,9 @@ function AccountCard4({
|
|
|
10881
11961
|
h2(
|
|
10882
11962
|
"div",
|
|
10883
11963
|
{ className: "dxw-actions dim-viewActions" },
|
|
10884
|
-
h2(
|
|
11964
|
+
h2(Button14, { onClick: onCancelRemove, disabled: busy === "delete" }, "\u4FDD\u7559\u8D26\u53F7"),
|
|
10885
11965
|
h2(
|
|
10886
|
-
|
|
11966
|
+
Button14,
|
|
10887
11967
|
{ kind: "danger", onClick: onConfirmRemove, disabled: busy === "delete" },
|
|
10888
11968
|
busy === "delete" ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664"
|
|
10889
11969
|
)
|
|
@@ -10903,7 +11983,7 @@ function AccountList2(props) {
|
|
|
10903
11983
|
h2("ul", { className: "dxw-list dim-botList" }, props.bots.map((account) => h2(
|
|
10904
11984
|
"li",
|
|
10905
11985
|
{ key: account.botId },
|
|
10906
|
-
h2(
|
|
11986
|
+
h2(AccountCard5, {
|
|
10907
11987
|
account,
|
|
10908
11988
|
busy: props.busyByBot[account.botId],
|
|
10909
11989
|
feedback: props.feedbackByBot[account.botId],
|
|
@@ -10931,7 +12011,7 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
|
|
|
10931
12011
|
};
|
|
10932
12012
|
}
|
|
10933
12013
|
function WeixinSettingsTab({ rpcCall }) {
|
|
10934
|
-
const [model, setModel] =
|
|
12014
|
+
const [model, setModel] = React21.useState({
|
|
10935
12015
|
phase: "loading",
|
|
10936
12016
|
bots: [],
|
|
10937
12017
|
totals: EMPTY_TOTALS3,
|
|
@@ -10940,33 +12020,33 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10940
12020
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
10941
12021
|
modelCatalog: EMPTY_MODEL_CATALOG
|
|
10942
12022
|
});
|
|
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 =
|
|
12023
|
+
const [provision, setProvision] = React21.useState(null);
|
|
12024
|
+
const [busy, setBusy] = React21.useState(false);
|
|
12025
|
+
const [busyByBot, setBusyByBot] = React21.useState({});
|
|
12026
|
+
const [feedbackByBot, setFeedbackByBot] = React21.useState({});
|
|
12027
|
+
const [removeTarget, setRemoveTarget] = React21.useState(null);
|
|
12028
|
+
const [notice, setNotice] = React21.useState("");
|
|
12029
|
+
const [now, setNow] = React21.useState(() => Date.now());
|
|
12030
|
+
const addButtonRef = React21.useRef(null);
|
|
12031
|
+
const mountedRef = React21.useRef(true);
|
|
10952
12032
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
10953
12033
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
10954
|
-
|
|
12034
|
+
React21.useEffect(() => {
|
|
10955
12035
|
mountedRef.current = true;
|
|
10956
12036
|
return () => {
|
|
10957
12037
|
mountedRef.current = false;
|
|
10958
12038
|
};
|
|
10959
12039
|
}, []);
|
|
10960
|
-
const announce =
|
|
12040
|
+
const announce = React21.useCallback((value) => {
|
|
10961
12041
|
setNotice("");
|
|
10962
12042
|
scheduleAnimationFrame(() => {
|
|
10963
12043
|
if (value) setNotice(value);
|
|
10964
12044
|
}, "announcement");
|
|
10965
12045
|
}, [scheduleAnimationFrame]);
|
|
10966
|
-
const invoke =
|
|
10967
|
-
return
|
|
12046
|
+
const invoke = React21.useCallback(async (endpoint, payload = {}, signal) => {
|
|
12047
|
+
return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
|
|
10968
12048
|
}, [rpcCall]);
|
|
10969
|
-
const loadStatus =
|
|
12049
|
+
const loadStatus = React21.useCallback(async ({
|
|
10970
12050
|
signal,
|
|
10971
12051
|
silent = false,
|
|
10972
12052
|
restoreProvisioning = false
|
|
@@ -10975,7 +12055,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10975
12055
|
if (workspaceVersion === null || !mountedRef.current) return void 0;
|
|
10976
12056
|
if (!silent) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
10977
12057
|
try {
|
|
10978
|
-
const snapshot =
|
|
12058
|
+
const snapshot = normalizeSnapshot8(await invoke(WEIXIN_ENDPOINTS.status, {}, signal));
|
|
10979
12059
|
if (signal?.aborted || !mountedRef.current || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
10980
12060
|
setModel({
|
|
10981
12061
|
phase: "ready",
|
|
@@ -10999,17 +12079,17 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
10999
12079
|
setModel((current) => ({
|
|
11000
12080
|
...current,
|
|
11001
12081
|
phase: silent && current.phase === "ready" ? "ready" : "error",
|
|
11002
|
-
error:
|
|
12082
|
+
error: presentError9(error)
|
|
11003
12083
|
}));
|
|
11004
12084
|
return void 0;
|
|
11005
12085
|
}
|
|
11006
12086
|
}, [invoke, workspaceFence]);
|
|
11007
|
-
|
|
12087
|
+
React21.useEffect(() => {
|
|
11008
12088
|
const controller = new AbortController();
|
|
11009
12089
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
11010
12090
|
return () => controller.abort();
|
|
11011
12091
|
}, [loadStatus]);
|
|
11012
|
-
|
|
12092
|
+
React21.useEffect(() => {
|
|
11013
12093
|
if (model.phase !== "ready") return void 0;
|
|
11014
12094
|
const controller = new AbortController();
|
|
11015
12095
|
let running = false;
|
|
@@ -11028,12 +12108,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11028
12108
|
window.clearInterval(timer);
|
|
11029
12109
|
};
|
|
11030
12110
|
}, [loadStatus, model.phase]);
|
|
11031
|
-
|
|
12111
|
+
React21.useEffect(() => {
|
|
11032
12112
|
if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
|
|
11033
12113
|
const timer = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
11034
12114
|
return () => window.clearInterval(timer);
|
|
11035
12115
|
}, [provision?.attemptId, provision?.status]);
|
|
11036
|
-
const startProvisioning =
|
|
12116
|
+
const startProvisioning = React21.useCallback(async ({ replace = false } = {}) => {
|
|
11037
12117
|
setBusy(true);
|
|
11038
12118
|
try {
|
|
11039
12119
|
if (replace && provision?.attemptId) {
|
|
@@ -11047,14 +12127,14 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11047
12127
|
} catch (error) {
|
|
11048
12128
|
setProvision({
|
|
11049
12129
|
status: "failed",
|
|
11050
|
-
error:
|
|
12130
|
+
error: presentError9(error),
|
|
11051
12131
|
...provision?.attemptId ? { attemptId: provision.attemptId } : {}
|
|
11052
12132
|
});
|
|
11053
12133
|
} finally {
|
|
11054
12134
|
setBusy(false);
|
|
11055
12135
|
}
|
|
11056
12136
|
}, [announce, invoke, provision?.attemptId]);
|
|
11057
|
-
const cancelProvisioning =
|
|
12137
|
+
const cancelProvisioning = React21.useCallback(async () => {
|
|
11058
12138
|
setBusy(true);
|
|
11059
12139
|
try {
|
|
11060
12140
|
if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
|
|
@@ -11064,12 +12144,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11064
12144
|
announce("\u5DF2\u53D6\u6D88\u5FAE\u4FE1\u7ED1\u5B9A\u3002");
|
|
11065
12145
|
scheduleAnimationFrame(() => addButtonRef.current?.focus(), "focus");
|
|
11066
12146
|
} catch (error) {
|
|
11067
|
-
setProvision((current) => ({ ...current, status: "failed", error:
|
|
12147
|
+
setProvision((current) => ({ ...current, status: "failed", error: presentError9(error) }));
|
|
11068
12148
|
} finally {
|
|
11069
12149
|
setBusy(false);
|
|
11070
12150
|
}
|
|
11071
12151
|
}, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
|
|
11072
|
-
const submitVerification =
|
|
12152
|
+
const submitVerification = React21.useCallback(async (verifyCode) => {
|
|
11073
12153
|
if (!provision?.attemptId) return;
|
|
11074
12154
|
setBusy(true);
|
|
11075
12155
|
try {
|
|
@@ -11080,12 +12160,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11080
12160
|
setProvision((current) => ({ ...current, ...next }));
|
|
11081
12161
|
announce("\u914D\u5BF9\u7801\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u7B49\u5F85\u5FAE\u4FE1\u786E\u8BA4\u3002");
|
|
11082
12162
|
} catch (error) {
|
|
11083
|
-
setProvision((current) => ({ ...current, status: "failed", error:
|
|
12163
|
+
setProvision((current) => ({ ...current, status: "failed", error: presentError9(error) }));
|
|
11084
12164
|
} finally {
|
|
11085
12165
|
setBusy(false);
|
|
11086
12166
|
}
|
|
11087
12167
|
}, [announce, invoke, provision?.attemptId]);
|
|
11088
|
-
|
|
12168
|
+
React21.useEffect(() => {
|
|
11089
12169
|
const attemptId = provision?.attemptId;
|
|
11090
12170
|
if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
|
|
11091
12171
|
const controller = new AbortController();
|
|
@@ -11124,7 +12204,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11124
12204
|
}
|
|
11125
12205
|
} catch (error) {
|
|
11126
12206
|
if (scheduler.disposed || error?.name === "AbortError") return;
|
|
11127
|
-
setProvision((current) => current?.attemptId === attemptId ? { ...current, status: "failed", error:
|
|
12207
|
+
setProvision((current) => current?.attemptId === attemptId ? { ...current, status: "failed", error: presentError9(error) } : current);
|
|
11128
12208
|
}
|
|
11129
12209
|
};
|
|
11130
12210
|
scheduler.schedule(poll, provision.pollIntervalMs ?? 1e3);
|
|
@@ -11133,7 +12213,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11133
12213
|
controller.abort();
|
|
11134
12214
|
};
|
|
11135
12215
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
|
|
11136
|
-
const setBotBusy =
|
|
12216
|
+
const setBotBusy = React21.useCallback((botId, value) => {
|
|
11137
12217
|
setBusyByBot((current) => {
|
|
11138
12218
|
const next = { ...current };
|
|
11139
12219
|
if (value) next[botId] = value;
|
|
@@ -11141,7 +12221,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11141
12221
|
return next;
|
|
11142
12222
|
});
|
|
11143
12223
|
}, []);
|
|
11144
|
-
const reconnect =
|
|
12224
|
+
const reconnect = React21.useCallback(async (account) => {
|
|
11145
12225
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11146
12226
|
setBotBusy(account.botId, "reconnect");
|
|
11147
12227
|
setFeedbackByBot((current) => {
|
|
@@ -11150,7 +12230,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11150
12230
|
return next;
|
|
11151
12231
|
});
|
|
11152
12232
|
try {
|
|
11153
|
-
const snapshot =
|
|
12233
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11154
12234
|
WEIXIN_ENDPOINTS.reconnectBot,
|
|
11155
12235
|
{ botId: account.botId, sendTest: true }
|
|
11156
12236
|
));
|
|
@@ -11193,11 +12273,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11193
12273
|
setBotBusy(account.botId, null);
|
|
11194
12274
|
}
|
|
11195
12275
|
}, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11196
|
-
const saveWorkspace =
|
|
12276
|
+
const saveWorkspace = React21.useCallback(async (account, workspace) => {
|
|
11197
12277
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
11198
12278
|
setBotBusy(account.botId, "workspace");
|
|
11199
12279
|
try {
|
|
11200
|
-
const snapshot =
|
|
12280
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11201
12281
|
WEIXIN_ENDPOINTS.setWorkspace,
|
|
11202
12282
|
{ botId: account.botId, workspace }
|
|
11203
12283
|
));
|
|
@@ -11218,11 +12298,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11218
12298
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
11219
12299
|
}
|
|
11220
12300
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11221
|
-
const saveBotSetting =
|
|
12301
|
+
const saveBotSetting = React21.useCallback(async (account, operation, endpoint, payload) => {
|
|
11222
12302
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11223
12303
|
setBotBusy(account.botId, operation);
|
|
11224
12304
|
try {
|
|
11225
|
-
const snapshot =
|
|
12305
|
+
const snapshot = normalizeSnapshot8(await invoke(
|
|
11226
12306
|
endpoint,
|
|
11227
12307
|
{ botId: account.botId, ...payload }
|
|
11228
12308
|
));
|
|
@@ -11243,11 +12323,11 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11243
12323
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
11244
12324
|
}
|
|
11245
12325
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
11246
|
-
const remove =
|
|
12326
|
+
const remove = React21.useCallback(async (account) => {
|
|
11247
12327
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
11248
12328
|
setBotBusy(account.botId, "delete");
|
|
11249
12329
|
try {
|
|
11250
|
-
const snapshot =
|
|
12330
|
+
const snapshot = normalizeSnapshot8(await invoke(WEIXIN_ENDPOINTS.deleteBot, {
|
|
11251
12331
|
botId: account.botId,
|
|
11252
12332
|
confirm: true
|
|
11253
12333
|
}));
|
|
@@ -11264,7 +12344,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11264
12344
|
setRemoveTarget(null);
|
|
11265
12345
|
announce("\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002");
|
|
11266
12346
|
} catch (error) {
|
|
11267
|
-
announce(`\u79FB\u9664\u5931\u8D25\uFF1A${
|
|
12347
|
+
announce(`\u79FB\u9664\u5931\u8D25\uFF1A${presentError9(error).message}`);
|
|
11268
12348
|
} finally {
|
|
11269
12349
|
const shouldRefresh = workspaceFence.endMutation();
|
|
11270
12350
|
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
@@ -11310,7 +12390,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11310
12390
|
}, h2(
|
|
11311
12391
|
"section",
|
|
11312
12392
|
{ className: "dxw-page dim-channelPage", "aria-label": "\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
11313
|
-
h2(
|
|
12393
|
+
h2(Heading6, {
|
|
11314
12394
|
totals: model.totals,
|
|
11315
12395
|
adding: Boolean(provision),
|
|
11316
12396
|
busy,
|
|
@@ -11319,7 +12399,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11319
12399
|
}),
|
|
11320
12400
|
h2("div", { className: "dxw-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
11321
12401
|
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(
|
|
12402
|
+
model.phase === "loading" ? h2(LoadingView6) : model.phase === "error" ? h2(
|
|
11323
12403
|
"div",
|
|
11324
12404
|
{ className: "dxw-card dim-surfaceCard" },
|
|
11325
12405
|
h2(
|
|
@@ -11327,13 +12407,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11327
12407
|
{ className: "dxw-error dim-inlineError" },
|
|
11328
12408
|
h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6\u5FAE\u4FE1\u72B6\u6001"),
|
|
11329
12409
|
h2("p", null, model.error?.message ?? "\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
|
|
11330
|
-
h2(
|
|
12410
|
+
h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
11331
12411
|
)
|
|
11332
12412
|
) : h2(
|
|
11333
|
-
|
|
12413
|
+
React21.Fragment,
|
|
11334
12414
|
null,
|
|
11335
12415
|
provisionView,
|
|
11336
|
-
model.bots.length === 0 && !provision ? h2(
|
|
12416
|
+
model.bots.length === 0 && !provision ? h2(EmptyView6, { onStart: () => void startProvisioning(), busy }) : null,
|
|
11337
12417
|
model.bots.length > 0 ? h2(AccountList2, {
|
|
11338
12418
|
bots: model.bots,
|
|
11339
12419
|
busyByBot,
|
|
@@ -11369,7 +12449,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
11369
12449
|
|
|
11370
12450
|
// plugin-src/client/channels/weixin/styles.js
|
|
11371
12451
|
var WEIXIN_STYLE_ID = "xmanrui-dsh-im-weixin-settings";
|
|
11372
|
-
var
|
|
12452
|
+
var CSS10 = String.raw`
|
|
11373
12453
|
.dxw-page {
|
|
11374
12454
|
--dxw-accent: #07c160;
|
|
11375
12455
|
--dxw-accent-dark: #05994c;
|
|
@@ -11479,7 +12559,7 @@ function installWeixinStyles() {
|
|
|
11479
12559
|
const style = document.createElement("style");
|
|
11480
12560
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
11481
12561
|
style.dataset.pluginCss = WEIXIN_STYLE_ID;
|
|
11482
|
-
style.textContent =
|
|
12562
|
+
style.textContent = CSS10;
|
|
11483
12563
|
document.head.appendChild(style);
|
|
11484
12564
|
return () => style.remove();
|
|
11485
12565
|
}
|
|
@@ -11502,28 +12582,28 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
11502
12582
|
var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
|
|
11503
12583
|
var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
11504
12584
|
var QR_DATA_URL4 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
11505
|
-
function
|
|
12585
|
+
function isRecord8(value) {
|
|
11506
12586
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11507
12587
|
}
|
|
11508
|
-
function
|
|
12588
|
+
function text6(value, fallback, max = 240) {
|
|
11509
12589
|
return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
|
|
11510
12590
|
}
|
|
11511
|
-
function
|
|
11512
|
-
const result =
|
|
12591
|
+
function id5(value) {
|
|
12592
|
+
const result = text6(value, "", 128);
|
|
11513
12593
|
return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
|
|
11514
12594
|
}
|
|
11515
|
-
function
|
|
12595
|
+
function timestamp7(value) {
|
|
11516
12596
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
11517
12597
|
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
11518
12598
|
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
11519
12599
|
}
|
|
11520
|
-
function
|
|
11521
|
-
if (!
|
|
12600
|
+
function unwrapRpcResult10(result) {
|
|
12601
|
+
if (!isRecord8(result) || typeof result.ok !== "boolean") {
|
|
11522
12602
|
throw new Error("WhatsApp \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
11523
12603
|
}
|
|
11524
12604
|
if (!result.ok) {
|
|
11525
|
-
const error = new Error(
|
|
11526
|
-
error.code =
|
|
12605
|
+
const error = new Error(text6(result.error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25"));
|
|
12606
|
+
error.code = text6(result.error?.code, "WHATSAPP_RPC_ERROR", 80);
|
|
11527
12607
|
throw error;
|
|
11528
12608
|
}
|
|
11529
12609
|
return result.value;
|
|
@@ -11532,61 +12612,61 @@ function safeQrSource6(value) {
|
|
|
11532
12612
|
return typeof value === "string" && value.length <= 2 * 1024 * 1024 && QR_DATA_URL4.test(value) ? value : void 0;
|
|
11533
12613
|
}
|
|
11534
12614
|
function normalizeProvisioning6(value, now = Date.now()) {
|
|
11535
|
-
const source =
|
|
11536
|
-
if (!
|
|
11537
|
-
const attemptId =
|
|
12615
|
+
const source = isRecord8(value?.provisioning) ? value.provisioning : value;
|
|
12616
|
+
if (!isRecord8(source)) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6");
|
|
12617
|
+
const attemptId = id5(source.attemptId);
|
|
11538
12618
|
if (!attemptId) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1");
|
|
11539
|
-
const reported =
|
|
12619
|
+
const reported = text6(source.status, "failed", 32);
|
|
11540
12620
|
const result = {
|
|
11541
12621
|
attemptId,
|
|
11542
12622
|
status: PROVISION_STATES5.has(reported) ? reported : "failed",
|
|
11543
|
-
expiresAt:
|
|
12623
|
+
expiresAt: timestamp7(source.expiresAt) ?? now + 6e4,
|
|
11544
12624
|
pollIntervalMs: Math.min(5e3, Math.max(500, Number(source.pollIntervalMs) || 1e3)),
|
|
11545
12625
|
qrRevision: Number.isSafeInteger(source.qrRevision) ? source.qrRevision : 0
|
|
11546
12626
|
};
|
|
11547
12627
|
const qrCodeDataUrl = safeQrSource6(source.qrCodeDataUrl);
|
|
11548
12628
|
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
11549
|
-
if (
|
|
11550
|
-
if (
|
|
11551
|
-
code:
|
|
11552
|
-
message:
|
|
12629
|
+
if (id5(source.botId)) result.botId = id5(source.botId);
|
|
12630
|
+
if (isRecord8(source.error)) result.error = {
|
|
12631
|
+
code: text6(source.error.code, "WHATSAPP_PROVISION_FAILED", 80),
|
|
12632
|
+
message: text6(source.error.message, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
|
|
11553
12633
|
};
|
|
11554
12634
|
return result;
|
|
11555
12635
|
}
|
|
11556
|
-
function
|
|
11557
|
-
if (!
|
|
12636
|
+
function normalizeBot7(value) {
|
|
12637
|
+
if (!isRecord8(value) || !id5(value.botId)) return void 0;
|
|
11558
12638
|
const connected = value.connected === true;
|
|
11559
12639
|
const state = BOT_STATES.has(value.state) ? value.state : "offline";
|
|
11560
12640
|
return {
|
|
11561
|
-
botId:
|
|
12641
|
+
botId: id5(value.botId),
|
|
11562
12642
|
connected,
|
|
11563
12643
|
state: connected ? "connected" : state,
|
|
11564
|
-
workspace:
|
|
12644
|
+
workspace: text6(value.workspace, "", 4096),
|
|
11565
12645
|
model: normalizeModelSelection(value.model),
|
|
11566
12646
|
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
11567
12647
|
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
|
11568
12648
|
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
|
11569
12649
|
bot: {
|
|
11570
|
-
name:
|
|
11571
|
-
idMasked:
|
|
12650
|
+
name: text6(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
|
|
12651
|
+
idMasked: text6(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
|
|
11572
12652
|
},
|
|
11573
12653
|
health: {
|
|
11574
|
-
summary:
|
|
11575
|
-
lastCheckedAt:
|
|
12654
|
+
summary: text6(value.health?.summary, connected ? "WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38" : "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
12655
|
+
lastCheckedAt: timestamp7(value.health?.lastCheckedAt)
|
|
11576
12656
|
},
|
|
11577
12657
|
lastMessageError: normalizeLastMessageError(value.lastMessageError),
|
|
11578
|
-
error:
|
|
11579
|
-
code:
|
|
11580
|
-
message:
|
|
12658
|
+
error: isRecord8(value.error) ? {
|
|
12659
|
+
code: text6(value.error.code, "WHATSAPP_ACCOUNT_ERROR", 80),
|
|
12660
|
+
message: text6(value.error.message, "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
|
|
11581
12661
|
} : null
|
|
11582
12662
|
};
|
|
11583
12663
|
}
|
|
11584
|
-
function
|
|
11585
|
-
const source =
|
|
11586
|
-
if (!
|
|
12664
|
+
function normalizeSnapshot9(value) {
|
|
12665
|
+
const source = isRecord8(value?.snapshot) ? value.snapshot : value;
|
|
12666
|
+
if (!isRecord8(source) || !Array.isArray(source.bots)) {
|
|
11587
12667
|
throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
11588
12668
|
}
|
|
11589
|
-
const bots = source.bots.map(
|
|
12669
|
+
const bots = source.bots.map(normalizeBot7).filter(Boolean);
|
|
11590
12670
|
return {
|
|
11591
12671
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
11592
12672
|
bots,
|
|
@@ -11596,10 +12676,10 @@ function normalizeSnapshot8(value) {
|
|
|
11596
12676
|
modelCatalog: normalizeModelCatalog(source.modelCatalog)
|
|
11597
12677
|
};
|
|
11598
12678
|
}
|
|
11599
|
-
function
|
|
12679
|
+
function presentError10(error) {
|
|
11600
12680
|
return {
|
|
11601
|
-
code:
|
|
11602
|
-
message:
|
|
12681
|
+
code: text6(error?.code, "WHATSAPP_ERROR", 80),
|
|
12682
|
+
message: text6(error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
11603
12683
|
};
|
|
11604
12684
|
}
|
|
11605
12685
|
function formatRemaining6(milliseconds) {
|
|
@@ -11608,11 +12688,11 @@ function formatRemaining6(milliseconds) {
|
|
|
11608
12688
|
}
|
|
11609
12689
|
|
|
11610
12690
|
// plugin-src/client/channels/whatsapp/index.js
|
|
11611
|
-
var
|
|
12691
|
+
var React22 = __toESM(require("react"), 1);
|
|
11612
12692
|
|
|
11613
12693
|
// plugin-src/client/channels/whatsapp/styles.js
|
|
11614
12694
|
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
|
11615
|
-
var
|
|
12695
|
+
var CSS11 = String.raw`
|
|
11616
12696
|
.dwa-page { --ddt-accent: #25d366; --ddt-accent-deep: #128c7e; --ddt-accent-wash: #eafbf0; }
|
|
11617
12697
|
.dwa-avatar { color: #fff; background: #25d366; }
|
|
11618
12698
|
.dwa-avatar svg { display: block; }
|
|
@@ -11626,14 +12706,14 @@ function installWhatsappStyles() {
|
|
|
11626
12706
|
const style = document.createElement("style");
|
|
11627
12707
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
11628
12708
|
style.dataset.pluginCss = WHATSAPP_STYLE_ID;
|
|
11629
|
-
style.textContent =
|
|
12709
|
+
style.textContent = CSS11;
|
|
11630
12710
|
document.head.appendChild(style);
|
|
11631
12711
|
return () => style.remove();
|
|
11632
12712
|
}
|
|
11633
12713
|
|
|
11634
12714
|
// plugin-src/client/channels/whatsapp/index.js
|
|
11635
12715
|
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
|
11636
|
-
var
|
|
12716
|
+
var Button16 = React22.forwardRef(function Button17({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
11637
12717
|
return h2("button", {
|
|
11638
12718
|
...props,
|
|
11639
12719
|
ref,
|
|
@@ -11642,7 +12722,7 @@ var Button14 = React21.forwardRef(function Button15({ children, kind = "secondar
|
|
|
11642
12722
|
"data-kind": kind
|
|
11643
12723
|
}, children);
|
|
11644
12724
|
});
|
|
11645
|
-
function
|
|
12725
|
+
function checkedTime7(value) {
|
|
11646
12726
|
if (!value) return "\u5C1A\u672A\u68C0\u67E5";
|
|
11647
12727
|
try {
|
|
11648
12728
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
@@ -11663,7 +12743,7 @@ function connectionTestNotice3(value) {
|
|
|
11663
12743
|
}
|
|
11664
12744
|
return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
11665
12745
|
}
|
|
11666
|
-
function
|
|
12746
|
+
function Heading7({ totals, busy, onAdd, addButtonRef }) {
|
|
11667
12747
|
return h2(
|
|
11668
12748
|
"div",
|
|
11669
12749
|
{ className: "ddt-heading" },
|
|
@@ -11673,7 +12753,7 @@ function Heading6({ totals, busy, onAdd, addButtonRef }) {
|
|
|
11673
12753
|
h2(
|
|
11674
12754
|
"div",
|
|
11675
12755
|
{ className: "dim-bindActions" },
|
|
11676
|
-
h2(
|
|
12756
|
+
h2(Button16, {
|
|
11677
12757
|
kind: "primary",
|
|
11678
12758
|
className: "dim-scanButton",
|
|
11679
12759
|
onClick: onAdd,
|
|
@@ -11690,13 +12770,13 @@ function Heading6({ totals, busy, onAdd, addButtonRef }) {
|
|
|
11690
12770
|
)
|
|
11691
12771
|
);
|
|
11692
12772
|
}
|
|
11693
|
-
function
|
|
12773
|
+
function LoadingView7() {
|
|
11694
12774
|
return h2("div", {
|
|
11695
12775
|
className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView",
|
|
11696
12776
|
"aria-busy": "true"
|
|
11697
12777
|
}, h2("div", { className: "ddt-spinner dim-spinner" }), "\u6B63\u5728\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001\u2026");
|
|
11698
12778
|
}
|
|
11699
|
-
function
|
|
12779
|
+
function EmptyView7({ busy, onStart }) {
|
|
11700
12780
|
return h2(
|
|
11701
12781
|
"div",
|
|
11702
12782
|
{ className: "ddt-card dim-surfaceCard" },
|
|
@@ -11718,7 +12798,7 @@ function EmptyView6({ busy, onStart }) {
|
|
|
11718
12798
|
"div",
|
|
11719
12799
|
{ className: "ddt-actions dim-viewActions" },
|
|
11720
12800
|
h2(
|
|
11721
|
-
|
|
12801
|
+
Button16,
|
|
11722
12802
|
{ kind: "primary", onClick: onStart, disabled: busy },
|
|
11723
12803
|
busy ? "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" : "\u751F\u6210\u4E8C\u7EF4\u7801"
|
|
11724
12804
|
)
|
|
@@ -11787,8 +12867,8 @@ function QrPanel5({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
11787
12867
|
h2(
|
|
11788
12868
|
"div",
|
|
11789
12869
|
{ className: "ddt-actions dim-viewActions" },
|
|
11790
|
-
h2(
|
|
11791
|
-
h2(
|
|
12870
|
+
h2(Button16, { onClick: onRefresh, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
12871
|
+
h2(Button16, { kind: "quiet", onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
11792
12872
|
)
|
|
11793
12873
|
)
|
|
11794
12874
|
)
|
|
@@ -11824,13 +12904,13 @@ function ProvisionView3({ provision, busy, onRetry, onClose }) {
|
|
|
11824
12904
|
h2(
|
|
11825
12905
|
"div",
|
|
11826
12906
|
{ className: "ddt-actions dim-viewActions" },
|
|
11827
|
-
h2(
|
|
11828
|
-
h2(
|
|
12907
|
+
h2(Button16, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
12908
|
+
h2(Button16, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
|
|
11829
12909
|
)
|
|
11830
12910
|
)
|
|
11831
12911
|
);
|
|
11832
12912
|
}
|
|
11833
|
-
function
|
|
12913
|
+
function RemoveConfirmation6({ account, busy, onConfirm, onCancel }) {
|
|
11834
12914
|
return h2(
|
|
11835
12915
|
"div",
|
|
11836
12916
|
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
@@ -11839,9 +12919,9 @@ function RemoveConfirmation5({ account, busy, onConfirm, onCancel }) {
|
|
|
11839
12919
|
h2(
|
|
11840
12920
|
"div",
|
|
11841
12921
|
{ className: "ddt-actions dim-viewActions" },
|
|
11842
|
-
h2(
|
|
12922
|
+
h2(Button16, { onClick: onCancel, disabled: busy }, "\u4FDD\u7559\u673A\u5668\u4EBA"),
|
|
11843
12923
|
h2(
|
|
11844
|
-
|
|
12924
|
+
Button16,
|
|
11845
12925
|
{ kind: "danger", onClick: onConfirm, disabled: busy },
|
|
11846
12926
|
busy ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664\u63A5\u5165"
|
|
11847
12927
|
)
|
|
@@ -11911,7 +12991,7 @@ function WhatsappAccountCard({
|
|
|
11911
12991
|
tone,
|
|
11912
12992
|
stateLabel: stateLabel2,
|
|
11913
12993
|
lastCheckedAt: account.health.lastCheckedAt,
|
|
11914
|
-
formatCheckedTime:
|
|
12994
|
+
formatCheckedTime: checkedTime7
|
|
11915
12995
|
}),
|
|
11916
12996
|
h2(BotSettingsButton, {
|
|
11917
12997
|
channel: "whatsapp",
|
|
@@ -11952,12 +13032,12 @@ function WhatsappAccountCard({
|
|
|
11952
13032
|
h2(
|
|
11953
13033
|
"div",
|
|
11954
13034
|
{ className: "ddt-actions dim-cardActions" },
|
|
11955
|
-
h2(
|
|
13035
|
+
h2(Button16, {
|
|
11956
13036
|
className: "dim-cardAction",
|
|
11957
13037
|
onClick: onReconnect,
|
|
11958
13038
|
disabled: Boolean(busy)
|
|
11959
13039
|
}, busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
|
|
11960
|
-
h2(
|
|
13040
|
+
h2(Button16, {
|
|
11961
13041
|
className: "dim-cardAction",
|
|
11962
13042
|
kind: "danger",
|
|
11963
13043
|
onClick: onRequestRemove,
|
|
@@ -11977,7 +13057,7 @@ function WhatsappAccountCard({
|
|
|
11977
13057
|
)
|
|
11978
13058
|
)
|
|
11979
13059
|
),
|
|
11980
|
-
removing ? h2(
|
|
13060
|
+
removing ? h2(RemoveConfirmation6, {
|
|
11981
13061
|
account,
|
|
11982
13062
|
busy: busy === "delete",
|
|
11983
13063
|
onConfirm: onConfirmRemove,
|
|
@@ -11986,7 +13066,7 @@ function WhatsappAccountCard({
|
|
|
11986
13066
|
);
|
|
11987
13067
|
}
|
|
11988
13068
|
function WhatsappSettingsTab({ rpcCall }) {
|
|
11989
|
-
const [model, setModel] =
|
|
13069
|
+
const [model, setModel] = React22.useState({
|
|
11990
13070
|
phase: "loading",
|
|
11991
13071
|
bots: [],
|
|
11992
13072
|
totals: { configured: 0, connected: 0 },
|
|
@@ -11994,16 +13074,16 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
11994
13074
|
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
|
11995
13075
|
modelCatalog: EMPTY_MODEL_CATALOG
|
|
11996
13076
|
});
|
|
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 =
|
|
13077
|
+
const [provision, setProvision] = React22.useState(null);
|
|
13078
|
+
const [busy, setBusy] = React22.useState(false);
|
|
13079
|
+
const [busyByBot, setBusyByBot] = React22.useState({});
|
|
13080
|
+
const [testNoticeByBot, setTestNoticeByBot] = React22.useState({});
|
|
13081
|
+
const [removeTarget, setRemoveTarget] = React22.useState(null);
|
|
13082
|
+
const [now, setNow] = React22.useState(Date.now());
|
|
13083
|
+
const mounted = React22.useRef(true);
|
|
12004
13084
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
12005
|
-
const addButtonRef =
|
|
12006
|
-
|
|
13085
|
+
const addButtonRef = React22.useRef(null);
|
|
13086
|
+
React22.useEffect(() => {
|
|
12007
13087
|
const disposeDingtalk = installDingtalkStyles();
|
|
12008
13088
|
const disposeWhatsapp = installWhatsappStyles();
|
|
12009
13089
|
mounted.current = true;
|
|
@@ -12013,16 +13093,16 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12013
13093
|
disposeDingtalk();
|
|
12014
13094
|
};
|
|
12015
13095
|
}, []);
|
|
12016
|
-
const invoke =
|
|
13096
|
+
const invoke = React22.useCallback(async (endpoint, payload = {}, signal) => {
|
|
12017
13097
|
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
12018
|
-
return
|
|
13098
|
+
return unwrapRpcResult10(await rpcCall(endpoint, payload, signal));
|
|
12019
13099
|
}, [rpcCall]);
|
|
12020
|
-
const loadStatus =
|
|
13100
|
+
const loadStatus = React22.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
12021
13101
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
12022
13102
|
if (workspaceVersion === null) return void 0;
|
|
12023
13103
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
12024
13104
|
try {
|
|
12025
|
-
const snapshot =
|
|
13105
|
+
const snapshot = normalizeSnapshot9(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
12026
13106
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
12027
13107
|
setModel({
|
|
12028
13108
|
phase: "ready",
|
|
@@ -12042,18 +13122,18 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12042
13122
|
setModel((current) => ({
|
|
12043
13123
|
...current,
|
|
12044
13124
|
phase: silent ? current.phase : "error",
|
|
12045
|
-
error:
|
|
13125
|
+
error: presentError10(error)
|
|
12046
13126
|
}));
|
|
12047
13127
|
}
|
|
12048
13128
|
return void 0;
|
|
12049
13129
|
}
|
|
12050
13130
|
}, [invoke, workspaceFence]);
|
|
12051
|
-
|
|
13131
|
+
React22.useEffect(() => {
|
|
12052
13132
|
const controller = new AbortController();
|
|
12053
13133
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
12054
13134
|
return () => controller.abort();
|
|
12055
13135
|
}, [loadStatus]);
|
|
12056
|
-
|
|
13136
|
+
React22.useEffect(() => {
|
|
12057
13137
|
if (model.phase !== "ready") return void 0;
|
|
12058
13138
|
const controller = new AbortController();
|
|
12059
13139
|
const timer = window.setInterval(
|
|
@@ -12065,12 +13145,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12065
13145
|
window.clearInterval(timer);
|
|
12066
13146
|
};
|
|
12067
13147
|
}, [loadStatus, model.phase]);
|
|
12068
|
-
|
|
13148
|
+
React22.useEffect(() => {
|
|
12069
13149
|
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
12070
13150
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
12071
13151
|
return () => window.clearInterval(timer);
|
|
12072
13152
|
}, [provision?.attemptId, provision?.status]);
|
|
12073
|
-
const startProvisioning =
|
|
13153
|
+
const startProvisioning = React22.useCallback(async (replace = false) => {
|
|
12074
13154
|
setBusy(true);
|
|
12075
13155
|
try {
|
|
12076
13156
|
if (replace && provision?.attemptId) {
|
|
@@ -12083,12 +13163,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12083
13163
|
setNow(Date.now());
|
|
12084
13164
|
setProvision({ ...started, durationMs: Math.max(1, started.expiresAt - Date.now()) });
|
|
12085
13165
|
} catch (error) {
|
|
12086
|
-
if (mounted.current) setProvision({ status: "failed", error:
|
|
13166
|
+
if (mounted.current) setProvision({ status: "failed", error: presentError10(error) });
|
|
12087
13167
|
} finally {
|
|
12088
13168
|
if (mounted.current) setBusy(false);
|
|
12089
13169
|
}
|
|
12090
13170
|
}, [invoke, provision?.attemptId]);
|
|
12091
|
-
const closeProvision =
|
|
13171
|
+
const closeProvision = React22.useCallback(async () => {
|
|
12092
13172
|
setBusy(true);
|
|
12093
13173
|
try {
|
|
12094
13174
|
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
|
@@ -12099,7 +13179,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12099
13179
|
if (mounted.current) setBusy(false);
|
|
12100
13180
|
}
|
|
12101
13181
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
12102
|
-
|
|
13182
|
+
React22.useEffect(() => {
|
|
12103
13183
|
const attemptId = provision?.attemptId;
|
|
12104
13184
|
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
12105
13185
|
const controller = new AbortController();
|
|
@@ -12129,7 +13209,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12129
13209
|
if (ACTIVE_STATES3.has(current.status)) schedule(current.pollIntervalMs);
|
|
12130
13210
|
} catch (error) {
|
|
12131
13211
|
if (!disposed && !controller.signal.aborted && mounted.current) {
|
|
12132
|
-
setProvision({ status: "failed", error:
|
|
13212
|
+
setProvision({ status: "failed", error: presentError10(error) });
|
|
12133
13213
|
}
|
|
12134
13214
|
}
|
|
12135
13215
|
};
|
|
@@ -12140,7 +13220,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12140
13220
|
if (timer) window.clearTimeout(timer);
|
|
12141
13221
|
};
|
|
12142
13222
|
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
|
12143
|
-
const botAction =
|
|
13223
|
+
const botAction = React22.useCallback(async (account, operation, endpoint, payload) => {
|
|
12144
13224
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
12145
13225
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
12146
13226
|
if (operation === "reconnect") {
|
|
@@ -12152,7 +13232,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12152
13232
|
}
|
|
12153
13233
|
try {
|
|
12154
13234
|
const value = await invoke(endpoint, payload);
|
|
12155
|
-
const snapshot =
|
|
13235
|
+
const snapshot = normalizeSnapshot9(value);
|
|
12156
13236
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
12157
13237
|
setModel({
|
|
12158
13238
|
phase: "ready",
|
|
@@ -12251,13 +13331,13 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12251
13331
|
className: "ddt-page dwa-page dim-channelPage",
|
|
12252
13332
|
"aria-label": "WhatsApp \u8BBE\u7F6E"
|
|
12253
13333
|
},
|
|
12254
|
-
h2(
|
|
13334
|
+
h2(Heading7, {
|
|
12255
13335
|
totals: model.totals,
|
|
12256
13336
|
busy,
|
|
12257
13337
|
onAdd: () => void startProvisioning(false),
|
|
12258
13338
|
addButtonRef
|
|
12259
13339
|
}),
|
|
12260
|
-
model.phase === "loading" ? h2(
|
|
13340
|
+
model.phase === "loading" ? h2(LoadingView7) : model.phase === "error" ? h2(
|
|
12261
13341
|
"div",
|
|
12262
13342
|
{ className: "ddt-card dim-surfaceCard" },
|
|
12263
13343
|
h2(
|
|
@@ -12265,10 +13345,10 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12265
13345
|
{ className: "ddt-inlineError dim-inlineError" },
|
|
12266
13346
|
h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001"),
|
|
12267
13347
|
h2("p", null, model.error?.message),
|
|
12268
|
-
h2(
|
|
13348
|
+
h2(Button16, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
12269
13349
|
)
|
|
12270
13350
|
) : h2(
|
|
12271
|
-
|
|
13351
|
+
React22.Fragment,
|
|
12272
13352
|
null,
|
|
12273
13353
|
provision?.status === "pending" ? h2(QrPanel5, {
|
|
12274
13354
|
provision,
|
|
@@ -12281,17 +13361,17 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
12281
13361
|
busy,
|
|
12282
13362
|
onRetry: () => void startProvisioning(true),
|
|
12283
13363
|
onClose: () => void closeProvision()
|
|
12284
|
-
}) : model.bots.length === 0 ? h2(
|
|
13364
|
+
}) : model.bots.length === 0 ? h2(EmptyView7, { busy, onStart: () => void startProvisioning(false) }) : null,
|
|
12285
13365
|
botList
|
|
12286
13366
|
)
|
|
12287
13367
|
)));
|
|
12288
13368
|
}
|
|
12289
13369
|
|
|
12290
13370
|
// plugin-src/client/delivery-settings.js
|
|
12291
|
-
var
|
|
13371
|
+
var React25 = __toESM(require("react"), 1);
|
|
12292
13372
|
|
|
12293
13373
|
// plugin-src/client/access-policy-settings.js
|
|
12294
|
-
var
|
|
13374
|
+
var React23 = __toESM(require("react"), 1);
|
|
12295
13375
|
var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
|
|
12296
13376
|
var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
|
12297
13377
|
weixin: Object.freeze({
|
|
@@ -12317,6 +13397,12 @@ var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
12317
13397
|
groupUserLabel: "\u7FA4\u6210\u5458\u7528\u6237 ID",
|
|
12318
13398
|
groupPlaceholder: "\u586B\u5199 userid"
|
|
12319
13399
|
}),
|
|
13400
|
+
wecomApp: Object.freeze({
|
|
13401
|
+
directUserLabel: "\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID",
|
|
13402
|
+
directPlaceholder: "\u586B\u5199 userid",
|
|
13403
|
+
groupUserLabel: "\u7FA4\u6210\u5458\u7528\u6237 ID",
|
|
13404
|
+
groupPlaceholder: "\u586B\u5199 userid"
|
|
13405
|
+
}),
|
|
12320
13406
|
qq: Object.freeze({
|
|
12321
13407
|
directUserLabel: "QQ User Open ID",
|
|
12322
13408
|
directPlaceholder: "\u586B\u5199 user_openid",
|
|
@@ -12366,7 +13452,7 @@ function clonePolicy(policy) {
|
|
|
12366
13452
|
group: cloneScope(policy.group)
|
|
12367
13453
|
};
|
|
12368
13454
|
}
|
|
12369
|
-
function
|
|
13455
|
+
function unwrapRpcResult11(result) {
|
|
12370
13456
|
if (result?.ok === true) return result.value;
|
|
12371
13457
|
if (result?.ok === false) {
|
|
12372
13458
|
const error = new Error(result.error?.message || "\u8BBF\u95EE\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -12393,8 +13479,8 @@ function ScenePolicyEditor({
|
|
|
12393
13479
|
unsupported = false,
|
|
12394
13480
|
onChange
|
|
12395
13481
|
}) {
|
|
12396
|
-
const ownerHelpId =
|
|
12397
|
-
const emptyAllowlistHelpId =
|
|
13482
|
+
const ownerHelpId = React23.useId();
|
|
13483
|
+
const emptyAllowlistHelpId = React23.useId();
|
|
12398
13484
|
const allowlist = policy.mode === "allowlist";
|
|
12399
13485
|
const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
|
|
12400
13486
|
const branchKey = allowlist ? "allowlist" : "open";
|
|
@@ -12446,7 +13532,7 @@ function ScenePolicyEditor({
|
|
|
12446
13532
|
h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
|
|
12447
13533
|
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
13534
|
) : h2(
|
|
12449
|
-
|
|
13535
|
+
React23.Fragment,
|
|
12450
13536
|
null,
|
|
12451
13537
|
h2(
|
|
12452
13538
|
"div",
|
|
@@ -12587,16 +13673,16 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12587
13673
|
const definition = ACCESS_CHANNEL_DEFINITIONS[channel4];
|
|
12588
13674
|
const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
|
|
12589
13675
|
const initialKey = JSON.stringify(initialPolicy);
|
|
12590
|
-
const [draft, setDraft] =
|
|
13676
|
+
const [draft, setDraft] = React23.useState(() => clonePolicy(
|
|
12591
13677
|
initialPolicy ?? DEFAULT_ACCESS_POLICY
|
|
12592
13678
|
));
|
|
12593
|
-
const [saving, setSaving] =
|
|
12594
|
-
const [feedback, setFeedback] =
|
|
12595
|
-
|
|
13679
|
+
const [saving, setSaving] = React23.useState(false);
|
|
13680
|
+
const [feedback, setFeedback] = React23.useState(null);
|
|
13681
|
+
React23.useEffect(() => {
|
|
12596
13682
|
const next = normalizeAccessPolicy(account?.accessPolicy);
|
|
12597
13683
|
setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
|
|
12598
13684
|
}, [account?.botId, initialKey]);
|
|
12599
|
-
|
|
13685
|
+
React23.useEffect(() => {
|
|
12600
13686
|
setFeedback(null);
|
|
12601
13687
|
}, [account?.botId]);
|
|
12602
13688
|
if (!definition) {
|
|
@@ -12613,7 +13699,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12613
13699
|
try {
|
|
12614
13700
|
const policy = validateAccessPolicy(draft);
|
|
12615
13701
|
if (typeof rpcCall !== "function") throw new Error("\u8BBF\u95EE\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
12616
|
-
const value =
|
|
13702
|
+
const value = unwrapRpcResult11(await rpcCall(ACCESS_POLICY_ENDPOINT, {
|
|
12617
13703
|
botId: account.botId,
|
|
12618
13704
|
policy
|
|
12619
13705
|
}));
|
|
@@ -12687,7 +13773,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|
|
12687
13773
|
}
|
|
12688
13774
|
|
|
12689
13775
|
// plugin-src/client/channels/feishu/group-settings.js
|
|
12690
|
-
var
|
|
13776
|
+
var React24 = __toESM(require("react"), 1);
|
|
12691
13777
|
var GROUP_MESSAGE_PERMISSION_OPERATION2 = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
12692
13778
|
function SettingsButton({ children, kind = "secondary", className = "", ...props }) {
|
|
12693
13779
|
return h2("button", {
|
|
@@ -12748,9 +13834,9 @@ function GroupResponseModeEditor({
|
|
|
12748
13834
|
onAuthorize
|
|
12749
13835
|
}) {
|
|
12750
13836
|
const current = normalizeGroupResponseMode(value);
|
|
12751
|
-
const [saving, setSaving] =
|
|
12752
|
-
const [authorizing, setAuthorizing] =
|
|
12753
|
-
const [error, setError] =
|
|
13837
|
+
const [saving, setSaving] = React24.useState(false);
|
|
13838
|
+
const [authorizing, setAuthorizing] = React24.useState(false);
|
|
13839
|
+
const [error, setError] = React24.useState(null);
|
|
12754
13840
|
const change = async (event) => {
|
|
12755
13841
|
const next = normalizeGroupResponseMode(event.target.value);
|
|
12756
13842
|
if (next === current || saving || disabled) return;
|
|
@@ -12831,8 +13917,8 @@ function GroupResponseModeEditor({
|
|
|
12831
13917
|
}
|
|
12832
13918
|
function GroupTopicReplyEditor({ value = false, disabled = false, onSave }) {
|
|
12833
13919
|
const current = value === true ? "on" : "off";
|
|
12834
|
-
const [saving, setSaving] =
|
|
12835
|
-
const [error, setError] =
|
|
13920
|
+
const [saving, setSaving] = React24.useState(false);
|
|
13921
|
+
const [error, setError] = React24.useState(null);
|
|
12836
13922
|
const change = async (event) => {
|
|
12837
13923
|
const next = event.target.value === "on";
|
|
12838
13924
|
if ((next ? "on" : "off") === current || saving || disabled) return;
|
|
@@ -13019,14 +14105,14 @@ function PermissionFlow({ provision, now, busy, botName, onRetry, onCancel, onCl
|
|
|
13019
14105
|
);
|
|
13020
14106
|
}
|
|
13021
14107
|
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
|
-
|
|
14108
|
+
const [settings, setSettings] = React24.useState(() => groupSettingsFrom(account));
|
|
14109
|
+
const [refreshing, setRefreshing] = React24.useState(false);
|
|
14110
|
+
const [refreshError, setRefreshError] = React24.useState(null);
|
|
14111
|
+
const [provision, setProvision] = React24.useState(null);
|
|
14112
|
+
const [provisionBusy, setProvisionBusy] = React24.useState(false);
|
|
14113
|
+
const [now, setNow] = React24.useState(() => Date.now());
|
|
14114
|
+
const mounted = React24.useRef(true);
|
|
14115
|
+
React24.useEffect(() => {
|
|
13030
14116
|
setSettings(groupSettingsFrom(account));
|
|
13031
14117
|
}, [
|
|
13032
14118
|
account.botId,
|
|
@@ -13034,22 +14120,22 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13034
14120
|
account.groupTopicReply,
|
|
13035
14121
|
account.groupMessagePermissionGranted
|
|
13036
14122
|
]);
|
|
13037
|
-
|
|
14123
|
+
React24.useEffect(() => {
|
|
13038
14124
|
mounted.current = true;
|
|
13039
14125
|
return () => {
|
|
13040
14126
|
mounted.current = false;
|
|
13041
14127
|
};
|
|
13042
14128
|
}, []);
|
|
13043
|
-
const invoke =
|
|
14129
|
+
const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
|
|
13044
14130
|
if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u7FA4\u804A\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
13045
14131
|
return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
|
|
13046
14132
|
}, [rpcCall]);
|
|
13047
|
-
const applySnapshot =
|
|
14133
|
+
const applySnapshot = React24.useCallback((value) => {
|
|
13048
14134
|
const result = targetBotFromSnapshot(value, account.botId);
|
|
13049
14135
|
if (mounted.current) setSettings(groupSettingsFrom(result.bot));
|
|
13050
14136
|
return result;
|
|
13051
14137
|
}, [account.botId]);
|
|
13052
|
-
const loadSettings =
|
|
14138
|
+
const loadSettings = React24.useCallback(async ({ signal, restoreProvisioning = false } = {}) => {
|
|
13053
14139
|
setRefreshing(true);
|
|
13054
14140
|
setRefreshError(null);
|
|
13055
14141
|
try {
|
|
@@ -13059,13 +14145,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13059
14145
|
if (restoreProvisioning) {
|
|
13060
14146
|
const active = result.snapshot.provisioning;
|
|
13061
14147
|
if (active?.operation === GROUP_MESSAGE_PERMISSION_OPERATION2 && active.botId === account.botId) {
|
|
13062
|
-
const
|
|
13063
|
-
setNow(
|
|
14148
|
+
const timestamp8 = Date.now();
|
|
14149
|
+
setNow(timestamp8);
|
|
13064
14150
|
setProvision({
|
|
13065
14151
|
phase: active.submitted ? "connecting" : "qr",
|
|
13066
14152
|
...active,
|
|
13067
|
-
durationMs: Math.max(1, active.expiresAt -
|
|
13068
|
-
expired: !active.submitted && active.expiresAt <=
|
|
14153
|
+
durationMs: Math.max(1, active.expiresAt - timestamp8),
|
|
14154
|
+
expired: !active.submitted && active.expiresAt <= timestamp8
|
|
13069
14155
|
});
|
|
13070
14156
|
}
|
|
13071
14157
|
}
|
|
@@ -13078,16 +14164,16 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13078
14164
|
if (!signal?.aborted && mounted.current) setRefreshing(false);
|
|
13079
14165
|
}
|
|
13080
14166
|
}, [account.botId, applySnapshot, invoke]);
|
|
13081
|
-
|
|
14167
|
+
React24.useEffect(() => {
|
|
13082
14168
|
const controller = new AbortController();
|
|
13083
14169
|
void loadSettings({ signal: controller.signal, restoreProvisioning: true });
|
|
13084
14170
|
return () => controller.abort();
|
|
13085
14171
|
}, [loadSettings]);
|
|
13086
|
-
const saveSetting =
|
|
14172
|
+
const saveSetting = React24.useCallback(async (endpoint, payload) => {
|
|
13087
14173
|
const value = await invoke(endpoint, { botId: account.botId, ...payload });
|
|
13088
14174
|
applySnapshot(value);
|
|
13089
14175
|
}, [account.botId, applySnapshot, invoke]);
|
|
13090
|
-
const startAuthorization =
|
|
14176
|
+
const startAuthorization = React24.useCallback(async ({ replace = false } = {}) => {
|
|
13091
14177
|
if (provisionBusy) return;
|
|
13092
14178
|
const previousAttemptId = provision?.attemptId;
|
|
13093
14179
|
setProvisionBusy(true);
|
|
@@ -13106,13 +14192,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13106
14192
|
if (normalized.operation !== GROUP_MESSAGE_PERMISSION_OPERATION2 || normalized.botId !== account.botId) {
|
|
13107
14193
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801");
|
|
13108
14194
|
}
|
|
13109
|
-
const
|
|
14195
|
+
const timestamp8 = Date.now();
|
|
13110
14196
|
if (!mounted.current) return;
|
|
13111
|
-
setNow(
|
|
14197
|
+
setNow(timestamp8);
|
|
13112
14198
|
setProvision({
|
|
13113
14199
|
phase: normalized.submitted ? "connecting" : "qr",
|
|
13114
14200
|
...normalized,
|
|
13115
|
-
durationMs: Math.max(1, normalized.expiresAt -
|
|
14201
|
+
durationMs: Math.max(1, normalized.expiresAt - timestamp8),
|
|
13116
14202
|
expired: false
|
|
13117
14203
|
});
|
|
13118
14204
|
} catch (cause) {
|
|
@@ -13128,13 +14214,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13128
14214
|
if (mounted.current) setProvisionBusy(false);
|
|
13129
14215
|
}
|
|
13130
14216
|
}, [account.botId, invoke, provision?.attemptId, provisionBusy]);
|
|
13131
|
-
const finishAuthorization =
|
|
14217
|
+
const finishAuthorization = React24.useCallback(async (signal) => {
|
|
13132
14218
|
const bot = await loadSettings({ signal, restoreProvisioning: false });
|
|
13133
14219
|
if (signal?.aborted || !mounted.current) return;
|
|
13134
14220
|
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
14221
|
setProvision(null);
|
|
13136
14222
|
}, [loadSettings]);
|
|
13137
|
-
|
|
14223
|
+
React24.useEffect(() => {
|
|
13138
14224
|
if (!provision?.attemptId || !["qr", "connecting"].includes(provision.phase) || provision.expired) return void 0;
|
|
13139
14225
|
const timerHost = globalThis.window ?? globalThis;
|
|
13140
14226
|
const controller = new AbortController();
|
|
@@ -13178,13 +14264,13 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13178
14264
|
timerHost.clearTimeout(timer);
|
|
13179
14265
|
};
|
|
13180
14266
|
}, [account.botId, finishAuthorization, invoke, provision]);
|
|
13181
|
-
|
|
14267
|
+
React24.useEffect(() => {
|
|
13182
14268
|
if (!provision?.attemptId || provision.phase !== "qr" || provision.expired) return void 0;
|
|
13183
14269
|
const timerHost = globalThis.window ?? globalThis;
|
|
13184
14270
|
const tick = () => {
|
|
13185
|
-
const
|
|
13186
|
-
setNow(
|
|
13187
|
-
if (
|
|
14271
|
+
const timestamp8 = Date.now();
|
|
14272
|
+
setNow(timestamp8);
|
|
14273
|
+
if (timestamp8 >= provision.expiresAt) {
|
|
13188
14274
|
setProvision((current) => current?.attemptId === provision.attemptId ? { ...current, expired: true } : current);
|
|
13189
14275
|
}
|
|
13190
14276
|
};
|
|
@@ -13192,7 +14278,7 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
13192
14278
|
const timer = timerHost.setInterval(tick, 1e3);
|
|
13193
14279
|
return () => timerHost.clearInterval(timer);
|
|
13194
14280
|
}, [provision?.attemptId, provision?.expired, provision?.expiresAt, provision?.phase]);
|
|
13195
|
-
const cancelAuthorization =
|
|
14281
|
+
const cancelAuthorization = React24.useCallback(async () => {
|
|
13196
14282
|
if (!provision?.attemptId || provisionBusy) {
|
|
13197
14283
|
setProvision(null);
|
|
13198
14284
|
return;
|
|
@@ -13336,6 +14422,13 @@ var CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
13336
14422
|
group: [{ key: "chatId", label: "\u7FA4 Chat ID", placeholder: "\u586B\u5199\u7FA4 chatid" }]
|
|
13337
14423
|
}
|
|
13338
14424
|
},
|
|
14425
|
+
wecomApp: {
|
|
14426
|
+
label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528",
|
|
14427
|
+
kinds: [{ value: "user", label: "\u79C1\u804A" }],
|
|
14428
|
+
fields: {
|
|
14429
|
+
user: [{ key: "chatId", label: "\u7528\u6237 ID", placeholder: "\u586B\u5199\u4F01\u4E1A\u5FAE\u4FE1\u7528\u6237 ID" }]
|
|
14430
|
+
}
|
|
14431
|
+
},
|
|
13339
14432
|
qq: {
|
|
13340
14433
|
label: "QQ",
|
|
13341
14434
|
kinds: [{ value: "user", label: "\u5355\u804A" }, { value: "group", label: "\u7FA4\u804A" }],
|
|
@@ -13380,10 +14473,10 @@ var CHANNEL_DEFINITIONS = Object.freeze({
|
|
|
13380
14473
|
}
|
|
13381
14474
|
}
|
|
13382
14475
|
});
|
|
13383
|
-
function
|
|
14476
|
+
function presentError11(error, fallback) {
|
|
13384
14477
|
return error?.message || fallback;
|
|
13385
14478
|
}
|
|
13386
|
-
function
|
|
14479
|
+
function unwrapRpcResult12(result) {
|
|
13387
14480
|
if (result?.ok === true) return result.value;
|
|
13388
14481
|
if (result?.ok === false) {
|
|
13389
14482
|
const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -13435,18 +14528,18 @@ function validSuggestions(definition, value) {
|
|
|
13435
14528
|
});
|
|
13436
14529
|
}
|
|
13437
14530
|
function maskRouteValue(value) {
|
|
13438
|
-
const
|
|
13439
|
-
if (!
|
|
13440
|
-
const at =
|
|
14531
|
+
const text7 = String(value ?? "").trim();
|
|
14532
|
+
if (!text7) return "";
|
|
14533
|
+
const at = text7.indexOf("@");
|
|
13441
14534
|
if (at > 0) {
|
|
13442
|
-
const local =
|
|
13443
|
-
const domain =
|
|
14535
|
+
const local = text7.slice(0, at);
|
|
14536
|
+
const domain = text7.slice(at);
|
|
13444
14537
|
const visible = local.length <= 4 ? `${local.slice(0, 1)}\u2022\u2022${local.slice(-1)}` : `${local.slice(0, 3)}\u2026${local.slice(-2)}`;
|
|
13445
14538
|
return `${visible}${domain}`;
|
|
13446
14539
|
}
|
|
13447
|
-
if (
|
|
13448
|
-
if (
|
|
13449
|
-
return `${
|
|
14540
|
+
if (text7.length <= 6) return `${text7.slice(0, 2)}\u2026${text7.slice(-1)}`;
|
|
14541
|
+
if (text7.length <= 12) return `${text7.slice(0, 3)}\u2026${text7.slice(-3)}`;
|
|
14542
|
+
return `${text7.slice(0, 5)}\u2026${text7.slice(-4)}`;
|
|
13450
14543
|
}
|
|
13451
14544
|
function suggestionFallbackName(definition, suggestion) {
|
|
13452
14545
|
const displayName = suggestionDisplayName(suggestion);
|
|
@@ -13501,13 +14594,13 @@ function TargetForm({
|
|
|
13501
14594
|
}) {
|
|
13502
14595
|
const editing = mode === "edit";
|
|
13503
14596
|
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] =
|
|
14597
|
+
const [targetId, setTargetId] = React25.useState(initialValue?.targetId ?? "");
|
|
14598
|
+
const [name2, setName] = React25.useState(initialValue?.name ?? "");
|
|
14599
|
+
const [kind, setKind] = React25.useState(initialKind);
|
|
14600
|
+
const [route, setRoute] = React25.useState(initialValue?.route ?? {});
|
|
14601
|
+
const [error, setError] = React25.useState(null);
|
|
14602
|
+
const [testing, setTesting] = React25.useState(false);
|
|
14603
|
+
const [testState, setTestState] = React25.useState(null);
|
|
13511
14604
|
const currentTarget = () => {
|
|
13512
14605
|
const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
|
|
13513
14606
|
const raw = String(route[field.key] ?? "").trim();
|
|
@@ -13528,7 +14621,7 @@ function TargetForm({
|
|
|
13528
14621
|
...currentTarget()
|
|
13529
14622
|
});
|
|
13530
14623
|
} catch (caught) {
|
|
13531
|
-
setError(
|
|
14624
|
+
setError(presentError11(caught, "\u76EE\u6807\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002"));
|
|
13532
14625
|
}
|
|
13533
14626
|
};
|
|
13534
14627
|
const testTarget = async () => {
|
|
@@ -13540,7 +14633,7 @@ function TargetForm({
|
|
|
13540
14633
|
await onTest({ kind: target.kind, route: target.route });
|
|
13541
14634
|
setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
|
|
13542
14635
|
} catch (caught) {
|
|
13543
|
-
setTestState({ tone: "error", message:
|
|
14636
|
+
setTestState({ tone: "error", message: presentError11(caught, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13544
14637
|
} finally {
|
|
13545
14638
|
setTesting(false);
|
|
13546
14639
|
}
|
|
@@ -13724,7 +14817,7 @@ function TargetSuggestionPicker({
|
|
|
13724
14817
|
suggestions.map((suggestion, index) => {
|
|
13725
14818
|
const identity = routeIdentity(definition, suggestion);
|
|
13726
14819
|
const added = configured.has(identity);
|
|
13727
|
-
return
|
|
14820
|
+
return React25.createElement("option", {
|
|
13728
14821
|
key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
|
|
13729
14822
|
value: String(index),
|
|
13730
14823
|
disabled: added
|
|
@@ -13741,11 +14834,11 @@ function TargetSuggestionPicker({
|
|
|
13741
14834
|
);
|
|
13742
14835
|
}
|
|
13743
14836
|
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] =
|
|
14837
|
+
const [action, setAction] = React25.useState(null);
|
|
14838
|
+
const [testState, setTestState] = React25.useState(null);
|
|
14839
|
+
const [syncFeedback, setSyncFeedback] = React25.useState(null);
|
|
14840
|
+
const [copyState, setCopyState] = React25.useState(null);
|
|
14841
|
+
const [confirmDelete, setConfirmDelete] = React25.useState(false);
|
|
13749
14842
|
const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
|
|
13750
14843
|
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
14844
|
const testTarget = async () => {
|
|
@@ -13755,7 +14848,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13755
14848
|
await rpcCall(DELIVERY_ENDPOINTS.test, { botId, targetId: target.targetId });
|
|
13756
14849
|
setTestState({ tone: "success", message: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u8BF7\u5230\u76EE\u6807\u4F1A\u8BDD\u786E\u8BA4\u3002" });
|
|
13757
14850
|
} catch (error) {
|
|
13758
|
-
setTestState({ tone: "error", message:
|
|
14851
|
+
setTestState({ tone: "error", message: presentError11(error, "\u6D4B\u8BD5\u53D1\u9001\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13759
14852
|
} finally {
|
|
13760
14853
|
setAction(null);
|
|
13761
14854
|
}
|
|
@@ -13766,7 +14859,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13766
14859
|
await copyText(JSON.stringify({ botId, targetId: target.targetId }));
|
|
13767
14860
|
setCopyState("\u5DF2\u590D\u5236\u8C03\u7528\u53C2\u6570");
|
|
13768
14861
|
} catch (error) {
|
|
13769
|
-
setCopyState(
|
|
14862
|
+
setCopyState(presentError11(error, "\u590D\u5236\u5931\u8D25\u3002"));
|
|
13770
14863
|
}
|
|
13771
14864
|
};
|
|
13772
14865
|
const deleteTarget = async () => {
|
|
@@ -13775,7 +14868,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13775
14868
|
await rpcCall(DELIVERY_ENDPOINTS.delete, { botId, targetId: target.targetId });
|
|
13776
14869
|
await onChanged();
|
|
13777
14870
|
} catch (error) {
|
|
13778
|
-
setTestState({ tone: "error", message:
|
|
14871
|
+
setTestState({ tone: "error", message: presentError11(error, "\u5220\u9664\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002") });
|
|
13779
14872
|
setAction(null);
|
|
13780
14873
|
setConfirmDelete(false);
|
|
13781
14874
|
}
|
|
@@ -13793,7 +14886,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13793
14886
|
} catch (error) {
|
|
13794
14887
|
setSyncFeedback({
|
|
13795
14888
|
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" :
|
|
14889
|
+
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
14890
|
});
|
|
13798
14891
|
} finally {
|
|
13799
14892
|
setAction(null);
|
|
@@ -13808,7 +14901,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
13808
14901
|
h2(
|
|
13809
14902
|
"div",
|
|
13810
14903
|
{ className: "dim-targetTitle" },
|
|
13811
|
-
|
|
14904
|
+
React25.createElement("strong", null, target.name || target.targetId),
|
|
13812
14905
|
h2("span", null, kindLabel(definition, target.kind))
|
|
13813
14906
|
),
|
|
13814
14907
|
h2("code", null, `targetId: ${target.targetId}`)
|
|
@@ -13894,26 +14987,26 @@ function DeliveryTargetSettingsPage({
|
|
|
13894
14987
|
onBack
|
|
13895
14988
|
}) {
|
|
13896
14989
|
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
|
-
|
|
14990
|
+
const [activeTabId, setActiveTabId] = React25.useState(BOT_SETTINGS_TABS[0].id);
|
|
14991
|
+
const [phase, setPhase] = React25.useState("loading");
|
|
14992
|
+
const [targets, setTargets] = React25.useState([]);
|
|
14993
|
+
const [suggestionPhase, setSuggestionPhase] = React25.useState("idle");
|
|
14994
|
+
const [suggestions, setSuggestions] = React25.useState([]);
|
|
14995
|
+
const [suggestionError, setSuggestionError] = React25.useState(null);
|
|
14996
|
+
const [error, setError] = React25.useState(null);
|
|
14997
|
+
const [editor, setEditor] = React25.useState(null);
|
|
14998
|
+
const [saving, setSaving] = React25.useState(false);
|
|
14999
|
+
const [botCopyState, setBotCopyState] = React25.useState(null);
|
|
15000
|
+
const [accessPolicy, setAccessPolicy] = React25.useState(account.accessPolicy);
|
|
15001
|
+
const mounted = React25.useRef(true);
|
|
15002
|
+
React25.useEffect(() => {
|
|
13910
15003
|
setAccessPolicy(account.accessPolicy);
|
|
13911
15004
|
}, [account.botId, account.accessPolicy]);
|
|
13912
|
-
const invoke =
|
|
15005
|
+
const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
|
|
13913
15006
|
if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
13914
|
-
return
|
|
15007
|
+
return unwrapRpcResult12(await rpcCall(endpoint, payload, signal));
|
|
13915
15008
|
}, [rpcCall]);
|
|
13916
|
-
const loadTargets =
|
|
15009
|
+
const loadTargets = React25.useCallback(async ({ signal, silent = false } = {}) => {
|
|
13917
15010
|
if (!silent) setPhase("loading");
|
|
13918
15011
|
setError(null);
|
|
13919
15012
|
try {
|
|
@@ -13923,11 +15016,11 @@ function DeliveryTargetSettingsPage({
|
|
|
13923
15016
|
setPhase("ready");
|
|
13924
15017
|
} catch (caught) {
|
|
13925
15018
|
if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
|
|
13926
|
-
setError(
|
|
15019
|
+
setError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u6295\u9012\u76EE\u6807\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
13927
15020
|
setPhase("error");
|
|
13928
15021
|
}
|
|
13929
15022
|
}, [account.botId, invoke]);
|
|
13930
|
-
const loadSuggestions =
|
|
15023
|
+
const loadSuggestions = React25.useCallback(async () => {
|
|
13931
15024
|
setSuggestionPhase("loading");
|
|
13932
15025
|
setSuggestionError(null);
|
|
13933
15026
|
try {
|
|
@@ -13937,11 +15030,11 @@ function DeliveryTargetSettingsPage({
|
|
|
13937
15030
|
setSuggestionPhase("ready");
|
|
13938
15031
|
} catch (caught) {
|
|
13939
15032
|
if (caught?.name === "AbortError" || !mounted.current) return;
|
|
13940
|
-
setSuggestionError(
|
|
15033
|
+
setSuggestionError(presentError11(caught, "\u65E0\u6CD5\u8BFB\u53D6\u5DF2\u804A\u4F1A\u8BDD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
13941
15034
|
setSuggestionPhase("error");
|
|
13942
15035
|
}
|
|
13943
15036
|
}, [account.botId, definition, invoke]);
|
|
13944
|
-
|
|
15037
|
+
React25.useEffect(() => {
|
|
13945
15038
|
mounted.current = true;
|
|
13946
15039
|
const controller = new AbortController();
|
|
13947
15040
|
void loadTargets({ signal: controller.signal });
|
|
@@ -14009,7 +15102,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14009
15102
|
await copyText(account.botId);
|
|
14010
15103
|
setBotCopyState("\u5DF2\u590D\u5236 Bot ID");
|
|
14011
15104
|
} catch (caught) {
|
|
14012
|
-
setBotCopyState(
|
|
15105
|
+
setBotCopyState(presentError11(caught, "\u590D\u5236\u5931\u8D25\u3002"));
|
|
14013
15106
|
}
|
|
14014
15107
|
};
|
|
14015
15108
|
const settingsTabs = botSettingsTabsForChannel(channel4);
|
|
@@ -14063,7 +15156,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14063
15156
|
account,
|
|
14064
15157
|
rpcCall: accessRpcCall
|
|
14065
15158
|
}) : h2(
|
|
14066
|
-
|
|
15159
|
+
React25.Fragment,
|
|
14067
15160
|
null,
|
|
14068
15161
|
h2(
|
|
14069
15162
|
"section",
|
|
@@ -14174,7 +15267,7 @@ function DeliveryTargetSettingsPage({
|
|
|
14174
15267
|
}
|
|
14175
15268
|
|
|
14176
15269
|
// plugin-src/client/global-settings.js
|
|
14177
|
-
var
|
|
15270
|
+
var React26 = __toESM(require("react"), 1);
|
|
14178
15271
|
|
|
14179
15272
|
// src/channels/shared/inbound-ttl.mjs
|
|
14180
15273
|
var DEFAULT_INBOUND_TTL_HOURS = 168;
|
|
@@ -14203,10 +15296,10 @@ var GLOBAL_SETTINGS_ENDPOINTS = Object.freeze({
|
|
|
14203
15296
|
setTtl: "settings.inbound-ttl.set",
|
|
14204
15297
|
sweep: "settings.inbound-ttl.sweep"
|
|
14205
15298
|
});
|
|
14206
|
-
function
|
|
15299
|
+
function presentError12(error, fallback) {
|
|
14207
15300
|
return error?.message || fallback;
|
|
14208
15301
|
}
|
|
14209
|
-
function
|
|
15302
|
+
function unwrapRpcResult13(result) {
|
|
14210
15303
|
if (result?.ok === true) return result.value;
|
|
14211
15304
|
if (result?.ok === false) {
|
|
14212
15305
|
const error = new Error(result.error?.message || "\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002");
|
|
@@ -14236,29 +15329,29 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
|
|
|
14236
15329
|
}, children);
|
|
14237
15330
|
}
|
|
14238
15331
|
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 =
|
|
15332
|
+
const [phase, setPhase] = React26.useState("loading");
|
|
15333
|
+
const [loadError, setLoadError] = React26.useState(null);
|
|
15334
|
+
const [ttlInput, setTtlInput] = React26.useState("");
|
|
15335
|
+
const [savedTtl, setSavedTtl] = React26.useState(null);
|
|
15336
|
+
const [ttlError, setTtlError] = React26.useState(false);
|
|
15337
|
+
const [saveError, setSaveError] = React26.useState(null);
|
|
15338
|
+
const [saveSucceeded, setSaveSucceeded] = React26.useState(false);
|
|
15339
|
+
const [isSaving, setIsSaving] = React26.useState(false);
|
|
15340
|
+
const [sweepConfirming, setSweepConfirming] = React26.useState(false);
|
|
15341
|
+
const [sweeping, setSweeping] = React26.useState(false);
|
|
15342
|
+
const ttlErrorId = React26.useId();
|
|
15343
|
+
const ttlHintsId = React26.useId();
|
|
15344
|
+
const sweepTriggerId = React26.useId();
|
|
15345
|
+
const sweepConfirmId = React26.useId();
|
|
15346
|
+
const sweepConfirmTextId = React26.useId();
|
|
15347
|
+
const sweepConfirmButtonId = React26.useId();
|
|
15348
|
+
const mounted = React26.useRef(true);
|
|
15349
|
+
const saving = React26.useRef(false);
|
|
15350
|
+
const invoke = React26.useCallback(async (endpoint, payload = {}, signal) => {
|
|
14258
15351
|
if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
14259
|
-
return
|
|
15352
|
+
return unwrapRpcResult13(await rpcCall(endpoint, payload, signal));
|
|
14260
15353
|
}, [rpcCall]);
|
|
14261
|
-
const loadSettings =
|
|
15354
|
+
const loadSettings = React26.useCallback(async ({ signal } = {}) => {
|
|
14262
15355
|
setPhase("loading");
|
|
14263
15356
|
setLoadError(null);
|
|
14264
15357
|
try {
|
|
@@ -14278,11 +15371,11 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14278
15371
|
setPhase("ready");
|
|
14279
15372
|
} catch (caught) {
|
|
14280
15373
|
if (signal?.aborted || caught?.name === "AbortError" || !mounted.current) return;
|
|
14281
|
-
setLoadError(
|
|
15374
|
+
setLoadError(presentError12(caught, "\u65E0\u6CD5\u8BFB\u53D6\u901A\u7528\u8BBE\u7F6E\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
14282
15375
|
setPhase("error");
|
|
14283
15376
|
}
|
|
14284
15377
|
}, [invoke]);
|
|
14285
|
-
|
|
15378
|
+
React26.useEffect(() => {
|
|
14286
15379
|
mounted.current = true;
|
|
14287
15380
|
const controller = new AbortController();
|
|
14288
15381
|
void loadSettings({ signal: controller.signal });
|
|
@@ -14291,7 +15384,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14291
15384
|
controller.abort();
|
|
14292
15385
|
};
|
|
14293
15386
|
}, [loadSettings]);
|
|
14294
|
-
|
|
15387
|
+
React26.useEffect(() => {
|
|
14295
15388
|
if (!sweepConfirming) return;
|
|
14296
15389
|
globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
|
|
14297
15390
|
}, [sweepConfirmButtonId, sweepConfirming]);
|
|
@@ -14322,7 +15415,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
14322
15415
|
setPhase("ready");
|
|
14323
15416
|
} catch (caught) {
|
|
14324
15417
|
if (mounted.current) {
|
|
14325
|
-
setSaveError(
|
|
15418
|
+
setSaveError(presentError12(caught, "\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
|
|
14326
15419
|
}
|
|
14327
15420
|
} finally {
|
|
14328
15421
|
saving.current = false;
|
|
@@ -14598,7 +15691,7 @@ function replacePageLocation(url, location = globalThis.location) {
|
|
|
14598
15691
|
|
|
14599
15692
|
// plugin-src/client/styles.js
|
|
14600
15693
|
var IM_STYLE_ID = "xmanrui-dsh-im-settings";
|
|
14601
|
-
var
|
|
15694
|
+
var CSS12 = String.raw`
|
|
14602
15695
|
.dim-page {
|
|
14603
15696
|
--dim-blue: var(--dsw-alias-state-business-primary, #3370ff);
|
|
14604
15697
|
--dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
|
|
@@ -14669,9 +15762,7 @@ var CSS11 = String.raw`
|
|
|
14669
15762
|
.dim-generalSettingsAction:hover .dim-generalSettingsTooltip, .dim-generalSettingsButton:focus-visible + .dim-generalSettingsTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
|
14670
15763
|
.dim-generalSettingsButton[aria-current="page"] + .dim-generalSettingsTooltip { opacity: 0; visibility: hidden; transform: translateY(-3px); }
|
|
14671
15764
|
.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); }
|
|
15765
|
+
.dim-rail { display: grid; align-content: start; gap: 8px; padding: 0 4px 1px 1px; }
|
|
14675
15766
|
.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
15767
|
.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
15768
|
.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 +15792,7 @@ var CSS11 = String.raw`
|
|
|
14701
15792
|
.dim-channelCopy { min-width: 0; display: grid; }
|
|
14702
15793
|
.dim-channelCopy strong { overflow: hidden; color: inherit; font-size: 14px; line-height: 20px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
|
|
14703
15794
|
.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;
|
|
15795
|
+
.dim-divider { width: 1px; align-self: stretch; background: var(--dsw-alias-border-l1, #eef0f3); }
|
|
14705
15796
|
.dim-panel { min-width: 0; container-type: inline-size; }
|
|
14706
15797
|
.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
15798
|
.dim-loopbackRecoveryCopy { min-width: 0; }
|
|
@@ -14817,6 +15908,24 @@ var CSS11 = String.raw`
|
|
|
14817
15908
|
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
14818
15909
|
.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
15910
|
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
15911
|
+
.dim-panel .dim-modelSetting { display: block; padding: 8px 4px 4px; }
|
|
15912
|
+
.dim-modelSetting > .dim-presetHeader { padding: 0 6px 6px; }
|
|
15913
|
+
.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; }
|
|
15914
|
+
.dim-modelRowLabel { flex: none; }
|
|
15915
|
+
.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; }
|
|
15916
|
+
.dim-modelChevron { flex: none; color: var(--dsw-alias-label-tertiary, #81858c); }
|
|
15917
|
+
.dim-modelRow:hover:not(:disabled), .dim-modelOption:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eceef1); }
|
|
15918
|
+
.dim-modelRow:focus-visible, .dim-modelOption:focus-visible { outline: 2px solid var(--dsw-alias-border-l3, #1677ff); outline-offset: -2px; }
|
|
15919
|
+
.dim-modelRow:disabled, .dim-modelOption:disabled { opacity: .55; cursor: default; }
|
|
15920
|
+
/* In-flow lists avoid clipping by collapsed-card and settings scroll containers. */
|
|
15921
|
+
.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; }
|
|
15922
|
+
.dim-modelGroupTitle { padding: 7px 8px 3px; color: var(--dsw-alias-label-tertiary, #81858c); font-size: 12px; line-height: 18px; font-weight: 500; }
|
|
15923
|
+
.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; }
|
|
15924
|
+
.dim-modelOptionCopy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
|
|
15925
|
+
.dim-modelOptionName { font-size: 14px; line-height: 20px; font-weight: 500; overflow-wrap: anywhere; }
|
|
15926
|
+
.dim-modelDescription { color: var(--dsw-alias-label-tertiary, #81858c); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
|
|
15927
|
+
.dim-modelCheck { flex: 0 0 18px; text-align: center; }
|
|
15928
|
+
.dim-modelHint { margin: 4px 10px 6px; color: var(--dsw-alias-label-tertiary, #81858c); font-size: 11px; line-height: 17px; }
|
|
14820
15929
|
.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
15930
|
.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
15931
|
.dim-contextEntry:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
|
|
@@ -15004,7 +16113,7 @@ var CSS11 = String.raw`
|
|
|
15004
16113
|
.dim-feishuGroupSettings { min-width: 0; display: grid; gap: 14px; }
|
|
15005
16114
|
.dim-feishuGroupControls { min-width: 0; display: grid; gap: 12px; }
|
|
15006
16115
|
.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; }
|
|
16116
|
+
.dim-feishuGroupControlHeader { position: relative; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
15008
16117
|
.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
16118
|
.dim-feishuGroupControlStatus { flex: none; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 17px; }
|
|
15010
16119
|
.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 +16315,8 @@ var CSS11 = String.raw`
|
|
|
15206
16315
|
@media (max-width: 840px) {
|
|
15207
16316
|
.dim-title { align-items: flex-start; }
|
|
15208
16317
|
.dim-layout { grid-template-columns: minmax(0, 1fr); gap: 18px; }
|
|
15209
|
-
.dim-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
16318
|
+
.dim-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); padding-right: 1px; }
|
|
15210
16319
|
.dim-divider { display: none; }
|
|
15211
|
-
.dim-rail { max-height: none; overflow: visible; padding-right: 1px; }
|
|
15212
16320
|
.dim-channel { min-height: 48px; }
|
|
15213
16321
|
}
|
|
15214
16322
|
@media (max-width: 560px) {
|
|
@@ -15256,7 +16364,7 @@ function installImStyles() {
|
|
|
15256
16364
|
const style = document.createElement("style");
|
|
15257
16365
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
15258
16366
|
style.dataset.pluginCss = IM_STYLE_ID;
|
|
15259
|
-
style.textContent =
|
|
16367
|
+
style.textContent = CSS12;
|
|
15260
16368
|
document.head.appendChild(style);
|
|
15261
16369
|
return () => style.remove();
|
|
15262
16370
|
}
|
|
@@ -15510,7 +16618,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
|
|
|
15510
16618
|
}
|
|
15511
16619
|
|
|
15512
16620
|
// plugin-src/client/update-panel.js
|
|
15513
|
-
var
|
|
16621
|
+
var React27 = __toESM(require("react"), 1);
|
|
15514
16622
|
var import_react_dom3 = require("react-dom");
|
|
15515
16623
|
var import_valid = __toESM(require_valid(), 1);
|
|
15516
16624
|
var import_rcompare = __toESM(require_rcompare(), 1);
|
|
@@ -15557,7 +16665,7 @@ function unwrapSnapshot(result) {
|
|
|
15557
16665
|
}
|
|
15558
16666
|
return value;
|
|
15559
16667
|
}
|
|
15560
|
-
function
|
|
16668
|
+
function presentError13(error) {
|
|
15561
16669
|
const code = error?.rpcError?.code ?? error?.code ?? "";
|
|
15562
16670
|
const message = error?.rpcError?.message ?? error?.message ?? "";
|
|
15563
16671
|
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)) {
|
|
@@ -15600,11 +16708,11 @@ function manualUpdateCommand(snapshot) {
|
|
|
15600
16708
|
return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
|
|
15601
16709
|
}
|
|
15602
16710
|
function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
15603
|
-
const [copyState, setCopyState] =
|
|
15604
|
-
const commandRef =
|
|
15605
|
-
const mounted =
|
|
15606
|
-
const copying =
|
|
15607
|
-
|
|
16711
|
+
const [copyState, setCopyState] = React27.useState("idle");
|
|
16712
|
+
const commandRef = React27.useRef(null);
|
|
16713
|
+
const mounted = React27.useRef(false);
|
|
16714
|
+
const copying = React27.useRef(false);
|
|
16715
|
+
React27.useEffect(() => {
|
|
15608
16716
|
mounted.current = true;
|
|
15609
16717
|
return () => {
|
|
15610
16718
|
mounted.current = false;
|
|
@@ -15636,7 +16744,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15636
16744
|
{ className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
|
|
15637
16745
|
h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
|
|
15638
16746
|
command ? h2(
|
|
15639
|
-
|
|
16747
|
+
React27.Fragment,
|
|
15640
16748
|
null,
|
|
15641
16749
|
h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
|
|
15642
16750
|
h2(
|
|
@@ -15672,7 +16780,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15672
16780
|
"aria-hidden": "true",
|
|
15673
16781
|
focusable: "false"
|
|
15674
16782
|
}, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
|
|
15675
|
-
|
|
16783
|
+
React27.Fragment,
|
|
15676
16784
|
null,
|
|
15677
16785
|
h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
|
|
15678
16786
|
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" })
|
|
@@ -15697,10 +16805,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
15697
16805
|
);
|
|
15698
16806
|
}
|
|
15699
16807
|
function UpdateDialog({ children, onClose }) {
|
|
15700
|
-
const dialogRef =
|
|
15701
|
-
const titleId =
|
|
15702
|
-
const descriptionId =
|
|
15703
|
-
|
|
16808
|
+
const dialogRef = React27.useRef(null);
|
|
16809
|
+
const titleId = React27.useId();
|
|
16810
|
+
const descriptionId = React27.useId();
|
|
16811
|
+
React27.useEffect(() => {
|
|
15704
16812
|
const previous = globalThis.document?.activeElement;
|
|
15705
16813
|
dialogRef.current?.focus?.();
|
|
15706
16814
|
return () => {
|
|
@@ -15758,19 +16866,19 @@ function UpdateDialog({ children, onClose }) {
|
|
|
15758
16866
|
return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
|
|
15759
16867
|
}
|
|
15760
16868
|
function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
15761
|
-
const [snapshot, setSnapshot] =
|
|
15762
|
-
const [action, setAction] =
|
|
15763
|
-
const [error, setError] =
|
|
15764
|
-
const [open, setOpen] =
|
|
15765
|
-
const [uncertainInstall, setUncertainInstall] =
|
|
15766
|
-
const mounted =
|
|
15767
|
-
const busy =
|
|
15768
|
-
const readController =
|
|
15769
|
-
const pollReadController =
|
|
15770
|
-
const installRequest =
|
|
15771
|
-
const onStatusRef =
|
|
16869
|
+
const [snapshot, setSnapshot] = React27.useState(null);
|
|
16870
|
+
const [action, setAction] = React27.useState("status");
|
|
16871
|
+
const [error, setError] = React27.useState(null);
|
|
16872
|
+
const [open, setOpen] = React27.useState(false);
|
|
16873
|
+
const [uncertainInstall, setUncertainInstall] = React27.useState(false);
|
|
16874
|
+
const mounted = React27.useRef(false);
|
|
16875
|
+
const busy = React27.useRef(false);
|
|
16876
|
+
const readController = React27.useRef(null);
|
|
16877
|
+
const pollReadController = React27.useRef(null);
|
|
16878
|
+
const installRequest = React27.useRef(null);
|
|
16879
|
+
const onStatusRef = React27.useRef(onStatus);
|
|
15772
16880
|
onStatusRef.current = onStatus;
|
|
15773
|
-
const accept =
|
|
16881
|
+
const accept = React27.useCallback((next) => {
|
|
15774
16882
|
setSnapshot(next);
|
|
15775
16883
|
onStatusRef.current?.(next);
|
|
15776
16884
|
}, []);
|
|
@@ -15779,7 +16887,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15779
16887
|
setUncertainInstall(false);
|
|
15780
16888
|
accept(next);
|
|
15781
16889
|
};
|
|
15782
|
-
const invoke =
|
|
16890
|
+
const invoke = React27.useCallback(async (endpoint, payload = {}, signal) => {
|
|
15783
16891
|
if (typeof rpcCall !== "function") {
|
|
15784
16892
|
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");
|
|
15785
16893
|
unavailable.code = "update-unavailable";
|
|
@@ -15787,14 +16895,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15787
16895
|
}
|
|
15788
16896
|
return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
|
|
15789
16897
|
}, [rpcCall]);
|
|
15790
|
-
|
|
16898
|
+
React27.useEffect(() => {
|
|
15791
16899
|
mounted.current = true;
|
|
15792
16900
|
busy.current = true;
|
|
15793
16901
|
const controller = new AbortController();
|
|
15794
16902
|
void invoke("update.status", {}, controller.signal).then((next) => {
|
|
15795
16903
|
if (!controller.signal.aborted) accept(next);
|
|
15796
16904
|
}).catch((cause) => {
|
|
15797
|
-
if (!controller.signal.aborted) setError(
|
|
16905
|
+
if (!controller.signal.aborted) setError(presentError13(cause));
|
|
15798
16906
|
}).finally(() => {
|
|
15799
16907
|
if (!controller.signal.aborted) {
|
|
15800
16908
|
busy.current = false;
|
|
@@ -15810,7 +16918,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15810
16918
|
const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
|
|
15811
16919
|
const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
|
|
15812
16920
|
const shouldPoll = activeJob || uncertainInstall;
|
|
15813
|
-
|
|
16921
|
+
React27.useEffect(() => {
|
|
15814
16922
|
if (!shouldPoll) return void 0;
|
|
15815
16923
|
let controller;
|
|
15816
16924
|
const scheduler = createPollScheduler({
|
|
@@ -15831,7 +16939,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15831
16939
|
keepPolling = ACTIVE_STATES4.has(next.job?.state);
|
|
15832
16940
|
}
|
|
15833
16941
|
} catch (cause) {
|
|
15834
|
-
if (!pendingController.signal.aborted) setError(
|
|
16942
|
+
if (!pendingController.signal.aborted) setError(presentError13(cause));
|
|
15835
16943
|
} finally {
|
|
15836
16944
|
if (pollReadController.current === pendingController) pollReadController.current = null;
|
|
15837
16945
|
}
|
|
@@ -15862,7 +16970,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15862
16970
|
else acceptAuthoritative(next);
|
|
15863
16971
|
}
|
|
15864
16972
|
} catch (cause) {
|
|
15865
|
-
if (!controller.signal.aborted && mounted.current) setError(
|
|
16973
|
+
if (!controller.signal.aborted && mounted.current) setError(presentError13(cause));
|
|
15866
16974
|
} finally {
|
|
15867
16975
|
if (!controller.signal.aborted && mounted.current) {
|
|
15868
16976
|
busy.current = false;
|
|
@@ -15888,7 +16996,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15888
16996
|
if (mounted.current) acceptAuthoritative(next);
|
|
15889
16997
|
} catch (cause) {
|
|
15890
16998
|
if (mounted.current) {
|
|
15891
|
-
setError(
|
|
16999
|
+
setError(presentError13(cause));
|
|
15892
17000
|
setUncertainInstall(true);
|
|
15893
17001
|
}
|
|
15894
17002
|
} finally {
|
|
@@ -15908,7 +17016,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15908
17016
|
const manualCommand = manualUpdateCommand(snapshot);
|
|
15909
17017
|
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";
|
|
15910
17018
|
return h2(
|
|
15911
|
-
|
|
17019
|
+
React27.Fragment,
|
|
15912
17020
|
null,
|
|
15913
17021
|
h2("button", {
|
|
15914
17022
|
type: "button",
|
|
@@ -15933,13 +17041,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
15933
17041
|
h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
|
|
15934
17042
|
h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
|
|
15935
17043
|
snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
|
|
15936
|
-
|
|
17044
|
+
React27.Fragment,
|
|
15937
17045
|
null,
|
|
15938
17046
|
h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
|
|
15939
17047
|
h2("dd", null, `v${snapshot.installedVersion}`)
|
|
15940
17048
|
) : null,
|
|
15941
17049
|
targetVersion ? h2(
|
|
15942
|
-
|
|
17050
|
+
React27.Fragment,
|
|
15943
17051
|
null,
|
|
15944
17052
|
h2("dt", null, "\u76EE\u6807\u7248\u672C"),
|
|
15945
17053
|
h2("dd", null, `v${targetVersion}`)
|
|
@@ -16029,6 +17137,7 @@ var CHANNELS = Object.freeze([
|
|
|
16029
17137
|
{ id: "telegram", label: "Telegram" },
|
|
16030
17138
|
{ id: "discord", label: "Discord" },
|
|
16031
17139
|
{ id: "whatsapp", label: "WhatsApp" },
|
|
17140
|
+
{ id: "wecomApp", label: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" },
|
|
16032
17141
|
{ id: "office", label: "AI Office", note: "\uFF08\u5B9E\u9A8C\u529F\u80FD\uFF09" }
|
|
16033
17142
|
]);
|
|
16034
17143
|
function WeixinLogo() {
|
|
@@ -16058,6 +17167,9 @@ function QqLogo() {
|
|
|
16058
17167
|
function WecomLogo() {
|
|
16059
17168
|
return h2("span", { className: "dim-logo dim-logoWecom", "aria-hidden": "true" }, h2(WecomLogoGlyph));
|
|
16060
17169
|
}
|
|
17170
|
+
function WecomAppLogo() {
|
|
17171
|
+
return h2("span", { className: "dim-logo dim-logoWecomApp", "aria-hidden": "true" }, h2(WecomLogoGlyph));
|
|
17172
|
+
}
|
|
16061
17173
|
function TelegramLogo() {
|
|
16062
17174
|
return h2(
|
|
16063
17175
|
"span",
|
|
@@ -16098,6 +17210,7 @@ function ChannelLogo({ channel: channel4 }) {
|
|
|
16098
17210
|
if (channel4 === "feishu") return h2(FeishuLogo);
|
|
16099
17211
|
if (channel4 === "dingtalk") return h2(DingtalkLogo);
|
|
16100
17212
|
if (channel4 === "wecom") return h2(WecomLogo);
|
|
17213
|
+
if (channel4 === "wecomApp") return h2(WecomAppLogo);
|
|
16101
17214
|
if (channel4 === "qq") return h2(QqLogo);
|
|
16102
17215
|
if (channel4 === "slack") return h2(SlackLogo);
|
|
16103
17216
|
if (channel4 === "telegram") return h2(TelegramLogo);
|
|
@@ -16134,6 +17247,7 @@ function IMSettingsTab({
|
|
|
16134
17247
|
slackRpcCall,
|
|
16135
17248
|
telegramRpcCall,
|
|
16136
17249
|
wecomRpcCall,
|
|
17250
|
+
wecomAppRpcCall,
|
|
16137
17251
|
weixinRpcCall,
|
|
16138
17252
|
whatsappRpcCall,
|
|
16139
17253
|
officeRpcCall,
|
|
@@ -16144,23 +17258,23 @@ function IMSettingsTab({
|
|
|
16144
17258
|
browserLocation = globalThis.location,
|
|
16145
17259
|
navigateToRecoveryUrl = replacePageLocation
|
|
16146
17260
|
}) {
|
|
16147
|
-
const [selected, setSelected] =
|
|
16148
|
-
const [loopbackRecovery, setLoopbackRecovery] =
|
|
16149
|
-
const [runningVersion, setRunningVersion] =
|
|
16150
|
-
const [deliverySettings, setDeliverySettings] =
|
|
16151
|
-
const githubTooltipId =
|
|
16152
|
-
const generalSettingsTooltipId =
|
|
17261
|
+
const [selected, setSelected] = React28.useState("weixin");
|
|
17262
|
+
const [loopbackRecovery, setLoopbackRecovery] = React28.useState(null);
|
|
17263
|
+
const [runningVersion, setRunningVersion] = React28.useState(IM_PLUGIN_VERSION);
|
|
17264
|
+
const [deliverySettings, setDeliverySettings] = React28.useState(null);
|
|
17265
|
+
const githubTooltipId = React28.useId();
|
|
17266
|
+
const generalSettingsTooltipId = React28.useId();
|
|
16153
17267
|
const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
|
|
16154
17268
|
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
|
16155
17269
|
const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
|
|
16156
17270
|
const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
|
|
16157
|
-
const reportLoopbackRecovery =
|
|
17271
|
+
const reportLoopbackRecovery = React28.useCallback((recovery) => {
|
|
16158
17272
|
setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
|
|
16159
17273
|
}, []);
|
|
16160
|
-
const reportUpdateStatus =
|
|
17274
|
+
const reportUpdateStatus = React28.useCallback((snapshot) => {
|
|
16161
17275
|
setRunningVersion(snapshot.runningVersion);
|
|
16162
17276
|
}, []);
|
|
16163
|
-
const rpcCalls =
|
|
17277
|
+
const rpcCalls = React28.useMemo(() => createLoopbackAwareRpcCalls({
|
|
16164
17278
|
dingtalkRpcCall,
|
|
16165
17279
|
discordRpcCall,
|
|
16166
17280
|
feishuRpcCall,
|
|
@@ -16168,6 +17282,7 @@ function IMSettingsTab({
|
|
|
16168
17282
|
slackRpcCall,
|
|
16169
17283
|
telegramRpcCall,
|
|
16170
17284
|
wecomRpcCall,
|
|
17285
|
+
wecomAppRpcCall,
|
|
16171
17286
|
weixinRpcCall,
|
|
16172
17287
|
whatsappRpcCall,
|
|
16173
17288
|
officeRpcCall,
|
|
@@ -16191,10 +17306,11 @@ function IMSettingsTab({
|
|
|
16191
17306
|
telegramRpcCall,
|
|
16192
17307
|
updateRpcCall,
|
|
16193
17308
|
wecomRpcCall,
|
|
17309
|
+
wecomAppRpcCall,
|
|
16194
17310
|
weixinRpcCall,
|
|
16195
17311
|
whatsappRpcCall
|
|
16196
17312
|
]);
|
|
16197
|
-
const botSettingsContext =
|
|
17313
|
+
const botSettingsContext = React28.useMemo(() => Object.freeze({
|
|
16198
17314
|
openBotSettings: setDeliverySettings
|
|
16199
17315
|
}), []);
|
|
16200
17316
|
return h2(
|
|
@@ -16323,7 +17439,7 @@ function IMSettingsTab({
|
|
|
16323
17439
|
rpcCall: rpcCalls.deliveryRpcCall,
|
|
16324
17440
|
accessRpcCall: rpcCalls[`${active.id}RpcCall`],
|
|
16325
17441
|
onBack: () => setDeliverySettings(null)
|
|
16326
|
-
}) : 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 })
|
|
17442
|
+
}) : 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 })
|
|
16327
17443
|
)
|
|
16328
17444
|
)
|
|
16329
17445
|
)
|
|
@@ -16343,6 +17459,7 @@ function apply(ctx) {
|
|
|
16343
17459
|
installFeishuStyles(),
|
|
16344
17460
|
installWeixinStyles(),
|
|
16345
17461
|
installWecomStyles(),
|
|
17462
|
+
installWecomAppStyles(),
|
|
16346
17463
|
installQqStyles(),
|
|
16347
17464
|
installSlackStyles(),
|
|
16348
17465
|
installTelegramStyles(),
|
|
@@ -16360,6 +17477,7 @@ function apply(ctx) {
|
|
|
16360
17477
|
const dingtalkRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
|
|
16361
17478
|
const qqRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(QQ_RPC_CHANNEL, endpoint, payload, signal);
|
|
16362
17479
|
const wecomRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_RPC_CHANNEL, endpoint, payload, signal);
|
|
17480
|
+
const wecomAppRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_APP_RPC_CHANNEL, endpoint, payload, signal);
|
|
16363
17481
|
const telegramRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
|
|
16364
17482
|
const discordRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DISCORD_RPC_CHANNEL, endpoint, payload, signal);
|
|
16365
17483
|
const whatsappRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
|
|
@@ -16386,6 +17504,7 @@ function apply(ctx) {
|
|
|
16386
17504
|
slackRpcCall,
|
|
16387
17505
|
telegramRpcCall,
|
|
16388
17506
|
wecomRpcCall,
|
|
17507
|
+
wecomAppRpcCall,
|
|
16389
17508
|
weixinRpcCall,
|
|
16390
17509
|
whatsappRpcCall,
|
|
16391
17510
|
officeRpcCall,
|