@xmanrui/dsh-im 4.28.1 → 4.29.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 +5 -3
- package/README.md +5 -3
- package/assets/logo-plugin-message-link-gradient.webp +0 -0
- package/lib/client.js +371 -115
- package/lib/index.js +286 -286
- package/package.json +6 -1
- package/plugin-src/client/channels/feishu/api.js +3 -0
- package/plugin-src/client/channels/feishu/voice-editor.js +115 -0
- package/plugin-src/client/channels/feishu/voice-settings.js +71 -0
- package/plugin-src/client/delivery-settings.js +8 -0
- package/plugin-src/client/i18n.js +16 -0
- package/plugin-src/client/styles.js +11 -0
- package/plugin-src/host/channels/feishu/production.mjs +11 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +21 -0
- package/src/channels/feishu/bridge.mjs +158 -11
- package/src/channels/feishu/feishu-cards.mjs +4 -2
- package/src/channels/feishu/feishu-runtime.mjs +16 -0
- package/src/channels/feishu/multi-bot-controller.mjs +22 -0
- package/src/channels/feishu/plugin-config-store.mjs +2 -0
- package/src/channels/feishu/voice-config.mjs +34 -0
- package/src/channels/feishu/voice.mjs +134 -0
- package/src/channels/shared/harness-approval.mjs +24 -17
package/lib/client.js
CHANGED
|
@@ -590,12 +590,13 @@ async function callManagementRpc(connection, channel7, method, payload, signal)
|
|
|
590
590
|
}
|
|
591
591
|
|
|
592
592
|
// plugin-src/client/index.js
|
|
593
|
-
var
|
|
593
|
+
var React36 = __toESM(require("react"), 1);
|
|
594
594
|
|
|
595
595
|
// package.json
|
|
596
596
|
var package_default = {
|
|
597
597
|
name: "@xmanrui/dsh-im",
|
|
598
|
-
version: "4.
|
|
598
|
+
version: "4.29.1",
|
|
599
|
+
icon: "./assets/logo-plugin-message-link-gradient.webp",
|
|
599
600
|
description: "\u628A\u5341\u4E8C\u79CD IM \u6E20\u9053\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect twelve IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
600
601
|
keywords: [
|
|
601
602
|
"deepseek-harness",
|
|
@@ -680,6 +681,10 @@ var package_default = {
|
|
|
680
681
|
{
|
|
681
682
|
name: "Zhe (Phil) Yang",
|
|
682
683
|
url: "https://github.com/yangzhe1991"
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
name: "Biertolovisk",
|
|
687
|
+
url: "https://github.com/rosalynthompson32-a11y"
|
|
683
688
|
}
|
|
684
689
|
],
|
|
685
690
|
license: "MIT",
|
|
@@ -1486,6 +1491,22 @@ var EN = Object.freeze({
|
|
|
1486
1491
|
"\u63A8\u8350\u957F\u4EFB\u52A1\u4F7F\u7528\uFF1A\u8FC7\u7A0B\u4E0E\u6700\u7EC8\u7B54\u6848\u90FD\u5728\u540C\u4E00\u5F20\u5361\u7247\u91CC\u5B9E\u65F6\u66F4\u65B0\uFF0C\u4E0D\u5237\u5C4F": "Recommended for long tasks: the process and the final answer update live in one card without flooding the chat",
|
|
1487
1492
|
"\u6BCF\u4E00\u6B65\u90FD\u5355\u72EC\u53D1\u4E00\u6761\u6D88\u606F\uFF08\u542B\u5DE5\u5177\u8C03\u7528\u548C\u8FC7\u7A0B\u8BF4\u660E\uFF09\uFF1B\u6CE8\u610F\u957F\u4EFB\u52A1\u4F1A\u8FDE\u7EED\u53D1\u9001\u8F83\u591A\u6D88\u606F": "Every step is sent as its own message (including tool calls and notes); long tasks may send many messages in a row",
|
|
1488
1493
|
"\u5206\u6B65\u76F4\u63A8\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save the step push setting. Try again.",
|
|
1494
|
+
"\u8BED\u97F3\u4EA4\u4E92": "Voice",
|
|
1495
|
+
"\u6B63\u5728\u8BFB\u53D6\u8BED\u97F3\u8BBE\u7F6E\u2026": "Loading voice settings\u2026",
|
|
1496
|
+
"\u98DE\u4E66\u8BED\u97F3\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002": "Feishu voice settings are unavailable.",
|
|
1497
|
+
"\u672A\u627E\u5230\u5F53\u524D\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u8BF7\u8FD4\u56DE\u5217\u8868\u540E\u91CD\u8BD5\u3002": "This Feishu bot was not found. Return to the bot list and try again.",
|
|
1498
|
+
"\u67E5\u770B\u8BED\u97F3\u4EA4\u4E92\u8BF4\u660E": "View voice help",
|
|
1499
|
+
"\u8BED\u97F3\u4EA4\u4E92\u5F00\u5173": "Voice on/off",
|
|
1500
|
+
"\u5F00\u542F(\u8BED\u97F3\u63D0\u95EE\u4E0E\u8BED\u97F3\u56DE\u590D)": "On (voice questions and voice replies)",
|
|
1501
|
+
"\u6536\u5230\u8BED\u97F3\u6D88\u606F\u65F6\u8F6C\u5199\u4E3A\u6587\u5B57\u5E76\u6309\u6587\u5B57\u6D41\u6C34\u7EBF\u5904\u7406,\u7B54\u6848\u540C\u65F6\u4EE5\u8BED\u97F3\u56DE\u590D;\u8F6C\u5199\u5931\u8D25\u65F6\u964D\u7EA7\u4E3A\u4EC5\u652F\u6301\u6587\u5B57/\u56FE\u7247/\u6587\u4EF6\u7684\u63D0\u793A\u3002\u51ED\u636E\u503C\u5728\u63D2\u4EF6\u51ED\u636E\u5E93\u91CC\u7BA1\u7406,\u8FD9\u91CC\u53EA\u5F15\u7528\u73AF\u5883\u53D8\u91CF\u540D\u3002": "Voice messages are transcribed to text and processed by the normal text pipeline; the answer is also sent as a voice reply. If transcription fails, the bot falls back to the text/image/file-only notice. The credential value lives in the plugin credential store; only the environment variable name is referenced here.",
|
|
1502
|
+
"\u51ED\u636E\u5F15\u7528(\u73AF\u5883\u53D8\u91CF\u540D)": "Credential reference (environment variable name)",
|
|
1503
|
+
"\u8F6C\u5199\u6A21\u578B(ASR)": "Transcription model (ASR)",
|
|
1504
|
+
"\u5408\u6210\u6A21\u578B(TTS)": "Synthesis model (TTS)",
|
|
1505
|
+
"\u56DE\u590D\u97F3\u8272": "Reply voice",
|
|
1506
|
+
'\u9700\u8981 DashScope \u5BC6\u94A5(\u51ED\u636E\u5E93\u4E2D\u4EE5"\u51ED\u636E\u5F15\u7528"\u4E3A\u540D\u7684\u73AF\u5883\u53D8\u91CF)\u4E0E\u53EF\u7528 ffmpeg;\u97F3\u8272\u652F\u6301 Cherry/Serena/Bella/Chelsie/Momo/Katerina \u7B49 qwen3-tts-flash \u5B98\u65B9\u97F3\u8272\u3002': "Requires a DashScope API key (the credential-store environment variable named by the credential reference above) and a working ffmpeg. Supported voices include the official qwen3-tts-flash voices Cherry/Serena/Bella/Chelsie/Momo/Katerina.",
|
|
1507
|
+
"\u4FDD\u5B58\u8BED\u97F3\u8BBE\u7F6E": "Save voice settings",
|
|
1508
|
+
"\u9ED8\u8BA4\u5173\u95ED;\u5F00\u542F\u540E\u673A\u5668\u4EBA\u53EF\u542C\u61C2\u8BED\u97F3\u6D88\u606F\u5E76\u4EE5\u8BED\u97F3\u56DE\u590D\u3002": "Off by default. When enabled, the bot understands voice messages and replies by voice.",
|
|
1509
|
+
"\u8BED\u97F3\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save the voice settings. Try again.",
|
|
1489
1510
|
"zcode\u8FC7\u7A0B\u5361\u6A21\u5F0F": "ZCode process-card mode",
|
|
1490
1511
|
"\u8FC7\u7A0B\u8BF4\u660E\u3001\u5DE5\u5177\u6458\u8981\u4E0E\u6700\u7EC8\u7B54\u6848\u90FD\u5728\u540C\u4E00\u5F20\u5361\u7247\u4E2D\u539F\u5730\u5237\u65B0": "Process notes, the tool summary, and the final answer refresh in place inside one card",
|
|
1491
1512
|
"\u601D\u8003\u4E0E\u5DE5\u5177\u6458\u8981\u6298\u53E0\u5C55\u793A\uFF0C\u6700\u7EC8\u7B54\u6848\u5728\u540C\u4E00\u5F20\u5361\u7247\u4E2D\u539F\u5730\u5237\u65B0": "Thinking and the tool summary stay folded; the final answer refreshes in place inside one card",
|
|
@@ -7198,6 +7219,29 @@ function normalizeFeishuStepPushMode(value) {
|
|
|
7198
7219
|
return FEISHU_STEP_PUSH_MODES.POST;
|
|
7199
7220
|
}
|
|
7200
7221
|
|
|
7222
|
+
// src/channels/feishu/voice-config.mjs
|
|
7223
|
+
var DEFAULT_ASR_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
7224
|
+
var DEFAULT_ASR_MODEL = "qwen3-asr-flash";
|
|
7225
|
+
var DEFAULT_TTS_MODEL = "qwen3-tts-flash";
|
|
7226
|
+
var DEFAULT_TTS_VOICE = "Momo";
|
|
7227
|
+
function cleanString(value) {
|
|
7228
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
7229
|
+
}
|
|
7230
|
+
function normalizeFeishuVoiceConfig(value) {
|
|
7231
|
+
if (value == null || typeof value !== "object" || value.enabled !== true) return null;
|
|
7232
|
+
const secretRef = cleanString(value.secretRef);
|
|
7233
|
+
if (!secretRef || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(secretRef)) return null;
|
|
7234
|
+
return Object.freeze({
|
|
7235
|
+
enabled: true,
|
|
7236
|
+
secretRef,
|
|
7237
|
+
asrModel: cleanString(value.asrModel) ?? DEFAULT_ASR_MODEL,
|
|
7238
|
+
ttsModel: cleanString(value.ttsModel) ?? DEFAULT_TTS_MODEL,
|
|
7239
|
+
ttsVoice: cleanString(value.ttsVoice) ?? DEFAULT_TTS_VOICE,
|
|
7240
|
+
asrBaseUrl: cleanString(value.asrBaseUrl) ?? DEFAULT_ASR_BASE_URL,
|
|
7241
|
+
ffmpeg: cleanString(value.ffmpeg)
|
|
7242
|
+
});
|
|
7243
|
+
}
|
|
7244
|
+
|
|
7201
7245
|
// plugin-src/client/channels/feishu/api.js
|
|
7202
7246
|
var FEISHU_RPC_CHANNEL = "/feishu";
|
|
7203
7247
|
var FEISHU_ENDPOINTS = Object.freeze({
|
|
@@ -7221,6 +7265,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
7221
7265
|
setGroupTopicReply: "bot.group-topic-reply.set",
|
|
7222
7266
|
setStepPush: "bot.step-push.set",
|
|
7223
7267
|
setStepPushMode: "bot.step-push-mode.set",
|
|
7268
|
+
setVoice: "bot.voice.set",
|
|
7224
7269
|
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
|
|
7225
7270
|
testConnection: "connection.test",
|
|
7226
7271
|
disconnect: "connection.disconnect"
|
|
@@ -7377,6 +7422,7 @@ function normalizeBotConnection(value, fallbackBotId) {
|
|
|
7377
7422
|
groupTopicReply: value.groupTopicReply === true,
|
|
7378
7423
|
stepPush: value.stepPush === true,
|
|
7379
7424
|
stepPushMode: normalizeFeishuStepPushMode(value.stepPushMode),
|
|
7425
|
+
voice: normalizeFeishuVoiceConfig(value.voice),
|
|
7380
7426
|
groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
|
|
7381
7427
|
bot: normalizeBot2(value.bot),
|
|
7382
7428
|
health: normalizeHealth(value.health, connected),
|
|
@@ -16075,7 +16121,7 @@ function installInterfaceLanguageMirror(ctx, {
|
|
|
16075
16121
|
}
|
|
16076
16122
|
|
|
16077
16123
|
// plugin-src/client/delivery-settings.js
|
|
16078
|
-
var
|
|
16124
|
+
var React32 = __toESM(require("react"), 1);
|
|
16079
16125
|
|
|
16080
16126
|
// plugin-src/client/access-policy-settings.js
|
|
16081
16127
|
var React28 = __toESM(require("react"), 1);
|
|
@@ -17078,6 +17124,200 @@ function FeishuGroupSettingsPage({ account, rpcCall }) {
|
|
|
17078
17124
|
);
|
|
17079
17125
|
}
|
|
17080
17126
|
|
|
17127
|
+
// plugin-src/client/channels/feishu/voice-settings.js
|
|
17128
|
+
var React31 = __toESM(require("react"), 1);
|
|
17129
|
+
|
|
17130
|
+
// plugin-src/client/channels/feishu/voice-editor.js
|
|
17131
|
+
var React30 = __toESM(require("react"), 1);
|
|
17132
|
+
function VoiceEditor({ value = null, disabled = false, onSave }) {
|
|
17133
|
+
const [enabled, setEnabled] = React30.useState(value != null);
|
|
17134
|
+
const [secretRef, setSecretRef] = React30.useState(value?.secretRef ?? "DASHSCOPE_API_KEY");
|
|
17135
|
+
const [asrModel, setAsrModel] = React30.useState(value?.asrModel ?? "qwen3-asr-flash");
|
|
17136
|
+
const [ttsModel, setTtsModel] = React30.useState(value?.ttsModel ?? "qwen3-tts-flash");
|
|
17137
|
+
const [ttsVoice, setTtsVoice] = React30.useState(value?.ttsVoice ?? "Momo");
|
|
17138
|
+
const [saving, setSaving] = React30.useState(false);
|
|
17139
|
+
const [error, setError] = React30.useState(null);
|
|
17140
|
+
const titleId = React30.useId();
|
|
17141
|
+
const helpId = `${titleId}-help`;
|
|
17142
|
+
React30.useEffect(() => {
|
|
17143
|
+
setEnabled(value != null);
|
|
17144
|
+
if (value) {
|
|
17145
|
+
setSecretRef(value.secretRef ?? "DASHSCOPE_API_KEY");
|
|
17146
|
+
setAsrModel(value.asrModel ?? "qwen3-asr-flash");
|
|
17147
|
+
setTtsModel(value.ttsModel ?? "qwen3-tts-flash");
|
|
17148
|
+
setTtsVoice(value.ttsVoice ?? "Momo");
|
|
17149
|
+
}
|
|
17150
|
+
}, [value]);
|
|
17151
|
+
const persist = async (payload) => {
|
|
17152
|
+
if (saving || disabled) return;
|
|
17153
|
+
setSaving(true);
|
|
17154
|
+
setError(null);
|
|
17155
|
+
try {
|
|
17156
|
+
await onSave?.(payload);
|
|
17157
|
+
} catch (cause) {
|
|
17158
|
+
setError(cause?.message ?? "\u8BED\u97F3\u8BBE\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
17159
|
+
} finally {
|
|
17160
|
+
setSaving(false);
|
|
17161
|
+
}
|
|
17162
|
+
};
|
|
17163
|
+
const save = () => persist(enabled ? { enabled: true, secretRef, asrModel, ttsModel, ttsVoice } : null);
|
|
17164
|
+
const toggle = (next) => {
|
|
17165
|
+
setEnabled(next);
|
|
17166
|
+
if (!next) void persist(null);
|
|
17167
|
+
};
|
|
17168
|
+
const input = (label, state, setState, placeholder) => h2(
|
|
17169
|
+
"label",
|
|
17170
|
+
{ className: "dim-feishuVoiceField" },
|
|
17171
|
+
h2("span", { className: "dim-feishuVoiceLabel" }, label),
|
|
17172
|
+
h2("input", {
|
|
17173
|
+
type: "text",
|
|
17174
|
+
className: "dim-feishuVoiceInput",
|
|
17175
|
+
value: state,
|
|
17176
|
+
placeholder,
|
|
17177
|
+
disabled: disabled || saving,
|
|
17178
|
+
onChange: (event) => setState(event.target.value)
|
|
17179
|
+
})
|
|
17180
|
+
);
|
|
17181
|
+
return h2(
|
|
17182
|
+
"section",
|
|
17183
|
+
{
|
|
17184
|
+
className: "dim-feishuGroupControl",
|
|
17185
|
+
"aria-labelledby": titleId
|
|
17186
|
+
},
|
|
17187
|
+
h2(
|
|
17188
|
+
"div",
|
|
17189
|
+
{ className: "dim-feishuGroupControlHeader" },
|
|
17190
|
+
h2(
|
|
17191
|
+
"div",
|
|
17192
|
+
{ className: "dim-presetTitle" },
|
|
17193
|
+
h2("h3", { id: titleId }, "\u8BED\u97F3\u4EA4\u4E92"),
|
|
17194
|
+
h2(
|
|
17195
|
+
"span",
|
|
17196
|
+
{ className: "dim-presetHelp" },
|
|
17197
|
+
h2("button", {
|
|
17198
|
+
type: "button",
|
|
17199
|
+
className: "dim-presetHelpButton",
|
|
17200
|
+
"aria-label": "\u67E5\u770B\u8BED\u97F3\u4EA4\u4E92\u8BF4\u660E",
|
|
17201
|
+
"aria-describedby": helpId
|
|
17202
|
+
}, h2("span", { "aria-hidden": "true" }, "?")),
|
|
17203
|
+
h2("span", {
|
|
17204
|
+
id: helpId,
|
|
17205
|
+
className: "dim-presetTooltip",
|
|
17206
|
+
role: "tooltip"
|
|
17207
|
+
}, "\u6536\u5230\u8BED\u97F3\u6D88\u606F\u65F6\u8F6C\u5199\u4E3A\u6587\u5B57\u5E76\u6309\u6587\u5B57\u6D41\u6C34\u7EBF\u5904\u7406,\u7B54\u6848\u540C\u65F6\u4EE5\u8BED\u97F3\u56DE\u590D;\u8F6C\u5199\u5931\u8D25\u65F6\u964D\u7EA7\u4E3A\u4EC5\u652F\u6301\u6587\u5B57/\u56FE\u7247/\u6587\u4EF6\u7684\u63D0\u793A\u3002\u51ED\u636E\u503C\u5728\u63D2\u4EF6\u51ED\u636E\u5E93\u91CC\u7BA1\u7406,\u8FD9\u91CC\u53EA\u5F15\u7528\u73AF\u5883\u53D8\u91CF\u540D\u3002")
|
|
17208
|
+
)
|
|
17209
|
+
),
|
|
17210
|
+
saving ? h2("span", { className: "dim-feishuGroupControlStatus", role: "status" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
17211
|
+
),
|
|
17212
|
+
h2(
|
|
17213
|
+
"select",
|
|
17214
|
+
{
|
|
17215
|
+
className: "dim-feishuGroupSelect",
|
|
17216
|
+
value: enabled ? "on" : "off",
|
|
17217
|
+
disabled: disabled || saving,
|
|
17218
|
+
"aria-label": "\u8BED\u97F3\u4EA4\u4E92\u5F00\u5173",
|
|
17219
|
+
onChange: (event) => toggle(event.target.value === "on")
|
|
17220
|
+
},
|
|
17221
|
+
h2("option", { value: "off" }, "\u5173\u95ED"),
|
|
17222
|
+
h2("option", { value: "on" }, "\u5F00\u542F(\u8BED\u97F3\u63D0\u95EE\u4E0E\u8BED\u97F3\u56DE\u590D)")
|
|
17223
|
+
),
|
|
17224
|
+
enabled ? h2(
|
|
17225
|
+
"div",
|
|
17226
|
+
{ className: "dim-feishuVoiceForm" },
|
|
17227
|
+
input("\u51ED\u636E\u5F15\u7528(\u73AF\u5883\u53D8\u91CF\u540D)", secretRef, setSecretRef, "DASHSCOPE_API_KEY"),
|
|
17228
|
+
input("\u8F6C\u5199\u6A21\u578B(ASR)", asrModel, setAsrModel, "qwen3-asr-flash"),
|
|
17229
|
+
input("\u5408\u6210\u6A21\u578B(TTS)", ttsModel, setTtsModel, "qwen3-tts-flash"),
|
|
17230
|
+
input("\u56DE\u590D\u97F3\u8272", ttsVoice, setTtsVoice, "Momo"),
|
|
17231
|
+
h2(
|
|
17232
|
+
"p",
|
|
17233
|
+
{ className: "dim-feishuGroupHelp" },
|
|
17234
|
+
'\u9700\u8981 DashScope \u5BC6\u94A5(\u51ED\u636E\u5E93\u4E2D\u4EE5"\u51ED\u636E\u5F15\u7528"\u4E3A\u540D\u7684\u73AF\u5883\u53D8\u91CF)\u4E0E\u53EF\u7528 ffmpeg;\u97F3\u8272\u652F\u6301 Cherry/Serena/Bella/Chelsie/Momo/Katerina \u7B49 qwen3-tts-flash \u5B98\u65B9\u97F3\u8272\u3002'
|
|
17235
|
+
),
|
|
17236
|
+
h2(
|
|
17237
|
+
"div",
|
|
17238
|
+
{ className: "dim-feishuVoiceActions" },
|
|
17239
|
+
h2("button", {
|
|
17240
|
+
type: "button",
|
|
17241
|
+
className: "dim-feishuVoiceSave",
|
|
17242
|
+
onClick: () => void save(),
|
|
17243
|
+
disabled: disabled || saving || !secretRef.trim()
|
|
17244
|
+
}, "\u4FDD\u5B58\u8BED\u97F3\u8BBE\u7F6E")
|
|
17245
|
+
)
|
|
17246
|
+
) : h2("p", { className: "dim-feishuGroupHelp" }, "\u9ED8\u8BA4\u5173\u95ED;\u5F00\u542F\u540E\u673A\u5668\u4EBA\u53EF\u542C\u61C2\u8BED\u97F3\u6D88\u606F\u5E76\u4EE5\u8BED\u97F3\u56DE\u590D\u3002"),
|
|
17247
|
+
error ? h2("p", {
|
|
17248
|
+
className: "dim-feishuGroupError",
|
|
17249
|
+
role: "alert"
|
|
17250
|
+
}, error) : null
|
|
17251
|
+
);
|
|
17252
|
+
}
|
|
17253
|
+
|
|
17254
|
+
// plugin-src/client/channels/feishu/voice-settings.js
|
|
17255
|
+
function FeishuVoiceSettingsPage({ account, rpcCall }) {
|
|
17256
|
+
const [voice, setVoice] = React31.useState(null);
|
|
17257
|
+
const [phase, setPhase] = React31.useState("loading");
|
|
17258
|
+
const [error, setError] = React31.useState(null);
|
|
17259
|
+
const mounted = React31.useRef(true);
|
|
17260
|
+
const invoke = React31.useCallback(async (endpoint, payload, signal) => {
|
|
17261
|
+
if (typeof rpcCall !== "function") throw new Error("\u98DE\u4E66\u8BED\u97F3\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
17262
|
+
return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
|
|
17263
|
+
}, [rpcCall]);
|
|
17264
|
+
const applySnapshot = React31.useCallback((value) => {
|
|
17265
|
+
const bot = normalizeBotsSnapshot(value).bots.find((entry) => entry.botId === account.botId);
|
|
17266
|
+
if (!bot) throw new Error("\u672A\u627E\u5230\u5F53\u524D\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u8BF7\u8FD4\u56DE\u5217\u8868\u540E\u91CD\u8BD5\u3002");
|
|
17267
|
+
if (mounted.current) setVoice(bot.voice);
|
|
17268
|
+
}, [account.botId]);
|
|
17269
|
+
const loadSettings = React31.useCallback(async (signal) => {
|
|
17270
|
+
setPhase("loading");
|
|
17271
|
+
setError(null);
|
|
17272
|
+
try {
|
|
17273
|
+
const value = await invoke(FEISHU_ENDPOINTS.status, {}, signal);
|
|
17274
|
+
if (signal?.aborted || !mounted.current) return;
|
|
17275
|
+
applySnapshot(value);
|
|
17276
|
+
setPhase("ready");
|
|
17277
|
+
} catch (cause) {
|
|
17278
|
+
if (signal?.aborted || !mounted.current) return;
|
|
17279
|
+
setError(cause?.message ?? "\u98DE\u4E66\u8BED\u97F3\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
17280
|
+
setPhase("error");
|
|
17281
|
+
}
|
|
17282
|
+
}, [applySnapshot, invoke]);
|
|
17283
|
+
React31.useEffect(() => {
|
|
17284
|
+
mounted.current = true;
|
|
17285
|
+
const controller = new AbortController();
|
|
17286
|
+
void loadSettings(controller.signal);
|
|
17287
|
+
return () => {
|
|
17288
|
+
mounted.current = false;
|
|
17289
|
+
controller.abort();
|
|
17290
|
+
};
|
|
17291
|
+
}, [loadSettings]);
|
|
17292
|
+
const saveVoice = async (settings) => {
|
|
17293
|
+
const value = await invoke(FEISHU_ENDPOINTS.setVoice, {
|
|
17294
|
+
botId: account.botId,
|
|
17295
|
+
voice: settings === null ? null : { ...voice, ...settings }
|
|
17296
|
+
});
|
|
17297
|
+
if (mounted.current) applySnapshot(value);
|
|
17298
|
+
};
|
|
17299
|
+
if (phase === "loading") {
|
|
17300
|
+
return h2(
|
|
17301
|
+
"div",
|
|
17302
|
+
{ className: "dim-deliveryState", role: "status", "aria-busy": "true" },
|
|
17303
|
+
"\u6B63\u5728\u8BFB\u53D6\u8BED\u97F3\u8BBE\u7F6E\u2026"
|
|
17304
|
+
);
|
|
17305
|
+
}
|
|
17306
|
+
if (phase === "error") {
|
|
17307
|
+
return h2(
|
|
17308
|
+
"div",
|
|
17309
|
+
{ className: "dim-deliveryState", role: "alert" },
|
|
17310
|
+
h2("p", null, error),
|
|
17311
|
+
h2("button", {
|
|
17312
|
+
type: "button",
|
|
17313
|
+
className: "dim-deliveryButton",
|
|
17314
|
+
onClick: () => void loadSettings()
|
|
17315
|
+
}, "\u91CD\u65B0\u8BFB\u53D6")
|
|
17316
|
+
);
|
|
17317
|
+
}
|
|
17318
|
+
return h2(VoiceEditor, { value: voice, onSave: saveVoice });
|
|
17319
|
+
}
|
|
17320
|
+
|
|
17081
17321
|
// plugin-src/client/delivery-settings.js
|
|
17082
17322
|
var DELIVERY_RPC_CHANNEL = "/dsh-im-delivery";
|
|
17083
17323
|
var DELIVERY_DOCS_URL = Object.freeze({
|
|
@@ -17099,7 +17339,8 @@ var BOT_SETTINGS_TABS = Object.freeze([
|
|
|
17099
17339
|
]);
|
|
17100
17340
|
var FEISHU_BOT_SETTINGS_TABS = Object.freeze([
|
|
17101
17341
|
...BOT_SETTINGS_TABS,
|
|
17102
|
-
Object.freeze({ id: "group", label: "\u7FA4\u804A" })
|
|
17342
|
+
Object.freeze({ id: "group", label: "\u7FA4\u804A" }),
|
|
17343
|
+
Object.freeze({ id: "voice", label: "\u8BED\u97F3\u4EA4\u4E92" })
|
|
17103
17344
|
]);
|
|
17104
17345
|
function botSettingsTabsForChannel(channel7) {
|
|
17105
17346
|
return channel7 === "feishu" ? FEISHU_BOT_SETTINGS_TABS : BOT_SETTINGS_TABS;
|
|
@@ -17311,13 +17552,13 @@ function TargetForm({
|
|
|
17311
17552
|
}) {
|
|
17312
17553
|
const editing = mode === "edit";
|
|
17313
17554
|
const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
|
|
17314
|
-
const [targetId, setTargetId] =
|
|
17315
|
-
const [name2, setName] =
|
|
17316
|
-
const [kind, setKind] =
|
|
17317
|
-
const [route, setRoute] =
|
|
17318
|
-
const [error, setError] =
|
|
17319
|
-
const [testing, setTesting] =
|
|
17320
|
-
const [testState, setTestState] =
|
|
17555
|
+
const [targetId, setTargetId] = React32.useState(initialValue?.targetId ?? "");
|
|
17556
|
+
const [name2, setName] = React32.useState(initialValue?.name ?? "");
|
|
17557
|
+
const [kind, setKind] = React32.useState(initialKind);
|
|
17558
|
+
const [route, setRoute] = React32.useState(initialValue?.route ?? {});
|
|
17559
|
+
const [error, setError] = React32.useState(null);
|
|
17560
|
+
const [testing, setTesting] = React32.useState(false);
|
|
17561
|
+
const [testState, setTestState] = React32.useState(null);
|
|
17321
17562
|
const currentTarget = () => {
|
|
17322
17563
|
const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field2) => {
|
|
17323
17564
|
const raw = String(route[field2.key] ?? "").trim();
|
|
@@ -17534,7 +17775,7 @@ function TargetSuggestionPicker({
|
|
|
17534
17775
|
suggestions.map((suggestion, index) => {
|
|
17535
17776
|
const identity = routeIdentity(definition, suggestion);
|
|
17536
17777
|
const added = configured.has(identity);
|
|
17537
|
-
return
|
|
17778
|
+
return React32.createElement("option", {
|
|
17538
17779
|
key: suggestion.id ?? suggestion.suggestionId ?? `${identity}:${index}`,
|
|
17539
17780
|
value: String(index),
|
|
17540
17781
|
disabled: added
|
|
@@ -17551,11 +17792,11 @@ function TargetSuggestionPicker({
|
|
|
17551
17792
|
);
|
|
17552
17793
|
}
|
|
17553
17794
|
function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
|
|
17554
|
-
const [action, setAction] =
|
|
17555
|
-
const [testState, setTestState] =
|
|
17556
|
-
const [syncFeedback, setSyncFeedback] =
|
|
17557
|
-
const [copyState, setCopyState] =
|
|
17558
|
-
const [confirmDelete, setConfirmDelete] =
|
|
17795
|
+
const [action, setAction] = React32.useState(null);
|
|
17796
|
+
const [testState, setTestState] = React32.useState(null);
|
|
17797
|
+
const [syncFeedback, setSyncFeedback] = React32.useState(null);
|
|
17798
|
+
const [copyState, setCopyState] = React32.useState(null);
|
|
17799
|
+
const [confirmDelete, setConfirmDelete] = React32.useState(false);
|
|
17559
17800
|
const sessionSync = target.sessionSync ?? { enabled: false, state: "unavailable" };
|
|
17560
17801
|
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";
|
|
17561
17802
|
const testTarget = async () => {
|
|
@@ -17618,7 +17859,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|
|
17618
17859
|
h2(
|
|
17619
17860
|
"div",
|
|
17620
17861
|
{ className: "dim-targetTitle" },
|
|
17621
|
-
|
|
17862
|
+
React32.createElement("strong", null, target.name || target.targetId),
|
|
17622
17863
|
h2("span", null, kindLabel(definition, target.kind))
|
|
17623
17864
|
),
|
|
17624
17865
|
h2("code", null, `targetId: ${target.targetId}`)
|
|
@@ -17704,26 +17945,26 @@ function DeliveryTargetSettingsPage({
|
|
|
17704
17945
|
onBack
|
|
17705
17946
|
}) {
|
|
17706
17947
|
const definition = CHANNEL_DEFINITIONS[channel7];
|
|
17707
|
-
const [activeTabId, setActiveTabId] =
|
|
17708
|
-
const [phase, setPhase] =
|
|
17709
|
-
const [targets, setTargets] =
|
|
17710
|
-
const [suggestionPhase, setSuggestionPhase] =
|
|
17711
|
-
const [suggestions, setSuggestions] =
|
|
17712
|
-
const [suggestionError, setSuggestionError] =
|
|
17713
|
-
const [error, setError] =
|
|
17714
|
-
const [editor, setEditor] =
|
|
17715
|
-
const [saving, setSaving] =
|
|
17716
|
-
const [botCopyState, setBotCopyState] =
|
|
17717
|
-
const [accessPolicy, setAccessPolicy] =
|
|
17718
|
-
const mounted =
|
|
17719
|
-
|
|
17948
|
+
const [activeTabId, setActiveTabId] = React32.useState(BOT_SETTINGS_TABS[0].id);
|
|
17949
|
+
const [phase, setPhase] = React32.useState("loading");
|
|
17950
|
+
const [targets, setTargets] = React32.useState([]);
|
|
17951
|
+
const [suggestionPhase, setSuggestionPhase] = React32.useState("idle");
|
|
17952
|
+
const [suggestions, setSuggestions] = React32.useState([]);
|
|
17953
|
+
const [suggestionError, setSuggestionError] = React32.useState(null);
|
|
17954
|
+
const [error, setError] = React32.useState(null);
|
|
17955
|
+
const [editor, setEditor] = React32.useState(null);
|
|
17956
|
+
const [saving, setSaving] = React32.useState(false);
|
|
17957
|
+
const [botCopyState, setBotCopyState] = React32.useState(null);
|
|
17958
|
+
const [accessPolicy, setAccessPolicy] = React32.useState(account.accessPolicy);
|
|
17959
|
+
const mounted = React32.useRef(true);
|
|
17960
|
+
React32.useEffect(() => {
|
|
17720
17961
|
setAccessPolicy(account.accessPolicy);
|
|
17721
17962
|
}, [account.botId, account.accessPolicy]);
|
|
17722
|
-
const invoke =
|
|
17963
|
+
const invoke = React32.useCallback(async (endpoint, payload = {}, signal) => {
|
|
17723
17964
|
if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
17724
17965
|
return unwrapRpcResult15(await rpcCall(endpoint, payload, signal));
|
|
17725
17966
|
}, [rpcCall]);
|
|
17726
|
-
const loadTargets =
|
|
17967
|
+
const loadTargets = React32.useCallback(async ({ signal, silent = false } = {}) => {
|
|
17727
17968
|
if (!silent) setPhase("loading");
|
|
17728
17969
|
setError(null);
|
|
17729
17970
|
try {
|
|
@@ -17737,7 +17978,7 @@ function DeliveryTargetSettingsPage({
|
|
|
17737
17978
|
setPhase("error");
|
|
17738
17979
|
}
|
|
17739
17980
|
}, [account.botId, invoke]);
|
|
17740
|
-
const loadSuggestions =
|
|
17981
|
+
const loadSuggestions = React32.useCallback(async () => {
|
|
17741
17982
|
setSuggestionPhase("loading");
|
|
17742
17983
|
setSuggestionError(null);
|
|
17743
17984
|
try {
|
|
@@ -17751,7 +17992,7 @@ function DeliveryTargetSettingsPage({
|
|
|
17751
17992
|
setSuggestionPhase("error");
|
|
17752
17993
|
}
|
|
17753
17994
|
}, [account.botId, definition, invoke]);
|
|
17754
|
-
|
|
17995
|
+
React32.useEffect(() => {
|
|
17755
17996
|
mounted.current = true;
|
|
17756
17997
|
const controller = new AbortController();
|
|
17757
17998
|
void loadTargets({ signal: controller.signal });
|
|
@@ -17872,8 +18113,12 @@ function DeliveryTargetSettingsPage({
|
|
|
17872
18113
|
}) : activeTab.id === "group" && channel7 === "feishu" ? h2(FeishuGroupSettingsPage, {
|
|
17873
18114
|
account,
|
|
17874
18115
|
rpcCall: accessRpcCall
|
|
18116
|
+
}) : activeTab.id === "voice" && channel7 === "feishu" ? h2(FeishuVoiceSettingsPage, {
|
|
18117
|
+
key: account.botId,
|
|
18118
|
+
account,
|
|
18119
|
+
rpcCall: accessRpcCall
|
|
17875
18120
|
}) : h2(
|
|
17876
|
-
|
|
18121
|
+
React32.Fragment,
|
|
17877
18122
|
null,
|
|
17878
18123
|
h2(
|
|
17879
18124
|
"section",
|
|
@@ -17984,7 +18229,7 @@ function DeliveryTargetSettingsPage({
|
|
|
17984
18229
|
}
|
|
17985
18230
|
|
|
17986
18231
|
// plugin-src/client/global-settings.js
|
|
17987
|
-
var
|
|
18232
|
+
var React33 = __toESM(require("react"), 1);
|
|
17988
18233
|
|
|
17989
18234
|
// src/channels/shared/inbound-ttl.mjs
|
|
17990
18235
|
var DEFAULT_INBOUND_TTL_HOURS = 168;
|
|
@@ -18069,14 +18314,14 @@ function GlobalButton({ children, kind = "secondary", className = "", ...props }
|
|
|
18069
18314
|
}, children);
|
|
18070
18315
|
}
|
|
18071
18316
|
function ImageInputSettings({ rpcCall }) {
|
|
18072
|
-
const [values, setValues] =
|
|
18073
|
-
const [phase, setPhase] =
|
|
18074
|
-
const [error, setError] =
|
|
18075
|
-
const [saved, setSaved] =
|
|
18076
|
-
const mounted =
|
|
18077
|
-
const saving =
|
|
18078
|
-
const id6 =
|
|
18079
|
-
const load =
|
|
18317
|
+
const [values, setValues] = React33.useState(DEFAULT_IMAGE_INPUT_SETTINGS);
|
|
18318
|
+
const [phase, setPhase] = React33.useState("loading");
|
|
18319
|
+
const [error, setError] = React33.useState(null);
|
|
18320
|
+
const [saved, setSaved] = React33.useState(false);
|
|
18321
|
+
const mounted = React33.useRef(false);
|
|
18322
|
+
const saving = React33.useRef(false);
|
|
18323
|
+
const id6 = React33.useId();
|
|
18324
|
+
const load = React33.useCallback(async (signal) => {
|
|
18080
18325
|
setPhase("loading");
|
|
18081
18326
|
setError(null);
|
|
18082
18327
|
try {
|
|
@@ -18092,7 +18337,7 @@ function ImageInputSettings({ rpcCall }) {
|
|
|
18092
18337
|
setPhase("error");
|
|
18093
18338
|
}
|
|
18094
18339
|
}, [rpcCall]);
|
|
18095
|
-
|
|
18340
|
+
React33.useEffect(() => {
|
|
18096
18341
|
mounted.current = true;
|
|
18097
18342
|
const controller = new AbortController();
|
|
18098
18343
|
void load(controller.signal);
|
|
@@ -18199,29 +18444,29 @@ function ImageInputSettings({ rpcCall }) {
|
|
|
18199
18444
|
);
|
|
18200
18445
|
}
|
|
18201
18446
|
function GlobalSettingsPanel({ rpcCall }) {
|
|
18202
|
-
const [phase, setPhase] =
|
|
18203
|
-
const [loadError, setLoadError] =
|
|
18204
|
-
const [ttlInput, setTtlInput] =
|
|
18205
|
-
const [savedTtl, setSavedTtl] =
|
|
18206
|
-
const [ttlError, setTtlError] =
|
|
18207
|
-
const [saveError, setSaveError] =
|
|
18208
|
-
const [saveSucceeded, setSaveSucceeded] =
|
|
18209
|
-
const [isSaving, setIsSaving] =
|
|
18210
|
-
const [sweepConfirming, setSweepConfirming] =
|
|
18211
|
-
const [sweeping, setSweeping] =
|
|
18212
|
-
const ttlErrorId =
|
|
18213
|
-
const ttlHintsId =
|
|
18214
|
-
const sweepTriggerId =
|
|
18215
|
-
const sweepConfirmId =
|
|
18216
|
-
const sweepConfirmTextId =
|
|
18217
|
-
const sweepConfirmButtonId =
|
|
18218
|
-
const mounted =
|
|
18219
|
-
const saving =
|
|
18220
|
-
const invoke =
|
|
18447
|
+
const [phase, setPhase] = React33.useState("loading");
|
|
18448
|
+
const [loadError, setLoadError] = React33.useState(null);
|
|
18449
|
+
const [ttlInput, setTtlInput] = React33.useState("");
|
|
18450
|
+
const [savedTtl, setSavedTtl] = React33.useState(null);
|
|
18451
|
+
const [ttlError, setTtlError] = React33.useState(false);
|
|
18452
|
+
const [saveError, setSaveError] = React33.useState(null);
|
|
18453
|
+
const [saveSucceeded, setSaveSucceeded] = React33.useState(false);
|
|
18454
|
+
const [isSaving, setIsSaving] = React33.useState(false);
|
|
18455
|
+
const [sweepConfirming, setSweepConfirming] = React33.useState(false);
|
|
18456
|
+
const [sweeping, setSweeping] = React33.useState(false);
|
|
18457
|
+
const ttlErrorId = React33.useId();
|
|
18458
|
+
const ttlHintsId = React33.useId();
|
|
18459
|
+
const sweepTriggerId = React33.useId();
|
|
18460
|
+
const sweepConfirmId = React33.useId();
|
|
18461
|
+
const sweepConfirmTextId = React33.useId();
|
|
18462
|
+
const sweepConfirmButtonId = React33.useId();
|
|
18463
|
+
const mounted = React33.useRef(true);
|
|
18464
|
+
const saving = React33.useRef(false);
|
|
18465
|
+
const invoke = React33.useCallback(async (endpoint, payload = {}, signal) => {
|
|
18221
18466
|
if (typeof rpcCall !== "function") throw new Error("\u901A\u7528\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
|
18222
18467
|
return unwrapRpcResult16(await rpcCall(endpoint, payload, signal));
|
|
18223
18468
|
}, [rpcCall]);
|
|
18224
|
-
const loadSettings =
|
|
18469
|
+
const loadSettings = React33.useCallback(async ({ signal } = {}) => {
|
|
18225
18470
|
setPhase("loading");
|
|
18226
18471
|
setLoadError(null);
|
|
18227
18472
|
try {
|
|
@@ -18245,7 +18490,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
18245
18490
|
setPhase("error");
|
|
18246
18491
|
}
|
|
18247
18492
|
}, [invoke]);
|
|
18248
|
-
|
|
18493
|
+
React33.useEffect(() => {
|
|
18249
18494
|
mounted.current = true;
|
|
18250
18495
|
const controller = new AbortController();
|
|
18251
18496
|
void loadSettings({ signal: controller.signal });
|
|
@@ -18254,7 +18499,7 @@ function GlobalSettingsPanel({ rpcCall }) {
|
|
|
18254
18499
|
controller.abort();
|
|
18255
18500
|
};
|
|
18256
18501
|
}, [loadSettings]);
|
|
18257
|
-
|
|
18502
|
+
React33.useEffect(() => {
|
|
18258
18503
|
if (!sweepConfirming) return;
|
|
18259
18504
|
globalThis.document?.getElementById(sweepConfirmButtonId)?.focus();
|
|
18260
18505
|
}, [sweepConfirmButtonId, sweepConfirming]);
|
|
@@ -19041,6 +19286,17 @@ var CSS15 = String.raw`
|
|
|
19041
19286
|
.dim-feishuGroupSelect:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary, #3370ff); box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 15%, transparent); }
|
|
19042
19287
|
.dim-feishuGroupSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
19043
19288
|
.dim-feishuGroupHelp { margin: -2px 0 0; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; line-height: 19px; }
|
|
19289
|
+
.dim-feishuVoiceForm { min-width: 0; display: grid; gap: 10px; }
|
|
19290
|
+
.dim-feishuVoiceField { min-width: 0; display: grid; gap: 5px; }
|
|
19291
|
+
.dim-feishuVoiceLabel { color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; }
|
|
19292
|
+
.dim-feishuVoiceInput { min-width: 0; width: 100%; height: 36px; padding: 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: 36px; transition: border-color .15s ease, box-shadow .15s ease; }
|
|
19293
|
+
.dim-feishuVoiceInput:hover:not(:disabled) { border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 42%, var(--dsw-alias-border-l2, #dfe1e5)); }
|
|
19294
|
+
.dim-feishuVoiceInput:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary, #3370ff); box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 15%, transparent); }
|
|
19295
|
+
.dim-feishuVoiceInput:disabled { cursor: not-allowed; opacity: .55; }
|
|
19296
|
+
.dim-feishuVoiceActions { display: flex; justify-content: flex-start; }
|
|
19297
|
+
.dim-feishuVoiceSave { height: 34px; padding: 0 15px; border: 1px solid var(--dsw-alias-state-business-primary, #3370ff); border-radius: 8px; color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 13px; line-height: 32px; cursor: pointer; transition: border-color .15s ease, color .15s ease, background .15s ease; }
|
|
19298
|
+
.dim-feishuVoiceSave:hover:not(:disabled) { color: #0f5fce; border-color: #0f5fce; background: color-mix(in srgb, #3370ff 6%, var(--dsw-alias-bg-layer-1, #fff)); }
|
|
19299
|
+
.dim-feishuVoiceSave:disabled { cursor: not-allowed; opacity: .55; }
|
|
19044
19300
|
.dim-feishuGroupPermissionAction { display: flex; justify-content: flex-start; }
|
|
19045
19301
|
.dim-feishuGroupPermissionAction .dim-deliveryButton { color: var(--dsw-alias-state-business-primary, #3370ff); border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary, #3370ff) 30%, var(--dsw-alias-border-l2, #dfe1e5)); }
|
|
19046
19302
|
.dim-feishuGroupError, .dim-feishuGroupRefreshError { margin: 0; padding: 9px 11px; border-radius: 8px; font-size: 12px; line-height: 18px; }
|
|
@@ -19555,7 +19811,7 @@ function installSessionChannelLogos(document2 = globalThis.document) {
|
|
|
19555
19811
|
}
|
|
19556
19812
|
|
|
19557
19813
|
// plugin-src/client/update-panel.js
|
|
19558
|
-
var
|
|
19814
|
+
var React34 = __toESM(require("react"), 1);
|
|
19559
19815
|
var import_react_dom4 = require("react-dom");
|
|
19560
19816
|
var import_valid = __toESM(require_valid(), 1);
|
|
19561
19817
|
var import_rcompare = __toESM(require_rcompare(), 1);
|
|
@@ -19648,11 +19904,11 @@ function manualUpdateCommand(snapshot) {
|
|
|
19648
19904
|
return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`;
|
|
19649
19905
|
}
|
|
19650
19906
|
function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
19651
|
-
const [copyState, setCopyState] =
|
|
19652
|
-
const commandRef =
|
|
19653
|
-
const mounted =
|
|
19654
|
-
const copying =
|
|
19655
|
-
|
|
19907
|
+
const [copyState, setCopyState] = React34.useState("idle");
|
|
19908
|
+
const commandRef = React34.useRef(null);
|
|
19909
|
+
const mounted = React34.useRef(false);
|
|
19910
|
+
const copying = React34.useRef(false);
|
|
19911
|
+
React34.useEffect(() => {
|
|
19656
19912
|
mounted.current = true;
|
|
19657
19913
|
return () => {
|
|
19658
19914
|
mounted.current = false;
|
|
@@ -19684,7 +19940,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
19684
19940
|
{ className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
|
|
19685
19941
|
h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
|
|
19686
19942
|
command ? h2(
|
|
19687
|
-
|
|
19943
|
+
React34.Fragment,
|
|
19688
19944
|
null,
|
|
19689
19945
|
h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
|
|
19690
19946
|
h2(
|
|
@@ -19720,7 +19976,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
19720
19976
|
"aria-hidden": "true",
|
|
19721
19977
|
focusable: "false"
|
|
19722
19978
|
}, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
|
|
19723
|
-
|
|
19979
|
+
React34.Fragment,
|
|
19724
19980
|
null,
|
|
19725
19981
|
h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
|
|
19726
19982
|
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" })
|
|
@@ -19745,10 +20001,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|
|
19745
20001
|
);
|
|
19746
20002
|
}
|
|
19747
20003
|
function UpdateDialog({ children, onClose }) {
|
|
19748
|
-
const dialogRef =
|
|
19749
|
-
const titleId =
|
|
19750
|
-
const descriptionId =
|
|
19751
|
-
|
|
20004
|
+
const dialogRef = React34.useRef(null);
|
|
20005
|
+
const titleId = React34.useId();
|
|
20006
|
+
const descriptionId = React34.useId();
|
|
20007
|
+
React34.useEffect(() => {
|
|
19752
20008
|
const previous = globalThis.document?.activeElement;
|
|
19753
20009
|
dialogRef.current?.focus?.();
|
|
19754
20010
|
return () => {
|
|
@@ -19806,20 +20062,20 @@ function UpdateDialog({ children, onClose }) {
|
|
|
19806
20062
|
return typeof document !== "undefined" && document.body ? (0, import_react_dom4.createPortal)(content, document.body) : content;
|
|
19807
20063
|
}
|
|
19808
20064
|
function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
19809
|
-
const tooltipId =
|
|
19810
|
-
const [snapshot, setSnapshot] =
|
|
19811
|
-
const [action, setAction] =
|
|
19812
|
-
const [error, setError] =
|
|
19813
|
-
const [open, setOpen] =
|
|
19814
|
-
const [uncertainInstall, setUncertainInstall] =
|
|
19815
|
-
const mounted =
|
|
19816
|
-
const busy =
|
|
19817
|
-
const readController =
|
|
19818
|
-
const pollReadController =
|
|
19819
|
-
const installRequest =
|
|
19820
|
-
const onStatusRef =
|
|
20065
|
+
const tooltipId = React34.useId();
|
|
20066
|
+
const [snapshot, setSnapshot] = React34.useState(null);
|
|
20067
|
+
const [action, setAction] = React34.useState("status");
|
|
20068
|
+
const [error, setError] = React34.useState(null);
|
|
20069
|
+
const [open, setOpen] = React34.useState(false);
|
|
20070
|
+
const [uncertainInstall, setUncertainInstall] = React34.useState(false);
|
|
20071
|
+
const mounted = React34.useRef(false);
|
|
20072
|
+
const busy = React34.useRef(false);
|
|
20073
|
+
const readController = React34.useRef(null);
|
|
20074
|
+
const pollReadController = React34.useRef(null);
|
|
20075
|
+
const installRequest = React34.useRef(null);
|
|
20076
|
+
const onStatusRef = React34.useRef(onStatus);
|
|
19821
20077
|
onStatusRef.current = onStatus;
|
|
19822
|
-
const accept =
|
|
20078
|
+
const accept = React34.useCallback((next) => {
|
|
19823
20079
|
setSnapshot(next);
|
|
19824
20080
|
onStatusRef.current?.(next);
|
|
19825
20081
|
}, []);
|
|
@@ -19828,7 +20084,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
19828
20084
|
setUncertainInstall(false);
|
|
19829
20085
|
accept(next);
|
|
19830
20086
|
};
|
|
19831
|
-
const invoke =
|
|
20087
|
+
const invoke = React34.useCallback(async (endpoint, payload = {}, signal) => {
|
|
19832
20088
|
if (typeof rpcCall !== "function") {
|
|
19833
20089
|
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");
|
|
19834
20090
|
unavailable.code = "update-unavailable";
|
|
@@ -19836,7 +20092,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
19836
20092
|
}
|
|
19837
20093
|
return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
|
|
19838
20094
|
}, [rpcCall]);
|
|
19839
|
-
|
|
20095
|
+
React34.useEffect(() => {
|
|
19840
20096
|
mounted.current = true;
|
|
19841
20097
|
busy.current = true;
|
|
19842
20098
|
const controller = new AbortController();
|
|
@@ -19859,7 +20115,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
19859
20115
|
const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
|
|
19860
20116
|
const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
|
|
19861
20117
|
const shouldPoll = activeJob || uncertainInstall;
|
|
19862
|
-
|
|
20118
|
+
React34.useEffect(() => {
|
|
19863
20119
|
if (!shouldPoll) return void 0;
|
|
19864
20120
|
let controller;
|
|
19865
20121
|
const scheduler = createPollScheduler({
|
|
@@ -19960,7 +20216,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
19960
20216
|
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";
|
|
19961
20217
|
const buttonDescription = localizeText(buttonLabel) + (buttonLabel === "\u66F4\u65B0\u81F3" ? ` v${snapshot.latestVersion}` : "");
|
|
19962
20218
|
return h2(
|
|
19963
|
-
|
|
20219
|
+
React34.Fragment,
|
|
19964
20220
|
null,
|
|
19965
20221
|
h2(
|
|
19966
20222
|
"span",
|
|
@@ -20010,25 +20266,25 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
20010
20266
|
h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
|
|
20011
20267
|
h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
|
|
20012
20268
|
snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
|
|
20013
|
-
|
|
20269
|
+
React34.Fragment,
|
|
20014
20270
|
null,
|
|
20015
20271
|
h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
|
|
20016
20272
|
h2("dd", null, `v${snapshot.installedVersion}`)
|
|
20017
20273
|
) : null,
|
|
20018
20274
|
targetVersion ? h2(
|
|
20019
|
-
|
|
20275
|
+
React34.Fragment,
|
|
20020
20276
|
null,
|
|
20021
20277
|
h2("dt", null, "\u76EE\u6807\u7248\u672C"),
|
|
20022
20278
|
h2("dd", null, `v${targetVersion}`)
|
|
20023
20279
|
) : null,
|
|
20024
20280
|
latestVersion ? h2(
|
|
20025
|
-
|
|
20281
|
+
React34.Fragment,
|
|
20026
20282
|
null,
|
|
20027
20283
|
h2("dt", null, "\u6700\u65B0\u7248\u672C"),
|
|
20028
20284
|
h2("dd", null, `v${latestVersion}`)
|
|
20029
20285
|
) : null,
|
|
20030
20286
|
historicalTargetVersion ? h2(
|
|
20031
|
-
|
|
20287
|
+
React34.Fragment,
|
|
20032
20288
|
null,
|
|
20033
20289
|
h2("dt", null, "\u4E0A\u6B21\u66F4\u65B0\u76EE\u6807"),
|
|
20034
20290
|
h2("dd", null, `v${historicalTargetVersion}`)
|
|
@@ -20110,8 +20366,8 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|
|
20110
20366
|
}
|
|
20111
20367
|
|
|
20112
20368
|
// plugin-src/client/panel-error-boundary.js
|
|
20113
|
-
var
|
|
20114
|
-
var IMPanelErrorBoundary = class extends
|
|
20369
|
+
var React35 = __toESM(require("react"), 1);
|
|
20370
|
+
var IMPanelErrorBoundary = class extends React35.Component {
|
|
20115
20371
|
state = { failed: false };
|
|
20116
20372
|
static getDerivedStateFromError() {
|
|
20117
20373
|
return { failed: true };
|
|
@@ -20304,28 +20560,28 @@ function IMSettingsTab({
|
|
|
20304
20560
|
browserLocation = globalThis.location,
|
|
20305
20561
|
navigateToRecoveryUrl = replacePageLocation
|
|
20306
20562
|
}) {
|
|
20307
|
-
const [selected, setSelected] =
|
|
20308
|
-
const [loopbackRecovery, setLoopbackRecovery] =
|
|
20309
|
-
const [runningVersion, setRunningVersion] =
|
|
20310
|
-
const [deliverySettings, setDeliverySettings] =
|
|
20563
|
+
const [selected, setSelected] = React36.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
|
|
20564
|
+
const [loopbackRecovery, setLoopbackRecovery] = React36.useState(null);
|
|
20565
|
+
const [runningVersion, setRunningVersion] = React36.useState(IM_PLUGIN_VERSION);
|
|
20566
|
+
const [deliverySettings, setDeliverySettings] = React36.useState(null);
|
|
20311
20567
|
const emailEnabled = useEmailChannelEnabled(emailRpcCall);
|
|
20312
|
-
const visibleChannels =
|
|
20568
|
+
const visibleChannels = React36.useMemo(
|
|
20313
20569
|
() => CHANNELS.filter((channel7) => channel7.id !== "email" || emailEnabled),
|
|
20314
20570
|
[emailEnabled]
|
|
20315
20571
|
);
|
|
20316
|
-
const githubTooltipId =
|
|
20317
|
-
const generalSettingsTooltipId =
|
|
20572
|
+
const githubTooltipId = React36.useId();
|
|
20573
|
+
const generalSettingsTooltipId = React36.useId();
|
|
20318
20574
|
const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
|
|
20319
20575
|
const active = visibleChannels.find((channel7) => channel7.id === selected) ?? visibleChannels[0];
|
|
20320
20576
|
const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
|
|
20321
20577
|
const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
|
|
20322
|
-
const reportLoopbackRecovery =
|
|
20578
|
+
const reportLoopbackRecovery = React36.useCallback((recovery) => {
|
|
20323
20579
|
setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
|
|
20324
20580
|
}, []);
|
|
20325
|
-
const reportUpdateStatus =
|
|
20581
|
+
const reportUpdateStatus = React36.useCallback((snapshot) => {
|
|
20326
20582
|
setRunningVersion(snapshot.runningVersion);
|
|
20327
20583
|
}, []);
|
|
20328
|
-
const rpcCalls =
|
|
20584
|
+
const rpcCalls = React36.useMemo(() => createLoopbackAwareRpcCalls({
|
|
20329
20585
|
dingtalkRpcCall,
|
|
20330
20586
|
discordRpcCall,
|
|
20331
20587
|
feishuRpcCall,
|
|
@@ -20367,7 +20623,7 @@ function IMSettingsTab({
|
|
|
20367
20623
|
weixinRpcCall,
|
|
20368
20624
|
whatsappRpcCall
|
|
20369
20625
|
]);
|
|
20370
|
-
const botSettingsContext =
|
|
20626
|
+
const botSettingsContext = React36.useMemo(() => Object.freeze({
|
|
20371
20627
|
openBotSettings: setDeliverySettings
|
|
20372
20628
|
}), []);
|
|
20373
20629
|
return h2(
|
|
@@ -20591,7 +20847,7 @@ function apply(ctx) {
|
|
|
20591
20847
|
};
|
|
20592
20848
|
const localeSnapshot = () => ctx.locale.getLocale?.()?.active ?? "";
|
|
20593
20849
|
function IMPanel({ preferredSectionId }) {
|
|
20594
|
-
|
|
20850
|
+
React36.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
|
|
20595
20851
|
return h2(
|
|
20596
20852
|
IMPanelErrorBoundary,
|
|
20597
20853
|
null,
|