@xmanrui/dsh-im 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -2
- package/README.md +3 -2
- package/lib/client.js +1297 -600
- package/lib/index.js +190 -145
- package/package.json +1 -1
- package/plugin-src/client/agent-preset.js +110 -0
- package/plugin-src/client/channels/dingtalk/api.js +5 -0
- package/plugin-src/client/channels/dingtalk/index.js +48 -2
- package/plugin-src/client/channels/feishu/api.js +28 -5
- package/plugin-src/client/channels/feishu/index.js +330 -41
- package/plugin-src/client/channels/feishu/styles.js +46 -0
- package/plugin-src/client/channels/qq/api.js +5 -0
- package/plugin-src/client/channels/qq/index.js +37 -6
- package/plugin-src/client/channels/shared/token-api.js +5 -0
- package/plugin-src/client/channels/shared/token-channel.js +34 -6
- package/plugin-src/client/channels/wecom/api.js +5 -0
- package/plugin-src/client/channels/wecom/index.js +37 -6
- package/plugin-src/client/channels/weixin/api.js +5 -0
- package/plugin-src/client/channels/weixin/index.js +50 -4
- package/plugin-src/client/channels/whatsapp/api.js +5 -0
- package/plugin-src/client/channels/whatsapp/index.js +30 -4
- package/plugin-src/client/i18n.js +59 -0
- package/plugin-src/client/styles.js +8 -0
- package/plugin-src/host/channels/dingtalk/production.mjs +10 -4
- package/plugin-src/host/channels/dingtalk/rpc.mjs +12 -0
- package/plugin-src/host/channels/feishu/connection-supervisor.mjs +1 -1
- package/plugin-src/host/channels/feishu/production.mjs +8 -3
- package/plugin-src/host/channels/feishu/rpc.mjs +78 -7
- package/plugin-src/host/channels/qq/production.mjs +10 -4
- package/plugin-src/host/channels/qq/rpc.mjs +12 -0
- package/plugin-src/host/channels/shared/agent-preset-rpc.mjs +25 -0
- package/plugin-src/host/channels/shared/production.mjs +10 -4
- package/plugin-src/host/channels/shared/rpc.mjs +12 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +2 -0
- package/plugin-src/host/channels/slack/production.mjs +10 -4
- package/plugin-src/host/channels/slack/rpc.mjs +13 -0
- package/plugin-src/host/channels/wecom/production.mjs +10 -4
- package/plugin-src/host/channels/wecom/rpc.mjs +12 -0
- package/plugin-src/host/channels/weixin/production.mjs +10 -4
- package/plugin-src/host/channels/weixin/rpc.mjs +15 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +10 -4
- package/plugin-src/host/channels/whatsapp/rpc.mjs +12 -0
- package/src/channels/discord/discord-api.mjs +1 -1
- package/src/channels/feishu/bridge.mjs +29 -4
- package/src/channels/feishu/feishu-runtime.mjs +14 -0
- package/src/channels/feishu/group-message-permission-manager.mjs +71 -0
- package/src/channels/feishu/group-response-mode.mjs +15 -0
- package/src/channels/feishu/multi-bot-controller.mjs +258 -9
- package/src/channels/feishu/plugin-config-store.mjs +3 -0
- package/src/channels/feishu/repair-manager.mjs +17 -3
- package/src/channels/shared/agent-preset.mjs +74 -0
- package/src/channels/shared/bot-workspace-store.mjs +141 -14
- package/src/channels/shared/harness-client.mjs +6 -4
- package/src/channels/telegram/telegram-api.mjs +31 -0
- package/src/channels/telegram/telegram-runtime.mjs +25 -1
- package/src/channels/weixin/weixin-api.mjs +1 -1
package/lib/client.js
CHANGED
|
@@ -40,7 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
name: () => name
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(index_exports);
|
|
43
|
-
var
|
|
43
|
+
var React19 = __toESM(require("react"), 1);
|
|
44
44
|
|
|
45
45
|
// plugin-src/client/channel-logos.js
|
|
46
46
|
var React = __toESM(require("react"), 1);
|
|
@@ -186,207 +186,7 @@ function OfficeLogoGlyph({ size } = {}) {
|
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
// plugin-src/client/
|
|
190
|
-
var DINGTALK_RPC_CHANNEL = "/dingtalk";
|
|
191
|
-
var DINGTALK_ENDPOINTS = Object.freeze({
|
|
192
|
-
status: "connection.status",
|
|
193
|
-
beginProvisioning: "provision.begin",
|
|
194
|
-
pollProvisioning: "provision.poll",
|
|
195
|
-
cancelProvisioning: "provision.cancel",
|
|
196
|
-
bindCredentials: "bot.bind-credentials",
|
|
197
|
-
reconnectBot: "bot.reconnect",
|
|
198
|
-
deleteBot: "bot.delete",
|
|
199
|
-
setWorkspace: "bot.workspace.set"
|
|
200
|
-
});
|
|
201
|
-
var ACCOUNT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
202
|
-
var SNAPSHOT_STATES = /* @__PURE__ */ new Set(["disconnected", "offline", "provisioning", "connected", "degraded"]);
|
|
203
|
-
var PROVISION_STATES = /* @__PURE__ */ new Set([
|
|
204
|
-
"starting",
|
|
205
|
-
"pending",
|
|
206
|
-
"scanned",
|
|
207
|
-
"authorizing",
|
|
208
|
-
"creating",
|
|
209
|
-
"connecting",
|
|
210
|
-
"connected",
|
|
211
|
-
"expired",
|
|
212
|
-
"failed",
|
|
213
|
-
"cancelled"
|
|
214
|
-
]);
|
|
215
|
-
var HEALTH_STATES = /* @__PURE__ */ new Set(["healthy", "checking", "degraded", "offline"]);
|
|
216
|
-
var FORBIDDEN_ERROR_FIELDS = /(client[_-]?secret|secret[_-]?ref|device[_-]?code|app[_-]?secret|access[_-]?token|token)/i;
|
|
217
|
-
var QR_DATA_URL = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
218
|
-
var MAX_QR_SOURCE_LENGTH = 2 * 1024 * 1024;
|
|
219
|
-
function isRecord(value) {
|
|
220
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
221
|
-
}
|
|
222
|
-
function optionalString(value, maxLength = 240) {
|
|
223
|
-
if (typeof value !== "string") return void 0;
|
|
224
|
-
const trimmed = value.trim();
|
|
225
|
-
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
226
|
-
}
|
|
227
|
-
function opaqueId(value) {
|
|
228
|
-
const id5 = optionalString(value, 128);
|
|
229
|
-
return id5 && /^[a-z\d_-]+$/i.test(id5) ? id5 : void 0;
|
|
230
|
-
}
|
|
231
|
-
function timestamp(value) {
|
|
232
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
233
|
-
if (typeof value === "string" && value.trim()) {
|
|
234
|
-
const parsed = Date.parse(value);
|
|
235
|
-
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
236
|
-
}
|
|
237
|
-
return void 0;
|
|
238
|
-
}
|
|
239
|
-
function nonNegativeInteger(value) {
|
|
240
|
-
const number = Number(value);
|
|
241
|
-
return Number.isSafeInteger(number) && number >= 0 ? number : 0;
|
|
242
|
-
}
|
|
243
|
-
function clamp(value, min, max, fallback) {
|
|
244
|
-
const number = Number(value);
|
|
245
|
-
return Number.isFinite(number) ? Math.min(max, Math.max(min, number)) : fallback;
|
|
246
|
-
}
|
|
247
|
-
function safeErrorCode(value, fallback) {
|
|
248
|
-
const code = optionalString(value, 80);
|
|
249
|
-
return code && /^[a-z][a-z\d_.:-]*$/i.test(code) && !FORBIDDEN_ERROR_FIELDS.test(code) ? code : fallback;
|
|
250
|
-
}
|
|
251
|
-
function sanitizeMessage(value, fallback) {
|
|
252
|
-
const message = optionalString(value, 480) ?? fallback;
|
|
253
|
-
if (FORBIDDEN_ERROR_FIELDS.test(message)) return fallback;
|
|
254
|
-
return message.replace(/([=:]\s*)[^\s,;,。]+/g, "$1\u2022\u2022\u2022\u2022\u2022\u2022").slice(0, 240);
|
|
255
|
-
}
|
|
256
|
-
function normalizeError(value, fallbackCode, fallbackMessage) {
|
|
257
|
-
if (!isRecord(value)) return void 0;
|
|
258
|
-
return {
|
|
259
|
-
code: safeErrorCode(value.code, fallbackCode),
|
|
260
|
-
message: sanitizeMessage(value.message, fallbackMessage)
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function normalizeTestMessage(value) {
|
|
264
|
-
if (!isRecord(value)) return null;
|
|
265
|
-
if (value.sent === true) return { sent: true };
|
|
266
|
-
if (value.sent !== false) return null;
|
|
267
|
-
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
268
|
-
return { sent: false, code };
|
|
269
|
-
}
|
|
270
|
-
function unwrapRpcResult(result) {
|
|
271
|
-
if (!isRecord(result) || typeof result.ok !== "boolean") {
|
|
272
|
-
throw new Error("\u9489\u9489\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
273
|
-
}
|
|
274
|
-
if (!result.ok) {
|
|
275
|
-
const error = new Error(sanitizeMessage(result.error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25"));
|
|
276
|
-
error.code = safeErrorCode(result.error?.code, "DINGTALK_RPC_ERROR");
|
|
277
|
-
throw error;
|
|
278
|
-
}
|
|
279
|
-
return result.value;
|
|
280
|
-
}
|
|
281
|
-
function safeQrSource(value) {
|
|
282
|
-
if (typeof value !== "string" || value.length > MAX_QR_SOURCE_LENGTH) return void 0;
|
|
283
|
-
return QR_DATA_URL.test(value) ? value : void 0;
|
|
284
|
-
}
|
|
285
|
-
function normalizeProvisioning(value, now = Date.now()) {
|
|
286
|
-
const source = isRecord(value?.provisioning) ? value.provisioning : value;
|
|
287
|
-
if (!isRecord(source)) throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6");
|
|
288
|
-
const attemptId = opaqueId(source.attemptId);
|
|
289
|
-
if (!attemptId) throw new Error("\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
290
|
-
const reportedStatus = optionalString(source.status, 32) ?? optionalString(source.state, 32);
|
|
291
|
-
const status = PROVISION_STATES.has(reportedStatus) ? reportedStatus : "failed";
|
|
292
|
-
const expiresAt = timestamp(source.expiresAt) ?? now + clamp(source.expiresIn, 1, 2 * 60 * 60, 10 * 60) * 1e3;
|
|
293
|
-
const result = {
|
|
294
|
-
attemptId,
|
|
295
|
-
status,
|
|
296
|
-
expiresAt,
|
|
297
|
-
pollIntervalMs: clamp(source.pollIntervalMs, 1e3, 1e4, 3e3)
|
|
298
|
-
};
|
|
299
|
-
const qrCodeDataUrl = safeQrSource(source.qrCodeDataUrl);
|
|
300
|
-
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
301
|
-
if (opaqueId(source.botId)) result.botId = opaqueId(source.botId);
|
|
302
|
-
if (source.alreadyConnected === true) result.alreadyConnected = true;
|
|
303
|
-
const error = normalizeError(
|
|
304
|
-
source.error,
|
|
305
|
-
"DINGTALK_PROVISION_FAILED",
|
|
306
|
-
"\u9489\u9489\u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210"
|
|
307
|
-
);
|
|
308
|
-
if (error) result.error = error;
|
|
309
|
-
return result;
|
|
310
|
-
}
|
|
311
|
-
function normalizeBot(value) {
|
|
312
|
-
if (!isRecord(value)) return void 0;
|
|
313
|
-
const botId = opaqueId(value.botId);
|
|
314
|
-
if (!botId) return void 0;
|
|
315
|
-
const bot = isRecord(value.bot) ? value.bot : {};
|
|
316
|
-
const connected = value.connected === true;
|
|
317
|
-
const reportedState = ACCOUNT_STATES.has(value.state) ? value.state : "offline";
|
|
318
|
-
const state = connected ? "connected" : reportedState === "connected" ? "connecting" : reportedState;
|
|
319
|
-
const health = isRecord(value.health) ? value.health : {};
|
|
320
|
-
const stats = isRecord(value.stats) ? value.stats : {};
|
|
321
|
-
return {
|
|
322
|
-
botId,
|
|
323
|
-
state,
|
|
324
|
-
connected,
|
|
325
|
-
configured: value.configured !== false,
|
|
326
|
-
workspace: optionalString(value.workspace, 4096) ?? "",
|
|
327
|
-
bot: {
|
|
328
|
-
name: optionalString(bot.name, 100) ?? "\u9489\u9489\u673A\u5668\u4EBA",
|
|
329
|
-
clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? "\u5DF2\u5B89\u5168\u4FDD\u5B58"
|
|
330
|
-
},
|
|
331
|
-
health: {
|
|
332
|
-
status: HEALTH_STATES.has(health.status) ? health.status : connected ? "healthy" : "offline",
|
|
333
|
-
summary: optionalString(health.summary, 200) ?? (connected ? "\u9489\u9489 Stream \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
334
|
-
lastCheckedAt: timestamp(health.lastCheckedAt),
|
|
335
|
-
lastConnectedAt: timestamp(health.lastConnectedAt)
|
|
336
|
-
},
|
|
337
|
-
stats: {
|
|
338
|
-
messagesReceived: nonNegativeInteger(stats.messagesReceived),
|
|
339
|
-
messagesReplied: nonNegativeInteger(stats.messagesReplied)
|
|
340
|
-
},
|
|
341
|
-
error: normalizeError(value.error, "DINGTALK_ACCOUNT_ERROR", "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA") ?? null
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
function normalizeSnapshot(value) {
|
|
345
|
-
const source = isRecord(value?.snapshot) ? value.snapshot : value;
|
|
346
|
-
if (!isRecord(source) || !Array.isArray(source.bots)) {
|
|
347
|
-
throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
348
|
-
}
|
|
349
|
-
const seen = /* @__PURE__ */ new Set();
|
|
350
|
-
const bots = source.bots.map(normalizeBot).filter((bot) => {
|
|
351
|
-
if (!bot || seen.has(bot.botId)) return false;
|
|
352
|
-
seen.add(bot.botId);
|
|
353
|
-
return true;
|
|
354
|
-
});
|
|
355
|
-
return {
|
|
356
|
-
schemaVersion: Number.isSafeInteger(source.schemaVersion) ? source.schemaVersion : 1,
|
|
357
|
-
revision: nonNegativeInteger(source.revision),
|
|
358
|
-
state: SNAPSHOT_STATES.has(source.state) ? source.state : "offline",
|
|
359
|
-
bots,
|
|
360
|
-
totals: {
|
|
361
|
-
configured: bots.length,
|
|
362
|
-
connected: bots.filter((bot) => bot.connected).length
|
|
363
|
-
},
|
|
364
|
-
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
365
|
-
testMessage: normalizeTestMessage(source.testMessage)
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
function connectionTestFeedback(result) {
|
|
369
|
-
if (result?.sent === true) return "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002";
|
|
370
|
-
if (result?.code === "test-target-unavailable") {
|
|
371
|
-
return "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002";
|
|
372
|
-
}
|
|
373
|
-
return result ? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
374
|
-
}
|
|
375
|
-
function presentError(error) {
|
|
376
|
-
return {
|
|
377
|
-
code: safeErrorCode(error?.code, "DINGTALK_ERROR"),
|
|
378
|
-
message: sanitizeMessage(error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function formatRemaining(milliseconds) {
|
|
382
|
-
const seconds = Math.max(0, Math.ceil(Number(milliseconds) / 1e3) || 0);
|
|
383
|
-
return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// plugin-src/client/channels/dingtalk/index.js
|
|
387
|
-
var React7 = __toESM(require("react"), 1);
|
|
388
|
-
|
|
389
|
-
// plugin-src/client/credential-binding.js
|
|
189
|
+
// plugin-src/client/agent-preset.js
|
|
390
190
|
var React3 = __toESM(require("react"), 1);
|
|
391
191
|
|
|
392
192
|
// plugin-src/client/i18n.js
|
|
@@ -458,6 +258,24 @@ var EN = Object.freeze({
|
|
|
458
258
|
"WhatsApp\u8D26\u53F7": "WhatsApp account",
|
|
459
259
|
"\u5FAE\u4FE1\u8BBE\u7F6E": "WeChat settings",
|
|
460
260
|
"\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E": "Feishu bot settings",
|
|
261
|
+
"\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F": "Group response mode",
|
|
262
|
+
"\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09": "Only respond when @mentioned (recommended)",
|
|
263
|
+
"\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F": "Respond to all group messages",
|
|
264
|
+
"\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\uFF08\u9700\u98DE\u4E66\u654F\u611F\u6743\u9650\uFF09": "Respond to all group messages (requires a sensitive Feishu scope)",
|
|
265
|
+
"\u91CD\u65B0\u6388\u6743": "Reauthorize",
|
|
266
|
+
"\u53BB\u6388\u6743": "Authorize",
|
|
267
|
+
"\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650": "Reauthorize group-message permission",
|
|
268
|
+
"\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650": "Authorize group-message permission",
|
|
269
|
+
"\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026": "Preparing authorization\u2026",
|
|
270
|
+
"\u6B63\u5728\u51C6\u5907\u2026": "Preparing\u2026",
|
|
271
|
+
"\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002": "Direct messages always work; group chats require an explicit @mention of this bot. The group-message permission is already granted, so switching again needs no authorization.",
|
|
272
|
+
"\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002": "Direct messages always work; group chats require an explicit @mention of this bot. Selecting all messages opens the official Feishu authorization flow.",
|
|
273
|
+
"\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002": "The \u201CRead all messages in associated group chat\u201D scope (im:message.group_msg) is granted; the bot processes every visible group message.",
|
|
274
|
+
"\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002": "The \u201CRead all messages in associated group chat\u201D scope has not been confirmed. Complete Feishu authorization.",
|
|
275
|
+
"\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002": "Direct messages always work; group chats require an explicit @mention of this bot.",
|
|
276
|
+
"\u9700\u5728\u98DE\u4E66\u4E3A\u8BE5\u673A\u5668\u4EBA\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u5F00\u901A\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002": "Grant this bot the \u201CRead all messages in associated group chat\u201D Feishu scope (im:message.group_msg); once granted, it will process every visible group message.",
|
|
277
|
+
"\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the group response mode. Try again.",
|
|
278
|
+
"\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not authorize group-message permission. Try again.",
|
|
461
279
|
"\u9489\u9489\u8BBE\u7F6E": "DingTalk settings",
|
|
462
280
|
"\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E": "WeCom settings",
|
|
463
281
|
"\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA": "Scan QR code",
|
|
@@ -507,6 +325,15 @@ var EN = Object.freeze({
|
|
|
507
325
|
"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002": "The workspace path does not exist.",
|
|
508
326
|
"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002": "The workspace path must point to a directory.",
|
|
509
327
|
"\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002": "The bot could not be found.",
|
|
328
|
+
"Agent Preset": "Agent Preset",
|
|
329
|
+
"\u8DDF\u968F Host \u9ED8\u8BA4": "Follow the Host default",
|
|
330
|
+
"\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09": " (unavailable)",
|
|
331
|
+
"\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": "This affects only new sessions. If the current chat already has a session, send /new, then send a regular message to apply it.",
|
|
332
|
+
"\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002": "The current Agent Preset is unavailable. Choose another preset or follow the Host default.",
|
|
333
|
+
"Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the Agent Preset. Try again.",
|
|
334
|
+
"\u8BF7\u9009\u62E9 Agent Preset\u3002": "Choose an Agent Preset.",
|
|
335
|
+
"Agent Preset \u65E0\u6548\u3002": "The Agent Preset is invalid.",
|
|
336
|
+
"Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002": "The Agent Preset does not exist or is unavailable.",
|
|
510
337
|
"\u5C1A\u672A\u68C0\u67E5": "Not checked yet",
|
|
511
338
|
"\u521A\u521A": "Just now",
|
|
512
339
|
"\u68C0\u67E5\u8FDE\u63A5": "Check connection",
|
|
@@ -571,6 +398,7 @@ var EN = Object.freeze({
|
|
|
571
398
|
"\u751F\u6210 QQ \u4E8C\u7EF4\u7801": "Generate QQ QR code",
|
|
572
399
|
"\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026": "Generating QR code\u2026",
|
|
573
400
|
"\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801": "Preparing authorization QR code",
|
|
401
|
+
"\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801": "Preparing permission authorization QR code",
|
|
574
402
|
"\u6B63\u5728\u51C6\u5907\u5FAE\u4FE1\u4E8C\u7EF4\u7801": "Preparing WeChat QR code",
|
|
575
403
|
"\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA": "Adding a new bot",
|
|
576
404
|
"\u6B63\u5728\u7533\u8BF7\u9489\u9489\u6388\u6743\u4E8C\u7EF4\u7801\u2026": "Requesting DingTalk authorization QR code\u2026",
|
|
@@ -588,6 +416,16 @@ var EN = Object.freeze({
|
|
|
588
416
|
"\u5728\u98DE\u4E66\u4E2D\u6253\u5F00": "Open in Feishu",
|
|
589
417
|
"\u53D6\u6D88\u6DFB\u52A0": "Cancel",
|
|
590
418
|
"\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Scan with Feishu to repair card buttons",
|
|
419
|
+
"\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650": "Confirm group-message permission with Feishu",
|
|
420
|
+
"\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the \u201CRead all messages in associated group chat\u201D scope. It does not create a new app. After confirmation, \u201CRespond to all group messages\u201D is enabled automatically; other bots are unaffected.",
|
|
421
|
+
"\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650": "Review the existing app and confirm the \u201CRead all messages in associated group chat\u201D permission",
|
|
422
|
+
"\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F": "Keep this page open while the permission takes effect and the response mode switches automatically",
|
|
423
|
+
"\u53D6\u6D88\u6388\u6743": "Cancel authorization",
|
|
424
|
+
"\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F": "Confirmed. Enabling all-message mode",
|
|
425
|
+
"\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The permission update was submitted. Saving the setting and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
|
|
426
|
+
"\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
|
|
427
|
+
"\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a group-message permission QR code for the existing Feishu app\u2026",
|
|
428
|
+
"\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210": "Group-message permission was not granted",
|
|
591
429
|
"\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the card-button callback. It does not create a new app. This bot reconnects briefly after confirmation; other bots are not affected.",
|
|
592
430
|
"\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03": "Review the existing app name and confirm that only the card callback is added",
|
|
593
431
|
"\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210": "Keep this page open until card-button repair finishes",
|
|
@@ -600,14 +438,25 @@ var EN = Object.freeze({
|
|
|
600
438
|
"\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Repair card buttons",
|
|
601
439
|
"\u7B49\u5F85\u626B\u7801\u2026": "Waiting for scan\u2026",
|
|
602
440
|
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801": "Feishu returned a repair QR code for a different bot",
|
|
441
|
+
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801": "Feishu returned a group-message permission QR code for a different bot",
|
|
603
442
|
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu repair status is missing the bot ID",
|
|
443
|
+
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu app-update status is missing the bot ID",
|
|
604
444
|
"\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6": "Feishu returned registration progress for a different operation",
|
|
605
445
|
"\u6B64\u673A\u5668\u4EBA": "this bot",
|
|
446
|
+
"\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801": "One-time QR code for granting group-message permission to ${botName}",
|
|
447
|
+
"\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650": "Granting group-message permission to \u201C${botName}\u201D",
|
|
606
448
|
'${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002': 'Repair QR code generated for ${botName ?? "bot"}. Scan it with Feishu.',
|
|
449
|
+
'${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002': 'Group-message permission QR code generated for ${botName ?? "bot"}. Confirm it with Feishu.',
|
|
450
|
+
"${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBotName} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
|
|
451
|
+
"${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBot.bot.name} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
|
|
607
452
|
"${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002": "${targetBot.bot.name} is connected and ready to chat in Feishu.",
|
|
608
453
|
"\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002": "Card-button repair was cancelled.",
|
|
454
|
+
"\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002": "Group-message permission authorization was cancelled.",
|
|
609
455
|
"\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The card callback was updated, but the bot connection could not be confirmed yet",
|
|
456
|
+
"\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The group-message permission was updated, but the bot connection could not be confirmed yet",
|
|
610
457
|
"\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25": "Could not repair the Feishu card buttons",
|
|
458
|
+
"\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25": "Could not grant the Feishu group-message permission",
|
|
459
|
+
"\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002": "Finish the current Feishu authorization before granting group-message permission.",
|
|
611
460
|
"\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA": "Confirmed. Connecting the new bot",
|
|
612
461
|
"\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "Saving credentials and checking the new bot connection. Existing bots will not be interrupted.",
|
|
613
462
|
"\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a one-time authorization QR code from Feishu\u2026",
|
|
@@ -900,16 +749,26 @@ function translateDynamic(text5) {
|
|
|
900
749
|
if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
|
|
901
750
|
match = /^从 DeepSeek Harness 移除(.+)$/.exec(text5);
|
|
902
751
|
if (match) return `Remove ${match[1]} from DeepSeek Harness`;
|
|
752
|
+
match = /^(.+)的飞书授权流程$/.exec(text5);
|
|
753
|
+
if (match) return `Feishu authorization flow for ${match[1]}`;
|
|
903
754
|
match = /^用于修复(.+)卡片按钮的一次性授权二维码$/.exec(text5);
|
|
904
755
|
if (match) return `One-time QR code for repairing card buttons for ${match[1]}`;
|
|
756
|
+
match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text5);
|
|
757
|
+
if (match) return `One-time QR code for granting group-message permission to ${match[1]}`;
|
|
905
758
|
match = /^正在修复「(.+)」$/.exec(text5);
|
|
906
759
|
if (match) return `Repairing \u201C${match[1]}\u201D`;
|
|
760
|
+
match = /^正在为「(.+)」开通群消息权限$/.exec(text5);
|
|
761
|
+
if (match) return `Granting group-message permission to \u201C${match[1]}\u201D`;
|
|
907
762
|
match = /^修复(.+)的卡片按钮$/.exec(text5);
|
|
908
763
|
if (match) return `Repair card buttons for ${match[1]}`;
|
|
909
764
|
match = /^(.+)的修复二维码已生成,请使用飞书扫码。$/.exec(text5);
|
|
910
765
|
if (match) return `Repair QR code generated for ${match[1]}. Scan it with Feishu.`;
|
|
766
|
+
match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text5);
|
|
767
|
+
if (match) return `Group-message permission QR code generated for ${match[1]}. Confirm it with Feishu.`;
|
|
911
768
|
match = /^(.+)的卡片按钮已修复。$/.exec(text5);
|
|
912
769
|
if (match) return `Card buttons repaired for ${match[1]}.`;
|
|
770
|
+
match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text5);
|
|
771
|
+
if (match) return `${match[1]} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.`;
|
|
913
772
|
match = /^(检查连接|重试连接)(.+)$/.exec(text5);
|
|
914
773
|
if (match) return `${localizeText(match[1])} ${match[2]}`;
|
|
915
774
|
match = /^移除(.+)$/.exec(text5);
|
|
@@ -975,37 +834,340 @@ function translateDynamic(text5) {
|
|
|
975
834
|
for (const [source, target] of phrases) output = output.replaceAll(source, target);
|
|
976
835
|
return output;
|
|
977
836
|
}
|
|
978
|
-
function localizeText(value) {
|
|
979
|
-
if (typeof value !== "string") return value;
|
|
980
|
-
const exact = translate(value);
|
|
981
|
-
if (exact !== value || !isEnglish()) return exact;
|
|
982
|
-
return translateDynamic(value);
|
|
837
|
+
function localizeText(value) {
|
|
838
|
+
if (typeof value !== "string") return value;
|
|
839
|
+
const exact = translate(value);
|
|
840
|
+
if (exact !== value || !isEnglish()) return exact;
|
|
841
|
+
return translateDynamic(value);
|
|
842
|
+
}
|
|
843
|
+
var LOCALIZED_PROPS = Object.freeze([
|
|
844
|
+
"aria-label",
|
|
845
|
+
"alt",
|
|
846
|
+
"placeholder",
|
|
847
|
+
"title"
|
|
848
|
+
]);
|
|
849
|
+
function localizeChild(child) {
|
|
850
|
+
if (typeof child === "string") return localizeText(child);
|
|
851
|
+
if (Array.isArray(child)) return child.map(localizeChild);
|
|
852
|
+
return child;
|
|
853
|
+
}
|
|
854
|
+
function h2(type, props, ...children) {
|
|
855
|
+
let localizedProps = props;
|
|
856
|
+
if (props) {
|
|
857
|
+
for (const key of LOCALIZED_PROPS) {
|
|
858
|
+
if (typeof props[key] === "string") {
|
|
859
|
+
localizedProps = localizedProps === props ? { ...props } : localizedProps;
|
|
860
|
+
localizedProps[key] = localizeText(props[key]);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return React2.createElement(type, localizedProps, ...children.map(localizeChild));
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// plugin-src/client/agent-preset.js
|
|
868
|
+
var SET_AGENT_PRESET_ENDPOINT = "bot.preset.set";
|
|
869
|
+
var PRESET_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
870
|
+
var EMPTY_AGENT_PRESET_CATALOG = Object.freeze({
|
|
871
|
+
defaultId: "",
|
|
872
|
+
items: Object.freeze([])
|
|
873
|
+
});
|
|
874
|
+
var AgentPresetCatalogContext = React3.createContext(EMPTY_AGENT_PRESET_CATALOG);
|
|
875
|
+
function normalizeAgentPresetId(value) {
|
|
876
|
+
if (typeof value !== "string") return "";
|
|
877
|
+
const id5 = value.trim();
|
|
878
|
+
return PRESET_ID.test(id5) ? id5 : "";
|
|
879
|
+
}
|
|
880
|
+
function normalizeAgentPresetCatalog(value) {
|
|
881
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
882
|
+
return { defaultId: "", items: [] };
|
|
883
|
+
}
|
|
884
|
+
const items = [];
|
|
885
|
+
const seen = /* @__PURE__ */ new Set();
|
|
886
|
+
for (const entry of Array.isArray(value.items) ? value.items : []) {
|
|
887
|
+
const id5 = typeof entry === "string" ? normalizeAgentPresetId(entry) : normalizeAgentPresetId(entry?.id);
|
|
888
|
+
if (!id5 || seen.has(id5)) continue;
|
|
889
|
+
seen.add(id5);
|
|
890
|
+
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) : id5;
|
|
891
|
+
items.push({ id: id5, label });
|
|
892
|
+
}
|
|
893
|
+
return {
|
|
894
|
+
defaultId: normalizeAgentPresetId(value.defaultId),
|
|
895
|
+
items
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
|
|
899
|
+
const catalog = React3.useContext(AgentPresetCatalogContext) ?? EMPTY_AGENT_PRESET_CATALOG;
|
|
900
|
+
const current = normalizeAgentPresetId(agentPreset);
|
|
901
|
+
const [saving, setSaving] = React3.useState(false);
|
|
902
|
+
const [error, setError] = React3.useState(null);
|
|
903
|
+
const items = [];
|
|
904
|
+
const seen = /* @__PURE__ */ new Set();
|
|
905
|
+
for (const item of Array.isArray(catalog.items) ? catalog.items : []) {
|
|
906
|
+
if (!item?.id || seen.has(item.id)) continue;
|
|
907
|
+
seen.add(item.id);
|
|
908
|
+
items.push(item);
|
|
909
|
+
}
|
|
910
|
+
const currentUnavailable = Boolean(current && !seen.has(current));
|
|
911
|
+
if (currentUnavailable) items.push({ id: current, label: current, unavailable: true });
|
|
912
|
+
const inheritLabel = "\u8DDF\u968F Host \u9ED8\u8BA4";
|
|
913
|
+
const change = async (event) => {
|
|
914
|
+
const next = event.target.value;
|
|
915
|
+
if (next === current || saving || disabled) return;
|
|
916
|
+
setSaving(true);
|
|
917
|
+
setError(null);
|
|
918
|
+
try {
|
|
919
|
+
await onSave?.(next || null);
|
|
920
|
+
} catch (cause) {
|
|
921
|
+
setError(cause?.message ?? "Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
922
|
+
} finally {
|
|
923
|
+
setSaving(false);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
return h2(
|
|
927
|
+
"div",
|
|
928
|
+
{ className: "dim-preset" },
|
|
929
|
+
h2(
|
|
930
|
+
"div",
|
|
931
|
+
{ className: "dim-presetHeader" },
|
|
932
|
+
h2("span", null, "Agent Preset"),
|
|
933
|
+
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
934
|
+
),
|
|
935
|
+
React3.createElement(
|
|
936
|
+
"select",
|
|
937
|
+
{
|
|
938
|
+
className: "dim-presetSelect",
|
|
939
|
+
value: current,
|
|
940
|
+
disabled: disabled || saving,
|
|
941
|
+
"aria-label": "Agent Preset",
|
|
942
|
+
onChange: (event) => {
|
|
943
|
+
void change(event);
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
h2("option", { value: "" }, inheritLabel),
|
|
947
|
+
...items.map((item) => h2(
|
|
948
|
+
"option",
|
|
949
|
+
{ key: item.id, value: item.id },
|
|
950
|
+
item.unavailable ? [item.id, "\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09"] : item.label && item.label !== item.id ? `${item.label}\uFF08${item.id}\uFF09` : item.id
|
|
951
|
+
))
|
|
952
|
+
),
|
|
953
|
+
h2(
|
|
954
|
+
"small",
|
|
955
|
+
{ className: "dim-presetHelp" },
|
|
956
|
+
"\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"
|
|
957
|
+
),
|
|
958
|
+
error || currentUnavailable ? h2(
|
|
959
|
+
"p",
|
|
960
|
+
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
|
961
|
+
error ?? "\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002"
|
|
962
|
+
) : null
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// plugin-src/client/channels/dingtalk/api.js
|
|
967
|
+
var DINGTALK_RPC_CHANNEL = "/dingtalk";
|
|
968
|
+
var DINGTALK_ENDPOINTS = Object.freeze({
|
|
969
|
+
status: "connection.status",
|
|
970
|
+
beginProvisioning: "provision.begin",
|
|
971
|
+
pollProvisioning: "provision.poll",
|
|
972
|
+
cancelProvisioning: "provision.cancel",
|
|
973
|
+
bindCredentials: "bot.bind-credentials",
|
|
974
|
+
reconnectBot: "bot.reconnect",
|
|
975
|
+
deleteBot: "bot.delete",
|
|
976
|
+
setWorkspace: "bot.workspace.set",
|
|
977
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
978
|
+
});
|
|
979
|
+
var ACCOUNT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
980
|
+
var SNAPSHOT_STATES = /* @__PURE__ */ new Set(["disconnected", "offline", "provisioning", "connected", "degraded"]);
|
|
981
|
+
var PROVISION_STATES = /* @__PURE__ */ new Set([
|
|
982
|
+
"starting",
|
|
983
|
+
"pending",
|
|
984
|
+
"scanned",
|
|
985
|
+
"authorizing",
|
|
986
|
+
"creating",
|
|
987
|
+
"connecting",
|
|
988
|
+
"connected",
|
|
989
|
+
"expired",
|
|
990
|
+
"failed",
|
|
991
|
+
"cancelled"
|
|
992
|
+
]);
|
|
993
|
+
var HEALTH_STATES = /* @__PURE__ */ new Set(["healthy", "checking", "degraded", "offline"]);
|
|
994
|
+
var FORBIDDEN_ERROR_FIELDS = /(client[_-]?secret|secret[_-]?ref|device[_-]?code|app[_-]?secret|access[_-]?token|token)/i;
|
|
995
|
+
var QR_DATA_URL = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
996
|
+
var MAX_QR_SOURCE_LENGTH = 2 * 1024 * 1024;
|
|
997
|
+
function isRecord(value) {
|
|
998
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
999
|
+
}
|
|
1000
|
+
function optionalString(value, maxLength = 240) {
|
|
1001
|
+
if (typeof value !== "string") return void 0;
|
|
1002
|
+
const trimmed = value.trim();
|
|
1003
|
+
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
1004
|
+
}
|
|
1005
|
+
function opaqueId(value) {
|
|
1006
|
+
const id5 = optionalString(value, 128);
|
|
1007
|
+
return id5 && /^[a-z\d_-]+$/i.test(id5) ? id5 : void 0;
|
|
1008
|
+
}
|
|
1009
|
+
function timestamp(value) {
|
|
1010
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
1011
|
+
if (typeof value === "string" && value.trim()) {
|
|
1012
|
+
const parsed = Date.parse(value);
|
|
1013
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
1014
|
+
}
|
|
1015
|
+
return void 0;
|
|
1016
|
+
}
|
|
1017
|
+
function nonNegativeInteger(value) {
|
|
1018
|
+
const number = Number(value);
|
|
1019
|
+
return Number.isSafeInteger(number) && number >= 0 ? number : 0;
|
|
1020
|
+
}
|
|
1021
|
+
function clamp(value, min, max, fallback) {
|
|
1022
|
+
const number = Number(value);
|
|
1023
|
+
return Number.isFinite(number) ? Math.min(max, Math.max(min, number)) : fallback;
|
|
1024
|
+
}
|
|
1025
|
+
function safeErrorCode(value, fallback) {
|
|
1026
|
+
const code = optionalString(value, 80);
|
|
1027
|
+
return code && /^[a-z][a-z\d_.:-]*$/i.test(code) && !FORBIDDEN_ERROR_FIELDS.test(code) ? code : fallback;
|
|
1028
|
+
}
|
|
1029
|
+
function sanitizeMessage(value, fallback) {
|
|
1030
|
+
const message = optionalString(value, 480) ?? fallback;
|
|
1031
|
+
if (FORBIDDEN_ERROR_FIELDS.test(message)) return fallback;
|
|
1032
|
+
return message.replace(/([=:]\s*)[^\s,;,。]+/g, "$1\u2022\u2022\u2022\u2022\u2022\u2022").slice(0, 240);
|
|
1033
|
+
}
|
|
1034
|
+
function normalizeError(value, fallbackCode, fallbackMessage) {
|
|
1035
|
+
if (!isRecord(value)) return void 0;
|
|
1036
|
+
return {
|
|
1037
|
+
code: safeErrorCode(value.code, fallbackCode),
|
|
1038
|
+
message: sanitizeMessage(value.message, fallbackMessage)
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
function normalizeTestMessage(value) {
|
|
1042
|
+
if (!isRecord(value)) return null;
|
|
1043
|
+
if (value.sent === true) return { sent: true };
|
|
1044
|
+
if (value.sent !== false) return null;
|
|
1045
|
+
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
1046
|
+
return { sent: false, code };
|
|
1047
|
+
}
|
|
1048
|
+
function unwrapRpcResult(result) {
|
|
1049
|
+
if (!isRecord(result) || typeof result.ok !== "boolean") {
|
|
1050
|
+
throw new Error("\u9489\u9489\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
1051
|
+
}
|
|
1052
|
+
if (!result.ok) {
|
|
1053
|
+
const error = new Error(sanitizeMessage(result.error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25"));
|
|
1054
|
+
error.code = safeErrorCode(result.error?.code, "DINGTALK_RPC_ERROR");
|
|
1055
|
+
throw error;
|
|
1056
|
+
}
|
|
1057
|
+
return result.value;
|
|
983
1058
|
}
|
|
984
|
-
|
|
985
|
-
"
|
|
986
|
-
|
|
987
|
-
"placeholder",
|
|
988
|
-
"title"
|
|
989
|
-
]);
|
|
990
|
-
function localizeChild(child) {
|
|
991
|
-
if (typeof child === "string") return localizeText(child);
|
|
992
|
-
if (Array.isArray(child)) return child.map(localizeChild);
|
|
993
|
-
return child;
|
|
1059
|
+
function safeQrSource(value) {
|
|
1060
|
+
if (typeof value !== "string" || value.length > MAX_QR_SOURCE_LENGTH) return void 0;
|
|
1061
|
+
return QR_DATA_URL.test(value) ? value : void 0;
|
|
994
1062
|
}
|
|
995
|
-
function
|
|
996
|
-
|
|
997
|
-
if (
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1063
|
+
function normalizeProvisioning(value, now = Date.now()) {
|
|
1064
|
+
const source = isRecord(value?.provisioning) ? value.provisioning : value;
|
|
1065
|
+
if (!isRecord(source)) throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6");
|
|
1066
|
+
const attemptId = opaqueId(source.attemptId);
|
|
1067
|
+
if (!attemptId) throw new Error("\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
1068
|
+
const reportedStatus = optionalString(source.status, 32) ?? optionalString(source.state, 32);
|
|
1069
|
+
const status = PROVISION_STATES.has(reportedStatus) ? reportedStatus : "failed";
|
|
1070
|
+
const expiresAt = timestamp(source.expiresAt) ?? now + clamp(source.expiresIn, 1, 2 * 60 * 60, 10 * 60) * 1e3;
|
|
1071
|
+
const result = {
|
|
1072
|
+
attemptId,
|
|
1073
|
+
status,
|
|
1074
|
+
expiresAt,
|
|
1075
|
+
pollIntervalMs: clamp(source.pollIntervalMs, 1e3, 1e4, 3e3)
|
|
1076
|
+
};
|
|
1077
|
+
const qrCodeDataUrl = safeQrSource(source.qrCodeDataUrl);
|
|
1078
|
+
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
1079
|
+
if (opaqueId(source.botId)) result.botId = opaqueId(source.botId);
|
|
1080
|
+
if (source.alreadyConnected === true) result.alreadyConnected = true;
|
|
1081
|
+
const error = normalizeError(
|
|
1082
|
+
source.error,
|
|
1083
|
+
"DINGTALK_PROVISION_FAILED",
|
|
1084
|
+
"\u9489\u9489\u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210"
|
|
1085
|
+
);
|
|
1086
|
+
if (error) result.error = error;
|
|
1087
|
+
return result;
|
|
1088
|
+
}
|
|
1089
|
+
function normalizeBot(value) {
|
|
1090
|
+
if (!isRecord(value)) return void 0;
|
|
1091
|
+
const botId = opaqueId(value.botId);
|
|
1092
|
+
if (!botId) return void 0;
|
|
1093
|
+
const bot = isRecord(value.bot) ? value.bot : {};
|
|
1094
|
+
const connected = value.connected === true;
|
|
1095
|
+
const reportedState = ACCOUNT_STATES.has(value.state) ? value.state : "offline";
|
|
1096
|
+
const state = connected ? "connected" : reportedState === "connected" ? "connecting" : reportedState;
|
|
1097
|
+
const health = isRecord(value.health) ? value.health : {};
|
|
1098
|
+
const stats = isRecord(value.stats) ? value.stats : {};
|
|
1099
|
+
return {
|
|
1100
|
+
botId,
|
|
1101
|
+
state,
|
|
1102
|
+
connected,
|
|
1103
|
+
configured: value.configured !== false,
|
|
1104
|
+
workspace: optionalString(value.workspace, 4096) ?? "",
|
|
1105
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
1106
|
+
bot: {
|
|
1107
|
+
name: optionalString(bot.name, 100) ?? "\u9489\u9489\u673A\u5668\u4EBA",
|
|
1108
|
+
clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? "\u5DF2\u5B89\u5168\u4FDD\u5B58"
|
|
1109
|
+
},
|
|
1110
|
+
health: {
|
|
1111
|
+
status: HEALTH_STATES.has(health.status) ? health.status : connected ? "healthy" : "offline",
|
|
1112
|
+
summary: optionalString(health.summary, 200) ?? (connected ? "\u9489\u9489 Stream \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
1113
|
+
lastCheckedAt: timestamp(health.lastCheckedAt),
|
|
1114
|
+
lastConnectedAt: timestamp(health.lastConnectedAt)
|
|
1115
|
+
},
|
|
1116
|
+
stats: {
|
|
1117
|
+
messagesReceived: nonNegativeInteger(stats.messagesReceived),
|
|
1118
|
+
messagesReplied: nonNegativeInteger(stats.messagesReplied)
|
|
1119
|
+
},
|
|
1120
|
+
error: normalizeError(value.error, "DINGTALK_ACCOUNT_ERROR", "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA") ?? null
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function normalizeSnapshot(value) {
|
|
1124
|
+
const source = isRecord(value?.snapshot) ? value.snapshot : value;
|
|
1125
|
+
if (!isRecord(source) || !Array.isArray(source.bots)) {
|
|
1126
|
+
throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
1004
1127
|
}
|
|
1005
|
-
|
|
1128
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1129
|
+
const bots = source.bots.map(normalizeBot).filter((bot) => {
|
|
1130
|
+
if (!bot || seen.has(bot.botId)) return false;
|
|
1131
|
+
seen.add(bot.botId);
|
|
1132
|
+
return true;
|
|
1133
|
+
});
|
|
1134
|
+
return {
|
|
1135
|
+
schemaVersion: Number.isSafeInteger(source.schemaVersion) ? source.schemaVersion : 1,
|
|
1136
|
+
revision: nonNegativeInteger(source.revision),
|
|
1137
|
+
state: SNAPSHOT_STATES.has(source.state) ? source.state : "offline",
|
|
1138
|
+
bots,
|
|
1139
|
+
totals: {
|
|
1140
|
+
configured: bots.length,
|
|
1141
|
+
connected: bots.filter((bot) => bot.connected).length
|
|
1142
|
+
},
|
|
1143
|
+
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
1144
|
+
testMessage: normalizeTestMessage(source.testMessage),
|
|
1145
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
function connectionTestFeedback(result) {
|
|
1149
|
+
if (result?.sent === true) return "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002";
|
|
1150
|
+
if (result?.code === "test-target-unavailable") {
|
|
1151
|
+
return "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002\u673A\u5668\u4EBA\u5C1A\u672A\u6536\u5230\u53EF\u7528\u4E8E\u6D4B\u8BD5\u7684\u79C1\u804A\u6D88\u606F\u3002";
|
|
1152
|
+
}
|
|
1153
|
+
return result ? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
1154
|
+
}
|
|
1155
|
+
function presentError(error) {
|
|
1156
|
+
return {
|
|
1157
|
+
code: safeErrorCode(error?.code, "DINGTALK_ERROR"),
|
|
1158
|
+
message: sanitizeMessage(error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
function formatRemaining(milliseconds) {
|
|
1162
|
+
const seconds = Math.max(0, Math.ceil(Number(milliseconds) / 1e3) || 0);
|
|
1163
|
+
return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
|
|
1006
1164
|
}
|
|
1007
1165
|
|
|
1166
|
+
// plugin-src/client/channels/dingtalk/index.js
|
|
1167
|
+
var React8 = __toESM(require("react"), 1);
|
|
1168
|
+
|
|
1008
1169
|
// plugin-src/client/credential-binding.js
|
|
1170
|
+
var React4 = __toESM(require("react"), 1);
|
|
1009
1171
|
function ActionIcon({ children }) {
|
|
1010
1172
|
return h2("svg", {
|
|
1011
1173
|
className: "dim-actionIcon",
|
|
@@ -1065,9 +1227,9 @@ function CredentialBindingPanel({
|
|
|
1065
1227
|
onSubmit,
|
|
1066
1228
|
onCancel
|
|
1067
1229
|
}) {
|
|
1068
|
-
const [identity, setIdentity] =
|
|
1069
|
-
const [secret, setSecret] =
|
|
1070
|
-
const headingId =
|
|
1230
|
+
const [identity, setIdentity] = React4.useState("");
|
|
1231
|
+
const [secret, setSecret] = React4.useState("");
|
|
1232
|
+
const headingId = React4.useId();
|
|
1071
1233
|
const hasIdentity = Boolean(identityLabel);
|
|
1072
1234
|
const submit = (event) => {
|
|
1073
1235
|
event.preventDefault();
|
|
@@ -1146,10 +1308,10 @@ function CredentialBindingPanel({
|
|
|
1146
1308
|
}
|
|
1147
1309
|
|
|
1148
1310
|
// plugin-src/client/workspace-editor.js
|
|
1149
|
-
var
|
|
1311
|
+
var React6 = __toESM(require("react"), 1);
|
|
1150
1312
|
|
|
1151
1313
|
// plugin-src/client/workspace-directory-picker.js
|
|
1152
|
-
var
|
|
1314
|
+
var React5 = __toESM(require("react"), 1);
|
|
1153
1315
|
var import_react_dom = require("react-dom");
|
|
1154
1316
|
function pickerErrorCode(error) {
|
|
1155
1317
|
return error?.rpcError?.code ?? error?.code;
|
|
@@ -1161,7 +1323,7 @@ function pickerErrorMessage(error) {
|
|
|
1161
1323
|
return error?.rpcError?.message ?? error?.message ?? "\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002";
|
|
1162
1324
|
}
|
|
1163
1325
|
function FolderIcon() {
|
|
1164
|
-
return
|
|
1326
|
+
return React5.createElement(
|
|
1165
1327
|
"svg",
|
|
1166
1328
|
{
|
|
1167
1329
|
viewBox: "0 0 24 24",
|
|
@@ -1172,11 +1334,11 @@ function FolderIcon() {
|
|
|
1172
1334
|
strokeLinejoin: "round",
|
|
1173
1335
|
"aria-hidden": "true"
|
|
1174
1336
|
},
|
|
1175
|
-
|
|
1337
|
+
React5.createElement("path", { d: "M3.5 7.25A2.25 2.25 0 0 1 5.75 5h4.1l1.8 2h6.6a2.25 2.25 0 0 1 2.25 2.25v7A2.75 2.75 0 0 1 17.75 19h-12A2.25 2.25 0 0 1 3.5 16.75v-9.5Z" })
|
|
1176
1338
|
);
|
|
1177
1339
|
}
|
|
1178
1340
|
function ChevronIcon() {
|
|
1179
|
-
return
|
|
1341
|
+
return React5.createElement("svg", {
|
|
1180
1342
|
viewBox: "0 0 20 20",
|
|
1181
1343
|
fill: "none",
|
|
1182
1344
|
stroke: "currentColor",
|
|
@@ -1184,7 +1346,7 @@ function ChevronIcon() {
|
|
|
1184
1346
|
strokeLinecap: "round",
|
|
1185
1347
|
strokeLinejoin: "round",
|
|
1186
1348
|
"aria-hidden": "true"
|
|
1187
|
-
},
|
|
1349
|
+
}, React5.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
|
|
1188
1350
|
}
|
|
1189
1351
|
function displayCrumbs(listing) {
|
|
1190
1352
|
const homeIndex = listing.crumbs.findIndex((crumb) => crumb.path === listing.home);
|
|
@@ -1200,25 +1362,25 @@ function WorkspaceDirectoryPicker({
|
|
|
1200
1362
|
onPicked,
|
|
1201
1363
|
onCancel
|
|
1202
1364
|
}) {
|
|
1203
|
-
const [listing, setListing] =
|
|
1204
|
-
const [loading, setLoading] =
|
|
1205
|
-
const [error, setError] =
|
|
1206
|
-
const [showHidden, setShowHidden] =
|
|
1207
|
-
const [retryKey, setRetryKey] =
|
|
1208
|
-
const requestRef =
|
|
1209
|
-
const controllerRef =
|
|
1210
|
-
const dialogRef =
|
|
1211
|
-
const bodyRef =
|
|
1212
|
-
const titleId =
|
|
1213
|
-
const noticeId =
|
|
1214
|
-
const initialPathRef =
|
|
1215
|
-
const onPickedRef =
|
|
1216
|
-
const onCancelRef =
|
|
1217
|
-
const busyRef =
|
|
1365
|
+
const [listing, setListing] = React5.useState(null);
|
|
1366
|
+
const [loading, setLoading] = React5.useState(false);
|
|
1367
|
+
const [error, setError] = React5.useState(null);
|
|
1368
|
+
const [showHidden, setShowHidden] = React5.useState(false);
|
|
1369
|
+
const [retryKey, setRetryKey] = React5.useState(0);
|
|
1370
|
+
const requestRef = React5.useRef(0);
|
|
1371
|
+
const controllerRef = React5.useRef(null);
|
|
1372
|
+
const dialogRef = React5.useRef(null);
|
|
1373
|
+
const bodyRef = React5.useRef(null);
|
|
1374
|
+
const titleId = React5.useId();
|
|
1375
|
+
const noticeId = React5.useId();
|
|
1376
|
+
const initialPathRef = React5.useRef(startPath);
|
|
1377
|
+
const onPickedRef = React5.useRef(onPicked);
|
|
1378
|
+
const onCancelRef = React5.useRef(onCancel);
|
|
1379
|
+
const busyRef = React5.useRef(busy);
|
|
1218
1380
|
onPickedRef.current = onPicked;
|
|
1219
1381
|
onCancelRef.current = onCancel;
|
|
1220
1382
|
busyRef.current = busy;
|
|
1221
|
-
const loadDirectory =
|
|
1383
|
+
const loadDirectory = React5.useCallback(async (path, { reportError = true } = {}) => {
|
|
1222
1384
|
const request = requestRef.current + 1;
|
|
1223
1385
|
requestRef.current = request;
|
|
1224
1386
|
controllerRef.current?.abort();
|
|
@@ -1241,7 +1403,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1241
1403
|
if (request === requestRef.current) setLoading(false);
|
|
1242
1404
|
}
|
|
1243
1405
|
}, [picker]);
|
|
1244
|
-
|
|
1406
|
+
React5.useEffect(() => {
|
|
1245
1407
|
if (!open) return void 0;
|
|
1246
1408
|
let active = true;
|
|
1247
1409
|
setListing(null);
|
|
@@ -1319,10 +1481,10 @@ function WorkspaceDirectoryPicker({
|
|
|
1319
1481
|
"nav",
|
|
1320
1482
|
{ className: "dim-directoryCrumbs", "aria-label": "\u5F53\u524D\u76EE\u5F55" },
|
|
1321
1483
|
crumbs.map((crumb, index) => h2(
|
|
1322
|
-
|
|
1484
|
+
React5.Fragment,
|
|
1323
1485
|
{ key: crumb.path },
|
|
1324
1486
|
index > 0 ? h2("span", { className: "dim-directoryCrumbSeparator", "aria-hidden": "true" }, "\u203A") : null,
|
|
1325
|
-
|
|
1487
|
+
React5.createElement("button", {
|
|
1326
1488
|
type: "button",
|
|
1327
1489
|
title: crumb.path,
|
|
1328
1490
|
disabled: loading || busy,
|
|
@@ -1343,7 +1505,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1343
1505
|
) : listing ? entries.length > 0 ? h2("ul", { className: "dim-directoryList" }, entries.map((entry) => h2(
|
|
1344
1506
|
"li",
|
|
1345
1507
|
{ key: entry.path },
|
|
1346
|
-
|
|
1508
|
+
React5.createElement(
|
|
1347
1509
|
"button",
|
|
1348
1510
|
{
|
|
1349
1511
|
type: "button",
|
|
@@ -1352,7 +1514,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1352
1514
|
onClick: () => void loadDirectory(entry.path)
|
|
1353
1515
|
},
|
|
1354
1516
|
h2("span", { className: "dim-directoryFolder" }, h2(FolderIcon)),
|
|
1355
|
-
|
|
1517
|
+
React5.createElement("span", { className: "dim-directoryName" }, entry.name),
|
|
1356
1518
|
h2("span", { className: "dim-directoryChevron" }, h2(ChevronIcon))
|
|
1357
1519
|
)
|
|
1358
1520
|
))) : h2(
|
|
@@ -1405,21 +1567,21 @@ function WorkspaceDirectoryPicker({
|
|
|
1405
1567
|
}
|
|
1406
1568
|
|
|
1407
1569
|
// plugin-src/client/workspace-editor.js
|
|
1408
|
-
var WorkspaceDirectoryPickerContext =
|
|
1570
|
+
var WorkspaceDirectoryPickerContext = React6.createContext(null);
|
|
1409
1571
|
function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave }) {
|
|
1410
|
-
const sharedDirectoryPicker =
|
|
1572
|
+
const sharedDirectoryPicker = React6.useContext(WorkspaceDirectoryPickerContext);
|
|
1411
1573
|
const activeDirectoryPicker = directoryPicker ?? sharedDirectoryPicker;
|
|
1412
|
-
const [open, setOpen] =
|
|
1413
|
-
const [saving, setSaving] =
|
|
1414
|
-
const [error, setError] =
|
|
1415
|
-
const editButtonRef =
|
|
1416
|
-
const savingRef =
|
|
1417
|
-
const close =
|
|
1574
|
+
const [open, setOpen] = React6.useState(false);
|
|
1575
|
+
const [saving, setSaving] = React6.useState(false);
|
|
1576
|
+
const [error, setError] = React6.useState(null);
|
|
1577
|
+
const editButtonRef = React6.useRef(null);
|
|
1578
|
+
const savingRef = React6.useRef(false);
|
|
1579
|
+
const close = React6.useCallback(() => {
|
|
1418
1580
|
setOpen(false);
|
|
1419
1581
|
setError(null);
|
|
1420
1582
|
queueMicrotask(() => editButtonRef.current?.focus?.());
|
|
1421
1583
|
}, []);
|
|
1422
|
-
const pick =
|
|
1584
|
+
const pick = React6.useCallback(async (value) => {
|
|
1423
1585
|
if (!value || savingRef.current || disabled) return;
|
|
1424
1586
|
if (value === workspace) {
|
|
1425
1587
|
close();
|
|
@@ -1456,7 +1618,7 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
|
|
|
1456
1618
|
disabled: disabled || !activeDirectoryPicker
|
|
1457
1619
|
}, "\u9009\u62E9\u76EE\u5F55")
|
|
1458
1620
|
),
|
|
1459
|
-
workspace ?
|
|
1621
|
+
workspace ? React6.createElement("code", {
|
|
1460
1622
|
className: "dim-workspacePath",
|
|
1461
1623
|
title: workspace
|
|
1462
1624
|
}, workspace) : h2("code", { className: "dim-workspacePath" }, "\u672A\u8BBE\u7F6E"),
|
|
@@ -1473,10 +1635,10 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
|
|
|
1473
1635
|
}
|
|
1474
1636
|
|
|
1475
1637
|
// plugin-src/client/workspace-snapshot-fence.js
|
|
1476
|
-
var
|
|
1638
|
+
var React7 = __toESM(require("react"), 1);
|
|
1477
1639
|
function useWorkspaceSnapshotFence() {
|
|
1478
|
-
const state =
|
|
1479
|
-
return
|
|
1640
|
+
const state = React7.useRef({ version: 0, pendingMutations: 0 });
|
|
1641
|
+
return React7.useMemo(() => Object.freeze({
|
|
1480
1642
|
beginStatus() {
|
|
1481
1643
|
return state.current.pendingMutations === 0 ? state.current.version : null;
|
|
1482
1644
|
},
|
|
@@ -1656,7 +1818,7 @@ function DingtalkIcon({ size = 28 }) {
|
|
|
1656
1818
|
d: "M37.05 22.783c-6.758-5.216-14.378-12.128-22.73-19.538-.655-.585-1.242-.354-1.536.42-1.88 4.973-.058 9.386 2.889 11.932s7.368 4.912 10.058 6.155c.105.049.013.203-.093.163-4.953-2.182-8.397-3.765-13.07-7.368-.497-.388-1.01-.242-1.07.521-.384 4.748 2.657 8.483 6.058 9.745 2.1.781 4.398 1.212 6.53 1.474.109.015.084.178-.027.178-2.747.01-6.058-.654-8.935-1.751-.606-.233-.818.25-.722.633.491 2.008 2.974 5.076 6.926 5.73a12 12 0 0 0 2.228.115c.164 0 .208.089.154.217q-2.685 4.6-2.803 4.797c-.091.152-.036.275.156.275h3.543c.164 0 .264.106.18.246l-4.958 8.196c-.191.328.035.565.395.301s15.212-11.133 15.636-11.448c.195-.142.148-.327-.124-.327h-3.18c-.206 0-.252-.14-.111-.28.14-.141 3.602-3.594 4.837-4.888 1.283-1.35 1.938-3.825-.231-5.498"
|
|
1657
1819
|
}));
|
|
1658
1820
|
}
|
|
1659
|
-
var Button =
|
|
1821
|
+
var Button = React8.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
1660
1822
|
return h2("button", {
|
|
1661
1823
|
...props,
|
|
1662
1824
|
ref,
|
|
@@ -1752,13 +1914,13 @@ function EmptyView({ busy, onStart }) {
|
|
|
1752
1914
|
);
|
|
1753
1915
|
}
|
|
1754
1916
|
function QrPanel({ provision, now, busy, onRefresh, onCancel }) {
|
|
1755
|
-
const [imageFailed, setImageFailed] =
|
|
1917
|
+
const [imageFailed, setImageFailed] = React8.useState(false);
|
|
1756
1918
|
const source = safeQrSource(provision.qrCodeDataUrl);
|
|
1757
1919
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
1758
1920
|
const expired = remaining === 0 || provision.status === "expired";
|
|
1759
1921
|
const duration = Math.max(1, provision.durationMs ?? 10 * 6e4);
|
|
1760
1922
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
1761
|
-
|
|
1923
|
+
React8.useEffect(() => setImageFailed(false), [source]);
|
|
1762
1924
|
return h2(
|
|
1763
1925
|
"div",
|
|
1764
1926
|
{ className: "ddt-card dim-surfaceCard" },
|
|
@@ -1875,8 +2037,8 @@ function checkedTime(value) {
|
|
|
1875
2037
|
}
|
|
1876
2038
|
}
|
|
1877
2039
|
function RemoveConfirmation({ account, busy, onConfirm, onCancel }) {
|
|
1878
|
-
const cancelRef =
|
|
1879
|
-
|
|
2040
|
+
const cancelRef = React8.useRef(null);
|
|
2041
|
+
React8.useEffect(() => cancelRef.current?.focus(), []);
|
|
1880
2042
|
return h2(
|
|
1881
2043
|
"div",
|
|
1882
2044
|
{
|
|
@@ -1908,6 +2070,7 @@ function AccountCard({
|
|
|
1908
2070
|
removing,
|
|
1909
2071
|
onReconnect,
|
|
1910
2072
|
onWorkspaceSave,
|
|
2073
|
+
onAgentPresetSave,
|
|
1911
2074
|
onRequestRemove,
|
|
1912
2075
|
onConfirmRemove,
|
|
1913
2076
|
onCancelRemove
|
|
@@ -1964,6 +2127,11 @@ function AccountCard({
|
|
|
1964
2127
|
disabled: Boolean(busy),
|
|
1965
2128
|
onSave: onWorkspaceSave
|
|
1966
2129
|
}),
|
|
2130
|
+
h2(AgentPresetEditor, {
|
|
2131
|
+
agentPreset: account.agentPreset,
|
|
2132
|
+
disabled: Boolean(busy),
|
|
2133
|
+
onSave: onAgentPresetSave
|
|
2134
|
+
}),
|
|
1967
2135
|
h2(
|
|
1968
2136
|
"div",
|
|
1969
2137
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -2015,6 +2183,7 @@ function AccountList(props) {
|
|
|
2015
2183
|
removing: props.removeTarget === account.botId,
|
|
2016
2184
|
onReconnect: () => props.onReconnect(account),
|
|
2017
2185
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
2186
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
2018
2187
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
2019
2188
|
onConfirmRemove: () => props.onConfirmRemove(account),
|
|
2020
2189
|
onCancelRemove: props.onCancelRemove
|
|
@@ -2024,29 +2193,30 @@ function AccountList(props) {
|
|
|
2024
2193
|
}
|
|
2025
2194
|
var EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
|
|
2026
2195
|
function DingtalkSettingsTab({ rpcCall }) {
|
|
2027
|
-
const [model, setModel] =
|
|
2196
|
+
const [model, setModel] = React8.useState({
|
|
2028
2197
|
phase: "loading",
|
|
2029
2198
|
bots: [],
|
|
2030
2199
|
totals: EMPTY_TOTALS,
|
|
2031
2200
|
revision: 0,
|
|
2032
|
-
error: null
|
|
2201
|
+
error: null,
|
|
2202
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
2033
2203
|
});
|
|
2034
|
-
const [provision, setProvision] =
|
|
2035
|
-
const [busy, setBusy] =
|
|
2036
|
-
const [busyByBot, setBusyByBot] =
|
|
2037
|
-
const [feedbackByBot, setFeedbackByBot] =
|
|
2038
|
-
const [removeTarget, setRemoveTarget] =
|
|
2039
|
-
const [credentialOpen, setCredentialOpen] =
|
|
2040
|
-
const [credentialError, setCredentialError] =
|
|
2041
|
-
const [notice, setNotice] =
|
|
2042
|
-
const [now, setNow] =
|
|
2043
|
-
const addButtonRef =
|
|
2044
|
-
const mountedRef =
|
|
2045
|
-
const statusRequestRef =
|
|
2204
|
+
const [provision, setProvision] = React8.useState(null);
|
|
2205
|
+
const [busy, setBusy] = React8.useState(false);
|
|
2206
|
+
const [busyByBot, setBusyByBot] = React8.useState({});
|
|
2207
|
+
const [feedbackByBot, setFeedbackByBot] = React8.useState({});
|
|
2208
|
+
const [removeTarget, setRemoveTarget] = React8.useState(null);
|
|
2209
|
+
const [credentialOpen, setCredentialOpen] = React8.useState(false);
|
|
2210
|
+
const [credentialError, setCredentialError] = React8.useState(null);
|
|
2211
|
+
const [notice, setNotice] = React8.useState("");
|
|
2212
|
+
const [now, setNow] = React8.useState(() => Date.now());
|
|
2213
|
+
const addButtonRef = React8.useRef(null);
|
|
2214
|
+
const mountedRef = React8.useRef(true);
|
|
2215
|
+
const statusRequestRef = React8.useRef(0);
|
|
2046
2216
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
2047
|
-
const noticeFrameRef =
|
|
2048
|
-
const focusFrameRef =
|
|
2049
|
-
|
|
2217
|
+
const noticeFrameRef = React8.useRef(null);
|
|
2218
|
+
const focusFrameRef = React8.useRef(null);
|
|
2219
|
+
React8.useEffect(() => {
|
|
2050
2220
|
mountedRef.current = true;
|
|
2051
2221
|
return () => {
|
|
2052
2222
|
mountedRef.current = false;
|
|
@@ -2061,8 +2231,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2061
2231
|
}
|
|
2062
2232
|
};
|
|
2063
2233
|
}, []);
|
|
2064
|
-
|
|
2065
|
-
const announce =
|
|
2234
|
+
React8.useEffect(() => installDingtalkStyles(), []);
|
|
2235
|
+
const announce = React8.useCallback((message) => {
|
|
2066
2236
|
if (!mountedRef.current) return;
|
|
2067
2237
|
if (noticeFrameRef.current !== null) {
|
|
2068
2238
|
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
@@ -2076,7 +2246,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2076
2246
|
});
|
|
2077
2247
|
}
|
|
2078
2248
|
}, []);
|
|
2079
|
-
const discardStaleFeedback =
|
|
2249
|
+
const discardStaleFeedback = React8.useCallback((snapshot) => {
|
|
2080
2250
|
const botsById = new Map(snapshot.bots.map((bot) => [bot.botId, bot]));
|
|
2081
2251
|
setFeedbackByBot((current) => {
|
|
2082
2252
|
let changed = false;
|
|
@@ -2091,7 +2261,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2091
2261
|
return changed ? next : current;
|
|
2092
2262
|
});
|
|
2093
2263
|
}, []);
|
|
2094
|
-
const focusAddButton =
|
|
2264
|
+
const focusAddButton = React8.useCallback(() => {
|
|
2095
2265
|
if (!mountedRef.current) return;
|
|
2096
2266
|
if (focusFrameRef.current !== null) window.cancelAnimationFrame(focusFrameRef.current);
|
|
2097
2267
|
focusFrameRef.current = window.requestAnimationFrame(() => {
|
|
@@ -2099,11 +2269,11 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2099
2269
|
if (mountedRef.current) addButtonRef.current?.focus();
|
|
2100
2270
|
});
|
|
2101
2271
|
}, []);
|
|
2102
|
-
const invoke =
|
|
2272
|
+
const invoke = React8.useCallback(async (endpoint, payload = {}, signal) => {
|
|
2103
2273
|
if (typeof rpcCall !== "function") throw new TypeError("\u9489\u9489\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
2104
2274
|
return unwrapRpcResult(await rpcCall(endpoint, payload, signal));
|
|
2105
2275
|
}, [rpcCall]);
|
|
2106
|
-
const loadStatus =
|
|
2276
|
+
const loadStatus = React8.useCallback(async ({
|
|
2107
2277
|
signal,
|
|
2108
2278
|
silent = false,
|
|
2109
2279
|
restoreProvisioning = false
|
|
@@ -2125,7 +2295,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2125
2295
|
bots: snapshot.bots,
|
|
2126
2296
|
totals: snapshot.totals,
|
|
2127
2297
|
revision: snapshot.revision,
|
|
2128
|
-
error: null
|
|
2298
|
+
error: null,
|
|
2299
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2129
2300
|
});
|
|
2130
2301
|
discardStaleFeedback(snapshot);
|
|
2131
2302
|
if (restoreProvisioning && snapshot.provisioning) {
|
|
@@ -2146,12 +2317,12 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2146
2317
|
return void 0;
|
|
2147
2318
|
}
|
|
2148
2319
|
}, [discardStaleFeedback, invoke, workspaceFence]);
|
|
2149
|
-
|
|
2320
|
+
React8.useEffect(() => {
|
|
2150
2321
|
const controller = new AbortController();
|
|
2151
2322
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
2152
2323
|
return () => controller.abort();
|
|
2153
2324
|
}, [loadStatus]);
|
|
2154
|
-
|
|
2325
|
+
React8.useEffect(() => {
|
|
2155
2326
|
if (model.phase !== "ready") return void 0;
|
|
2156
2327
|
const controller = new AbortController();
|
|
2157
2328
|
let running = false;
|
|
@@ -2170,14 +2341,14 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2170
2341
|
window.clearInterval(timer);
|
|
2171
2342
|
};
|
|
2172
2343
|
}, [loadStatus, model.phase]);
|
|
2173
|
-
|
|
2344
|
+
React8.useEffect(() => {
|
|
2174
2345
|
if (!provision || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
|
|
2175
2346
|
const timer = window.setInterval(() => {
|
|
2176
2347
|
if (mountedRef.current) setNow(Date.now());
|
|
2177
2348
|
}, 1e3);
|
|
2178
2349
|
return () => window.clearInterval(timer);
|
|
2179
2350
|
}, [provision?.attemptId, provision?.status]);
|
|
2180
|
-
const startProvisioning =
|
|
2351
|
+
const startProvisioning = React8.useCallback(async ({ replace = false } = {}) => {
|
|
2181
2352
|
if (!mountedRef.current) return;
|
|
2182
2353
|
setCredentialOpen(false);
|
|
2183
2354
|
setCredentialError(null);
|
|
@@ -2215,7 +2386,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2215
2386
|
if (mountedRef.current) setBusy(false);
|
|
2216
2387
|
}
|
|
2217
2388
|
}, [announce, invoke, provision?.attemptId]);
|
|
2218
|
-
const bindCredentials =
|
|
2389
|
+
const bindCredentials = React8.useCallback(async ({ identity, secret }) => {
|
|
2219
2390
|
if (!mountedRef.current) return;
|
|
2220
2391
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2221
2392
|
setBusy(true);
|
|
@@ -2232,7 +2403,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2232
2403
|
bots: snapshot.bots,
|
|
2233
2404
|
totals: snapshot.totals,
|
|
2234
2405
|
revision: snapshot.revision,
|
|
2235
|
-
error: null
|
|
2406
|
+
error: null,
|
|
2407
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2236
2408
|
});
|
|
2237
2409
|
discardStaleFeedback(snapshot);
|
|
2238
2410
|
}
|
|
@@ -2246,7 +2418,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2246
2418
|
if (mountedRef.current) setBusy(false);
|
|
2247
2419
|
}
|
|
2248
2420
|
}, [announce, discardStaleFeedback, invoke, loadStatus, workspaceFence]);
|
|
2249
|
-
const cancelProvisioning =
|
|
2421
|
+
const cancelProvisioning = React8.useCallback(async () => {
|
|
2250
2422
|
if (!mountedRef.current) return;
|
|
2251
2423
|
setBusy(true);
|
|
2252
2424
|
try {
|
|
@@ -2264,7 +2436,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2264
2436
|
if (mountedRef.current) setBusy(false);
|
|
2265
2437
|
}
|
|
2266
2438
|
}, [announce, focusAddButton, invoke, provision?.attemptId, provision?.status]);
|
|
2267
|
-
|
|
2439
|
+
React8.useEffect(() => {
|
|
2268
2440
|
const attemptId = provision?.attemptId;
|
|
2269
2441
|
if (!attemptId || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
|
|
2270
2442
|
const controller = new AbortController();
|
|
@@ -2323,7 +2495,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2323
2495
|
timer = null;
|
|
2324
2496
|
};
|
|
2325
2497
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
2326
|
-
const setBotBusy =
|
|
2498
|
+
const setBotBusy = React8.useCallback((botId, operation) => {
|
|
2327
2499
|
if (!mountedRef.current) return;
|
|
2328
2500
|
setBusyByBot((current) => {
|
|
2329
2501
|
const next = { ...current };
|
|
@@ -2332,7 +2504,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2332
2504
|
return next;
|
|
2333
2505
|
});
|
|
2334
2506
|
}, []);
|
|
2335
|
-
const runBotAction =
|
|
2507
|
+
const runBotAction = React8.useCallback(async ({ account, operation, endpoint, payload, success }) => {
|
|
2336
2508
|
if (!mountedRef.current) return void 0;
|
|
2337
2509
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2338
2510
|
setBotBusy(account.botId, operation);
|
|
@@ -2352,7 +2524,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2352
2524
|
bots: snapshot.bots,
|
|
2353
2525
|
totals: snapshot.totals,
|
|
2354
2526
|
revision: snapshot.revision,
|
|
2355
|
-
error: null
|
|
2527
|
+
error: null,
|
|
2528
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2356
2529
|
});
|
|
2357
2530
|
discardStaleFeedback(snapshot);
|
|
2358
2531
|
}
|
|
@@ -2385,7 +2558,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2385
2558
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2386
2559
|
}
|
|
2387
2560
|
}, [announce, discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2388
|
-
const reconnect =
|
|
2561
|
+
const reconnect = React8.useCallback((account) => runBotAction({
|
|
2389
2562
|
account,
|
|
2390
2563
|
operation: "reconnect",
|
|
2391
2564
|
endpoint: DINGTALK_ENDPOINTS.reconnectBot,
|
|
@@ -2396,7 +2569,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2396
2569
|
return connectionTestFeedback(snapshot.testMessage) ?? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
|
|
2397
2570
|
}
|
|
2398
2571
|
}), [runBotAction]);
|
|
2399
|
-
const saveWorkspace =
|
|
2572
|
+
const saveWorkspace = React8.useCallback(async (account, workspace) => {
|
|
2400
2573
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
2401
2574
|
setBotBusy(account.botId, "workspace");
|
|
2402
2575
|
try {
|
|
@@ -2410,7 +2583,33 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2410
2583
|
bots: snapshot.bots,
|
|
2411
2584
|
totals: snapshot.totals,
|
|
2412
2585
|
revision: snapshot.revision,
|
|
2413
|
-
error: null
|
|
2586
|
+
error: null,
|
|
2587
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2588
|
+
});
|
|
2589
|
+
discardStaleFeedback(snapshot);
|
|
2590
|
+
}
|
|
2591
|
+
} finally {
|
|
2592
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
2593
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
2594
|
+
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2595
|
+
}
|
|
2596
|
+
}, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2597
|
+
const saveAgentPreset = React8.useCallback(async (account, agentPreset) => {
|
|
2598
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
2599
|
+
setBotBusy(account.botId, "preset");
|
|
2600
|
+
try {
|
|
2601
|
+
const snapshot = normalizeSnapshot(await invoke(
|
|
2602
|
+
DINGTALK_ENDPOINTS.setAgentPreset,
|
|
2603
|
+
{ botId: account.botId, agentPreset }
|
|
2604
|
+
));
|
|
2605
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2606
|
+
setModel({
|
|
2607
|
+
phase: "ready",
|
|
2608
|
+
bots: snapshot.bots,
|
|
2609
|
+
totals: snapshot.totals,
|
|
2610
|
+
revision: snapshot.revision,
|
|
2611
|
+
error: null,
|
|
2612
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2414
2613
|
});
|
|
2415
2614
|
discardStaleFeedback(snapshot);
|
|
2416
2615
|
}
|
|
@@ -2420,7 +2619,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2420
2619
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2421
2620
|
}
|
|
2422
2621
|
}, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2423
|
-
const remove =
|
|
2622
|
+
const remove = React8.useCallback(async (account) => {
|
|
2424
2623
|
const snapshot = await runBotAction({
|
|
2425
2624
|
account,
|
|
2426
2625
|
operation: "delete",
|
|
@@ -2474,7 +2673,9 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2474
2673
|
setCredentialError(null);
|
|
2475
2674
|
}
|
|
2476
2675
|
}) : null;
|
|
2477
|
-
return h2(
|
|
2676
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
2677
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2678
|
+
}, h2(
|
|
2478
2679
|
"section",
|
|
2479
2680
|
{ className: "ddt-page dim-channelPage", "aria-label": "\u9489\u9489\u8BBE\u7F6E" },
|
|
2480
2681
|
h2(Heading, {
|
|
@@ -2502,7 +2703,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2502
2703
|
h2(Button, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
2503
2704
|
)
|
|
2504
2705
|
) : h2(
|
|
2505
|
-
|
|
2706
|
+
React8.Fragment,
|
|
2506
2707
|
null,
|
|
2507
2708
|
credentialView,
|
|
2508
2709
|
provisionView,
|
|
@@ -2514,12 +2715,13 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2514
2715
|
removeTarget,
|
|
2515
2716
|
onReconnect: (account) => void reconnect(account),
|
|
2516
2717
|
onWorkspaceSave: saveWorkspace,
|
|
2718
|
+
onAgentPresetSave: saveAgentPreset,
|
|
2517
2719
|
onRequestRemove: (account) => setRemoveTarget(account.botId),
|
|
2518
2720
|
onConfirmRemove: (account) => void remove(account),
|
|
2519
2721
|
onCancelRemove: () => setRemoveTarget(null)
|
|
2520
2722
|
}) : null
|
|
2521
2723
|
)
|
|
2522
|
-
);
|
|
2724
|
+
));
|
|
2523
2725
|
}
|
|
2524
2726
|
|
|
2525
2727
|
// plugin-src/client/channels/shared/token-api.js
|
|
@@ -2544,7 +2746,8 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
2544
2746
|
bindCredentials: "bot.bind-credentials",
|
|
2545
2747
|
reconnectBot: "bot.reconnect",
|
|
2546
2748
|
deleteBot: "bot.delete",
|
|
2547
|
-
setWorkspace: "bot.workspace.set"
|
|
2749
|
+
setWorkspace: "bot.workspace.set",
|
|
2750
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
2548
2751
|
});
|
|
2549
2752
|
function createTokenChannelApi(channel4, connectionSummary, {
|
|
2550
2753
|
normalizeBotExtension = () => ({})
|
|
@@ -2570,6 +2773,7 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
2570
2773
|
connected,
|
|
2571
2774
|
state: connected ? "connected" : state,
|
|
2572
2775
|
workspace: text(value.workspace, "", 4096),
|
|
2776
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
2573
2777
|
bot: {
|
|
2574
2778
|
name: text(value.bot?.name, `${channel4}\u673A\u5668\u4EBA`, 100),
|
|
2575
2779
|
username: text(value.bot?.username, "", 100),
|
|
@@ -2598,7 +2802,8 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
2598
2802
|
return {
|
|
2599
2803
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
2600
2804
|
bots,
|
|
2601
|
-
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length }
|
|
2805
|
+
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
2806
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
2602
2807
|
};
|
|
2603
2808
|
};
|
|
2604
2809
|
const presentError10 = (error) => ({
|
|
@@ -2617,8 +2822,8 @@ var normalizeSnapshot2 = api.normalizeSnapshot;
|
|
|
2617
2822
|
var presentError2 = api.presentError;
|
|
2618
2823
|
|
|
2619
2824
|
// plugin-src/client/channels/shared/token-channel.js
|
|
2620
|
-
var
|
|
2621
|
-
var Button3 =
|
|
2825
|
+
var React9 = __toESM(require("react"), 1);
|
|
2826
|
+
var Button3 = React9.forwardRef(function Button4({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
2622
2827
|
return h2("button", {
|
|
2623
2828
|
...props,
|
|
2624
2829
|
ref,
|
|
@@ -2670,7 +2875,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2670
2875
|
AccountSettings = null,
|
|
2671
2876
|
accountSettingsEndpoint = null
|
|
2672
2877
|
} = definition;
|
|
2673
|
-
function AccountCard5({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
2878
|
+
function AccountCard5({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
2674
2879
|
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
2675
2880
|
const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
|
|
2676
2881
|
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
@@ -2728,6 +2933,11 @@ function createTokenChannelSettings(definition) {
|
|
|
2728
2933
|
disabled: Boolean(busy),
|
|
2729
2934
|
onSave: onWorkspaceSave
|
|
2730
2935
|
}),
|
|
2936
|
+
h2(AgentPresetEditor, {
|
|
2937
|
+
agentPreset: account.agentPreset,
|
|
2938
|
+
disabled: Boolean(busy),
|
|
2939
|
+
onSave: onAgentPresetSave
|
|
2940
|
+
}),
|
|
2731
2941
|
AccountSettings ? h2(AccountSettings, {
|
|
2732
2942
|
account,
|
|
2733
2943
|
busy: Boolean(busy),
|
|
@@ -2774,21 +2984,22 @@ function createTokenChannelSettings(definition) {
|
|
|
2774
2984
|
);
|
|
2775
2985
|
}
|
|
2776
2986
|
function SettingsTab({ rpcCall }) {
|
|
2777
|
-
const [model, setModel] =
|
|
2987
|
+
const [model, setModel] = React9.useState({
|
|
2778
2988
|
phase: "loading",
|
|
2779
2989
|
bots: [],
|
|
2780
2990
|
totals: { configured: 0, connected: 0 },
|
|
2781
|
-
error: null
|
|
2991
|
+
error: null,
|
|
2992
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
2782
2993
|
});
|
|
2783
|
-
const [credentialOpen, setCredentialOpen] =
|
|
2784
|
-
const [credentialError, setCredentialError] =
|
|
2785
|
-
const [busy, setBusy] =
|
|
2786
|
-
const [busyByBot, setBusyByBot] =
|
|
2787
|
-
const [testNoticeByBot, setTestNoticeByBot] =
|
|
2788
|
-
const [removeTarget, setRemoveTarget] =
|
|
2789
|
-
const mounted =
|
|
2994
|
+
const [credentialOpen, setCredentialOpen] = React9.useState(false);
|
|
2995
|
+
const [credentialError, setCredentialError] = React9.useState(null);
|
|
2996
|
+
const [busy, setBusy] = React9.useState(false);
|
|
2997
|
+
const [busyByBot, setBusyByBot] = React9.useState({});
|
|
2998
|
+
const [testNoticeByBot, setTestNoticeByBot] = React9.useState({});
|
|
2999
|
+
const [removeTarget, setRemoveTarget] = React9.useState(null);
|
|
3000
|
+
const mounted = React9.useRef(true);
|
|
2790
3001
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
2791
|
-
|
|
3002
|
+
React9.useEffect(() => {
|
|
2792
3003
|
const disposeDingtalk = installDingtalkStyles();
|
|
2793
3004
|
const disposeChannel = installStyles();
|
|
2794
3005
|
mounted.current = true;
|
|
@@ -2798,18 +3009,24 @@ function createTokenChannelSettings(definition) {
|
|
|
2798
3009
|
disposeDingtalk();
|
|
2799
3010
|
};
|
|
2800
3011
|
}, []);
|
|
2801
|
-
const invoke =
|
|
3012
|
+
const invoke = React9.useCallback(async (endpoint, payload = {}, signal) => {
|
|
2802
3013
|
if (typeof rpcCall !== "function") throw new TypeError(`${channel4} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
|
|
2803
3014
|
return api4.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
|
|
2804
3015
|
}, [rpcCall]);
|
|
2805
|
-
const loadStatus =
|
|
3016
|
+
const loadStatus = React9.useCallback(async ({ signal, silent = false } = {}) => {
|
|
2806
3017
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
2807
3018
|
if (workspaceVersion === null) return;
|
|
2808
3019
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
2809
3020
|
try {
|
|
2810
3021
|
const snapshot = api4.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
|
|
2811
3022
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return;
|
|
2812
|
-
setModel({
|
|
3023
|
+
setModel({
|
|
3024
|
+
phase: "ready",
|
|
3025
|
+
bots: snapshot.bots,
|
|
3026
|
+
totals: snapshot.totals,
|
|
3027
|
+
error: null,
|
|
3028
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3029
|
+
});
|
|
2813
3030
|
} catch (error) {
|
|
2814
3031
|
if (error?.name !== "AbortError" && mounted.current && !signal?.aborted && workspaceFence.canCommitStatus(workspaceVersion)) {
|
|
2815
3032
|
setModel((current) => ({
|
|
@@ -2820,12 +3037,12 @@ function createTokenChannelSettings(definition) {
|
|
|
2820
3037
|
}
|
|
2821
3038
|
}
|
|
2822
3039
|
}, [invoke, workspaceFence]);
|
|
2823
|
-
|
|
3040
|
+
React9.useEffect(() => {
|
|
2824
3041
|
const controller = new AbortController();
|
|
2825
3042
|
void loadStatus({ signal: controller.signal });
|
|
2826
3043
|
return () => controller.abort();
|
|
2827
3044
|
}, [loadStatus]);
|
|
2828
|
-
|
|
3045
|
+
React9.useEffect(() => {
|
|
2829
3046
|
if (model.phase !== "ready") return void 0;
|
|
2830
3047
|
const controller = new AbortController();
|
|
2831
3048
|
const timer = window.setInterval(
|
|
@@ -2837,7 +3054,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2837
3054
|
window.clearInterval(timer);
|
|
2838
3055
|
};
|
|
2839
3056
|
}, [loadStatus, model.phase]);
|
|
2840
|
-
const bindCredentials =
|
|
3057
|
+
const bindCredentials = React9.useCallback(async (values) => {
|
|
2841
3058
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2842
3059
|
setBusy(true);
|
|
2843
3060
|
setCredentialError(null);
|
|
@@ -2848,7 +3065,13 @@ function createTokenChannelSettings(definition) {
|
|
|
2848
3065
|
));
|
|
2849
3066
|
if (!mounted.current) return;
|
|
2850
3067
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2851
|
-
setModel({
|
|
3068
|
+
setModel({
|
|
3069
|
+
phase: "ready",
|
|
3070
|
+
bots: snapshot.bots,
|
|
3071
|
+
totals: snapshot.totals,
|
|
3072
|
+
error: null,
|
|
3073
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3074
|
+
});
|
|
2852
3075
|
}
|
|
2853
3076
|
setCredentialOpen(false);
|
|
2854
3077
|
} catch (error) {
|
|
@@ -2859,14 +3082,20 @@ function createTokenChannelSettings(definition) {
|
|
|
2859
3082
|
if (mounted.current) setBusy(false);
|
|
2860
3083
|
}
|
|
2861
3084
|
}, [invoke, loadStatus, workspaceFence]);
|
|
2862
|
-
const botAction =
|
|
3085
|
+
const botAction = React9.useCallback(async (account, operation, endpoint, payload) => {
|
|
2863
3086
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2864
3087
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
2865
3088
|
try {
|
|
2866
3089
|
const value = await invoke(endpoint, payload);
|
|
2867
3090
|
const snapshot = api4.normalizeSnapshot(value);
|
|
2868
3091
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2869
|
-
setModel({
|
|
3092
|
+
setModel({
|
|
3093
|
+
phase: "ready",
|
|
3094
|
+
bots: snapshot.bots,
|
|
3095
|
+
totals: snapshot.totals,
|
|
3096
|
+
error: null,
|
|
3097
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3098
|
+
});
|
|
2870
3099
|
}
|
|
2871
3100
|
if (mounted.current && operation === "reconnect") {
|
|
2872
3101
|
setTestNoticeByBot((current) => ({
|
|
@@ -2917,6 +3146,12 @@ function createTokenChannelSettings(definition) {
|
|
|
2917
3146
|
endpoints.setWorkspace,
|
|
2918
3147
|
{ botId: account.botId, workspace }
|
|
2919
3148
|
),
|
|
3149
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
3150
|
+
account,
|
|
3151
|
+
"preset",
|
|
3152
|
+
endpoints.setAgentPreset,
|
|
3153
|
+
{ botId: account.botId, agentPreset }
|
|
3154
|
+
),
|
|
2920
3155
|
onAccountSettingsSave: AccountSettings && accountSettingsEndpoint ? (payload) => botAction(
|
|
2921
3156
|
account,
|
|
2922
3157
|
"settings",
|
|
@@ -2934,7 +3169,9 @@ function createTokenChannelSettings(definition) {
|
|
|
2934
3169
|
}
|
|
2935
3170
|
}))))
|
|
2936
3171
|
) : null;
|
|
2937
|
-
return h2(
|
|
3172
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
3173
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3174
|
+
}, h2(
|
|
2938
3175
|
"section",
|
|
2939
3176
|
{
|
|
2940
3177
|
className: `ddt-page ${pageClass} dim-channelPage`,
|
|
@@ -2982,7 +3219,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2982
3219
|
h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
2983
3220
|
)
|
|
2984
3221
|
) : h2(
|
|
2985
|
-
|
|
3222
|
+
React9.Fragment,
|
|
2986
3223
|
null,
|
|
2987
3224
|
credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
|
|
2988
3225
|
busy,
|
|
@@ -3038,7 +3275,7 @@ function createTokenChannelSettings(definition) {
|
|
|
3038
3275
|
) : null,
|
|
3039
3276
|
botList
|
|
3040
3277
|
)
|
|
3041
|
-
);
|
|
3278
|
+
));
|
|
3042
3279
|
}
|
|
3043
3280
|
return { SettingsTab, AccountCard: AccountCard5 };
|
|
3044
3281
|
}
|
|
@@ -3083,7 +3320,7 @@ var DiscordSettingsTab = channel.SettingsTab;
|
|
|
3083
3320
|
var DiscordAccountCard = channel.AccountCard;
|
|
3084
3321
|
|
|
3085
3322
|
// plugin-src/client/channels/feishu/index.js
|
|
3086
|
-
var
|
|
3323
|
+
var React11 = __toESM(require("react"), 1);
|
|
3087
3324
|
|
|
3088
3325
|
// plugin-src/client/channels/feishu/api.js
|
|
3089
3326
|
var FEISHU_RPC_CHANNEL = "/feishu";
|
|
@@ -3091,6 +3328,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
3091
3328
|
status: "connection.status",
|
|
3092
3329
|
beginProvisioning: "provision.begin",
|
|
3093
3330
|
beginCallbackRepair: "bot.callback-repair.begin",
|
|
3331
|
+
beginGroupMessagePermission: "bot.group-message-permission.begin",
|
|
3094
3332
|
pollProvisioning: "provision.poll",
|
|
3095
3333
|
cancelProvisioning: "provision.cancel",
|
|
3096
3334
|
bindCredentials: "bot.bind-credentials",
|
|
@@ -3098,13 +3336,16 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
3098
3336
|
disconnectBot: "bot.disconnect",
|
|
3099
3337
|
deleteBot: "bot.delete",
|
|
3100
3338
|
setWorkspace: "bot.workspace.set",
|
|
3339
|
+
setAgentPreset: "bot.preset.set",
|
|
3340
|
+
setGroupResponseMode: "bot.group-response-mode.set",
|
|
3101
3341
|
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
|
|
3102
3342
|
testConnection: "connection.test",
|
|
3103
3343
|
disconnect: "connection.disconnect"
|
|
3104
3344
|
});
|
|
3105
3345
|
var FEISHU_REGISTRATION_OPERATIONS = Object.freeze({
|
|
3106
3346
|
PROVISION: "provision",
|
|
3107
|
-
CALLBACK_REPAIR: "callback_repair"
|
|
3347
|
+
CALLBACK_REPAIR: "callback_repair",
|
|
3348
|
+
GROUP_MESSAGE_PERMISSION: "group_message_permission"
|
|
3108
3349
|
});
|
|
3109
3350
|
var CONNECTION_STATES = /* @__PURE__ */ new Set([
|
|
3110
3351
|
"disconnected",
|
|
@@ -3137,11 +3378,23 @@ function optionalTimestamp(value) {
|
|
|
3137
3378
|
}
|
|
3138
3379
|
return void 0;
|
|
3139
3380
|
}
|
|
3381
|
+
function normalizeGroupResponseMode(value) {
|
|
3382
|
+
return value === "all" ? "all" : "mention";
|
|
3383
|
+
}
|
|
3140
3384
|
function clamp2(value, min, max, fallback) {
|
|
3141
3385
|
return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
|
|
3142
3386
|
}
|
|
3143
3387
|
function normalizeRegistrationOperation(value) {
|
|
3144
|
-
|
|
3388
|
+
if (value === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR) {
|
|
3389
|
+
return FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
|
|
3390
|
+
}
|
|
3391
|
+
if (value === FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION) {
|
|
3392
|
+
return FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
3393
|
+
}
|
|
3394
|
+
return FEISHU_REGISTRATION_OPERATIONS.PROVISION;
|
|
3395
|
+
}
|
|
3396
|
+
function isTargetedAppUpdate(operation) {
|
|
3397
|
+
return operation === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR || operation === FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
3145
3398
|
}
|
|
3146
3399
|
function unwrapRpcResult3(result) {
|
|
3147
3400
|
if (!isRecord3(result) || typeof result.ok !== "boolean") {
|
|
@@ -3169,8 +3422,8 @@ function normalizeProvisioning2(value, now = Date.now()) {
|
|
|
3169
3422
|
const expireIn = clamp2(source.expireIn, 1, 60 * 60, 5 * 60);
|
|
3170
3423
|
const operation = normalizeRegistrationOperation(source.operation);
|
|
3171
3424
|
const botId = optionalString2(source.botId);
|
|
3172
|
-
if (operation
|
|
3173
|
-
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\
|
|
3425
|
+
if (isTargetedAppUpdate(operation) && !botId) {
|
|
3426
|
+
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId");
|
|
3174
3427
|
}
|
|
3175
3428
|
return {
|
|
3176
3429
|
attemptId,
|
|
@@ -3231,6 +3484,9 @@ function normalizeBotConnection(value, fallbackBotId) {
|
|
|
3231
3484
|
connected,
|
|
3232
3485
|
configured: value.configured !== false,
|
|
3233
3486
|
workspace: optionalString2(value.workspace)?.slice(0, 4096) ?? "",
|
|
3487
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
3488
|
+
groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
|
|
3489
|
+
groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
|
|
3234
3490
|
bot: normalizeBot2(value.bot),
|
|
3235
3491
|
health: normalizeHealth(value.health, connected),
|
|
3236
3492
|
error: normalizeError2(value.error)
|
|
@@ -3271,7 +3527,8 @@ function normalizeBotsSnapshot(value) {
|
|
|
3271
3527
|
// make the UI claim that an unavailable bot is online.
|
|
3272
3528
|
totals: { configured, connected },
|
|
3273
3529
|
provisioning: value.provisioning ? normalizeProvisioning2(value.provisioning) : void 0,
|
|
3274
|
-
error: normalizeError2(value.error)
|
|
3530
|
+
error: normalizeError2(value.error),
|
|
3531
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog)
|
|
3275
3532
|
};
|
|
3276
3533
|
}
|
|
3277
3534
|
function normalizeConnectionSnapshot(value) {
|
|
@@ -3321,7 +3578,7 @@ function formatRemaining2(milliseconds) {
|
|
|
3321
3578
|
}
|
|
3322
3579
|
|
|
3323
3580
|
// plugin-src/client/lifecycle.js
|
|
3324
|
-
var
|
|
3581
|
+
var React10 = __toESM(require("react"), 1);
|
|
3325
3582
|
function createPollScheduler({ setTimeoutFn, clearTimeoutFn }) {
|
|
3326
3583
|
let disposed = false;
|
|
3327
3584
|
let timer;
|
|
@@ -3383,8 +3640,8 @@ function createAnimationFrameScheduler({ requestFrame, cancelFrame }) {
|
|
|
3383
3640
|
};
|
|
3384
3641
|
}
|
|
3385
3642
|
function useAnimationFrameScheduler() {
|
|
3386
|
-
const schedulerRef =
|
|
3387
|
-
|
|
3643
|
+
const schedulerRef = React10.useRef(null);
|
|
3644
|
+
React10.useEffect(() => {
|
|
3388
3645
|
const scheduler = createAnimationFrameScheduler({
|
|
3389
3646
|
requestFrame: (callback) => window.requestAnimationFrame(callback),
|
|
3390
3647
|
cancelFrame: (frame) => window.cancelAnimationFrame(frame)
|
|
@@ -3395,7 +3652,7 @@ function useAnimationFrameScheduler() {
|
|
|
3395
3652
|
if (schedulerRef.current === scheduler) schedulerRef.current = null;
|
|
3396
3653
|
};
|
|
3397
3654
|
}, []);
|
|
3398
|
-
return
|
|
3655
|
+
return React10.useCallback(
|
|
3399
3656
|
(callback, key) => schedulerRef.current?.schedule(callback, key) ?? false,
|
|
3400
3657
|
[]
|
|
3401
3658
|
);
|
|
@@ -3810,6 +4067,50 @@ var CSS3 = String.raw`
|
|
|
3810
4067
|
.bxf-metric dt { color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 17px; }
|
|
3811
4068
|
.bxf-metric dd { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-primary, #1f2329); font-size: 12px; line-height: 18px; font-weight: 550; margin: 3px 0 0; }
|
|
3812
4069
|
|
|
4070
|
+
.bxf-responseMode { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 5px; margin-top: 6px; padding: 8px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
|
|
4071
|
+
.bxf-responseModeHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
|
4072
|
+
.bxf-responseModeHeader > span:first-child { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
|
4073
|
+
.bxf-responseModeStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
4074
|
+
.bxf-responseModeSelect { min-width: 0; width: 100%; grid-column: 1 / -1; grid-row: 2; height: 32px; padding: 0 30px 0 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background-color: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 12px; cursor: pointer; transition: border-color .16s ease, box-shadow .16s ease, background-color .16s ease; }
|
|
4075
|
+
.bxf-responseModeSelect:hover:not(:disabled) { border-color: color-mix(in srgb, var(--bxf-accent) 45%, var(--dsw-alias-border-l2, #dfe1e5)); }
|
|
4076
|
+
.bxf-responseModeSelect:focus-visible { outline: none; border-color: var(--bxf-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bxf-accent) 16%, transparent); }
|
|
4077
|
+
.bxf-responseModeSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
4078
|
+
.bxf-responseModeHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.45; }
|
|
4079
|
+
.bxf-responseModePermissionAction { grid-column: 1 / -1; grid-row: 4; display: flex; justify-content: flex-start; margin-top: 2px; }
|
|
4080
|
+
.bxf-responseModePermissionButton { min-height: 28px; padding: 3px 9px; color: var(--bxf-accent); border-color: color-mix(in srgb, var(--bxf-accent) 30%, var(--dsw-alias-border-l2, #dfe1e5)); background: var(--dsw-alias-bg-layer-1, #fff); }
|
|
4081
|
+
.bxf-responseModePermissionButton:hover:not(:disabled) { background: color-mix(in srgb, var(--bxf-accent) 7%, transparent); }
|
|
4082
|
+
.bxf-responseModeError { grid-column: 1 / -1; grid-row: 5; color: var(--bxf-error); font-size: 12px; line-height: 1.4; margin: 0; }
|
|
4083
|
+
|
|
4084
|
+
.bxf-botProvision {
|
|
4085
|
+
position: relative;
|
|
4086
|
+
margin-top: 14px;
|
|
4087
|
+
scroll-margin-block: 20px;
|
|
4088
|
+
animation: bxf-revealProvision .2s var(--ds-ease-out, ease-out) both;
|
|
4089
|
+
}
|
|
4090
|
+
.bxf-botProvision:focus { outline: none; }
|
|
4091
|
+
.bxf-botProvision:focus-visible {
|
|
4092
|
+
outline: 2px solid color-mix(in srgb, var(--bxf-accent) 75%, transparent);
|
|
4093
|
+
outline-offset: 3px;
|
|
4094
|
+
border-radius: 12px;
|
|
4095
|
+
}
|
|
4096
|
+
.bxf-botProvision > .bxf-provisionCard {
|
|
4097
|
+
border-radius: 11px;
|
|
4098
|
+
box-shadow: none;
|
|
4099
|
+
background: color-mix(in srgb, var(--bxf-accent) 2.5%, var(--dsw-alias-bg-layer-3, #fff));
|
|
4100
|
+
}
|
|
4101
|
+
.bxf-botProvision .bxf-cardBody { padding: 18px; }
|
|
4102
|
+
.bxf-botProvision .bxf-qrLayout {
|
|
4103
|
+
grid-template-columns: 184px minmax(0, 1fr);
|
|
4104
|
+
align-items: start;
|
|
4105
|
+
gap: 24px;
|
|
4106
|
+
}
|
|
4107
|
+
.bxf-botProvision .bxf-qrFrame { width: 176px; height: 176px; padding: 10px; border-radius: 11px; }
|
|
4108
|
+
.bxf-botProvision .bxf-countdown { width: 176px; }
|
|
4109
|
+
.bxf-botProvision .bxf-qrCopy h3 { font-size: 18px; line-height: 26px; }
|
|
4110
|
+
.bxf-botProvision .bxf-steps { gap: 8px; margin-top: 14px; }
|
|
4111
|
+
.bxf-botProvision .bxf-actions { margin-top: 16px; }
|
|
4112
|
+
.bxf-botProvision .bxf-inlineError { min-height: 160px; padding: 22px; }
|
|
4113
|
+
|
|
3813
4114
|
.bxf-connectedFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); }
|
|
3814
4115
|
.bxf-healthSummary { min-width: 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; }
|
|
3815
4116
|
.bxf-healthSummary[data-error="true"] { color: var(--bxf-error); }
|
|
@@ -3862,6 +4163,7 @@ var CSS3 = String.raw`
|
|
|
3862
4163
|
@keyframes bxf-rotate { to { transform: rotate(360deg); } }
|
|
3863
4164
|
@keyframes bxf-pulse { 0%, 100% { transform: scale(.9); opacity: .45; } 50% { transform: scale(1.08); opacity: 1; } }
|
|
3864
4165
|
@keyframes bxf-shimmer { to { background-position: -220% 0; } }
|
|
4166
|
+
@keyframes bxf-revealProvision { from { opacity: 0; transform: translateY(-5px); } }
|
|
3865
4167
|
|
|
3866
4168
|
@container (max-width: 620px) {
|
|
3867
4169
|
.bxf-headingTools { gap: 6px; }
|
|
@@ -3873,6 +4175,7 @@ var CSS3 = String.raw`
|
|
|
3873
4175
|
.bxf-intro { grid-template-columns: minmax(0, 1fr); }
|
|
3874
4176
|
.bxf-markStage { display: none; }
|
|
3875
4177
|
.bxf-qrLayout { grid-template-columns: minmax(0, 1fr); justify-items: center; }
|
|
4178
|
+
.bxf-botProvision .bxf-qrLayout { grid-template-columns: minmax(0, 1fr); }
|
|
3876
4179
|
.bxf-qrCopy { width: 100%; }
|
|
3877
4180
|
.bxf-statusGrid { grid-template-columns: minmax(0, 1fr); }
|
|
3878
4181
|
.bxf-connectedTop { align-items: flex-start; flex-direction: column; }
|
|
@@ -3909,9 +4212,16 @@ function installFeishuStyles() {
|
|
|
3909
4212
|
|
|
3910
4213
|
// plugin-src/client/channels/feishu/index.js
|
|
3911
4214
|
var CALLBACK_REPAIR_OPERATION = FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
|
|
4215
|
+
var GROUP_MESSAGE_PERMISSION_OPERATION = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
3912
4216
|
function isCallbackRepair(value) {
|
|
3913
4217
|
return value?.operation === CALLBACK_REPAIR_OPERATION;
|
|
3914
4218
|
}
|
|
4219
|
+
function isGroupMessagePermission(value) {
|
|
4220
|
+
return value?.operation === GROUP_MESSAGE_PERMISSION_OPERATION;
|
|
4221
|
+
}
|
|
4222
|
+
function isTargetedAppUpdate2(value) {
|
|
4223
|
+
return isCallbackRepair(value) || isGroupMessagePermission(value);
|
|
4224
|
+
}
|
|
3915
4225
|
function SvgIcon({ children, size = 18, className, viewBox = "0 0 24 24" }) {
|
|
3916
4226
|
return h2("svg", {
|
|
3917
4227
|
width: size,
|
|
@@ -3969,7 +4279,7 @@ function QrIcon({ size = 58 }) {
|
|
|
3969
4279
|
fill: "currentColor"
|
|
3970
4280
|
}));
|
|
3971
4281
|
}
|
|
3972
|
-
var Button5 =
|
|
4282
|
+
var Button5 = React11.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
|
|
3973
4283
|
return h2("button", {
|
|
3974
4284
|
...props,
|
|
3975
4285
|
ref,
|
|
@@ -4086,15 +4396,16 @@ function safeQrSource2(value) {
|
|
|
4086
4396
|
return /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
|
|
4087
4397
|
}
|
|
4088
4398
|
function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
4089
|
-
const [imageFailed, setImageFailed] =
|
|
4399
|
+
const [imageFailed, setImageFailed] = React11.useState(false);
|
|
4090
4400
|
const qrSource = safeQrSource2(provision.qrCodeDataUrl);
|
|
4091
4401
|
const href = safeVerificationHref(provision.verificationUrl);
|
|
4092
4402
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
4093
4403
|
const expired = provision.expired === true || remaining === 0;
|
|
4094
4404
|
const progress = Math.min(1, remaining / Math.max(1, provision.durationMs ?? remaining));
|
|
4095
4405
|
const repairing = isCallbackRepair(provision);
|
|
4406
|
+
const grantingGroupMessages = isGroupMessagePermission(provision);
|
|
4096
4407
|
const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
|
|
4097
|
-
|
|
4408
|
+
React11.useEffect(() => setImageFailed(false), [qrSource]);
|
|
4098
4409
|
return h2(
|
|
4099
4410
|
"div",
|
|
4100
4411
|
{ className: "bxf-card bxf-provisionCard dim-surfaceCard" },
|
|
@@ -4109,7 +4420,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4109
4420
|
{ className: "bxf-qrFrame dim-qrFrame" },
|
|
4110
4421
|
qrSource && !imageFailed ? h2("img", {
|
|
4111
4422
|
src: qrSource,
|
|
4112
|
-
alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
|
|
4423
|
+
alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : grantingGroupMessages ? `\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
|
|
4113
4424
|
onError: () => setImageFailed(true)
|
|
4114
4425
|
}) : h2(
|
|
4115
4426
|
"div",
|
|
@@ -4148,16 +4459,16 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4148
4459
|
"div",
|
|
4149
4460
|
{ className: "bxf-stateLabel dim-stateLabel" },
|
|
4150
4461
|
h2("span", { className: "bxf-dot dim-stateDot", "data-tone": "warning" }),
|
|
4151
|
-
h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
|
|
4462
|
+
h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : grantingGroupMessages ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
|
|
4152
4463
|
),
|
|
4153
|
-
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
4154
|
-
h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
|
|
4464
|
+
h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : grantingGroupMessages ? "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
|
|
4465
|
+
h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
|
|
4155
4466
|
h2(
|
|
4156
4467
|
"ol",
|
|
4157
4468
|
{ className: "bxf-steps dim-steps" },
|
|
4158
4469
|
h2("li", null, "\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801"),
|
|
4159
|
-
h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
|
|
4160
|
-
h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
|
|
4470
|
+
h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : grantingGroupMessages ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
|
|
4471
|
+
h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
|
|
4161
4472
|
),
|
|
4162
4473
|
h2(
|
|
4163
4474
|
"div",
|
|
@@ -4174,7 +4485,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4174
4485
|
rel: "noopener noreferrer"
|
|
4175
4486
|
}, h2("span", null, "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00")) : null,
|
|
4176
4487
|
!expired ? h2(Button5, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
|
|
4177
|
-
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4488
|
+
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4178
4489
|
)
|
|
4179
4490
|
)
|
|
4180
4491
|
)
|
|
@@ -4183,6 +4494,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4183
4494
|
function ProvisionProgress({ phase, provision, onCancel, busy }) {
|
|
4184
4495
|
const connecting = phase === "connecting";
|
|
4185
4496
|
const repairing = isCallbackRepair(provision);
|
|
4497
|
+
const grantingGroupMessages = isGroupMessagePermission(provision);
|
|
4186
4498
|
return h2(
|
|
4187
4499
|
"div",
|
|
4188
4500
|
{
|
|
@@ -4190,17 +4502,18 @@ function ProvisionProgress({ phase, provision, onCancel, busy }) {
|
|
|
4190
4502
|
"aria-busy": "true"
|
|
4191
4503
|
},
|
|
4192
4504
|
h2("div", { className: "dim-spinner", "aria-hidden": "true" }),
|
|
4193
|
-
h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
|
|
4194
|
-
h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
|
|
4505
|
+
h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : grantingGroupMessages ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : grantingGroupMessages ? "\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
|
|
4506
|
+
h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : grantingGroupMessages ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
|
|
4195
4507
|
connecting && onCancel ? h2(
|
|
4196
4508
|
"div",
|
|
4197
4509
|
{ className: "bxf-actions dim-viewActions", style: { justifyContent: "center" } },
|
|
4198
|
-
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4510
|
+
h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
|
|
4199
4511
|
) : null
|
|
4200
4512
|
);
|
|
4201
4513
|
}
|
|
4202
4514
|
function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
|
|
4203
4515
|
const repairing = isCallbackRepair(provision);
|
|
4516
|
+
const grantingGroupMessages = isGroupMessagePermission(provision);
|
|
4204
4517
|
return h2(
|
|
4205
4518
|
"div",
|
|
4206
4519
|
{ className: "bxf-card bxf-provisionCard dim-surfaceCard" },
|
|
@@ -4210,7 +4523,7 @@ function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
|
|
|
4210
4523
|
h2(
|
|
4211
4524
|
"div",
|
|
4212
4525
|
null,
|
|
4213
|
-
h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
|
|
4526
|
+
h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
|
|
4214
4527
|
h2("p", null, error.message),
|
|
4215
4528
|
error.code ? h2("span", { className: "bxf-errorCode" }, error.code) : null,
|
|
4216
4529
|
h2(
|
|
@@ -4255,11 +4568,11 @@ function connectionTestNotice2(value) {
|
|
|
4255
4568
|
return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
4256
4569
|
}
|
|
4257
4570
|
function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
4258
|
-
const cancelRef =
|
|
4571
|
+
const cancelRef = React11.useRef(null);
|
|
4259
4572
|
const idPart = bot.botId.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
4260
4573
|
const titleId = `bxf-remove-title-${idPart}`;
|
|
4261
4574
|
const descriptionId = `bxf-remove-description-${idPart}`;
|
|
4262
|
-
|
|
4575
|
+
React11.useEffect(() => cancelRef.current?.focus(), []);
|
|
4263
4576
|
return h2(
|
|
4264
4577
|
"div",
|
|
4265
4578
|
{
|
|
@@ -4292,16 +4605,110 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
|
4292
4605
|
)
|
|
4293
4606
|
);
|
|
4294
4607
|
}
|
|
4608
|
+
function GroupResponseModeEditor({
|
|
4609
|
+
value,
|
|
4610
|
+
permissionGranted = false,
|
|
4611
|
+
disabled = false,
|
|
4612
|
+
authorizationDisabled = false,
|
|
4613
|
+
onSave,
|
|
4614
|
+
onAuthorize
|
|
4615
|
+
}) {
|
|
4616
|
+
const current = normalizeGroupResponseMode(value);
|
|
4617
|
+
const [saving, setSaving] = React11.useState(false);
|
|
4618
|
+
const [authorizing, setAuthorizing] = React11.useState(false);
|
|
4619
|
+
const [error, setError] = React11.useState(null);
|
|
4620
|
+
const change = async (event) => {
|
|
4621
|
+
const next = normalizeGroupResponseMode(event.target.value);
|
|
4622
|
+
if (next === current || saving || disabled) return;
|
|
4623
|
+
setSaving(true);
|
|
4624
|
+
setError(null);
|
|
4625
|
+
try {
|
|
4626
|
+
await onSave?.(next);
|
|
4627
|
+
} catch (cause) {
|
|
4628
|
+
setError(cause?.message ?? "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
4629
|
+
} finally {
|
|
4630
|
+
setSaving(false);
|
|
4631
|
+
}
|
|
4632
|
+
};
|
|
4633
|
+
const authorize = async () => {
|
|
4634
|
+
if (current !== "all" || saving || authorizing || disabled || authorizationDisabled) return;
|
|
4635
|
+
setAuthorizing(true);
|
|
4636
|
+
setError(null);
|
|
4637
|
+
try {
|
|
4638
|
+
await onAuthorize?.();
|
|
4639
|
+
} catch (cause) {
|
|
4640
|
+
setError(cause?.message ?? "\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
4641
|
+
} finally {
|
|
4642
|
+
setAuthorizing(false);
|
|
4643
|
+
}
|
|
4644
|
+
};
|
|
4645
|
+
return h2(
|
|
4646
|
+
"div",
|
|
4647
|
+
{ className: "bxf-responseMode dim-responseMode" },
|
|
4648
|
+
h2(
|
|
4649
|
+
"div",
|
|
4650
|
+
{ className: "bxf-responseModeHeader dim-responseModeHeader" },
|
|
4651
|
+
h2("span", null, "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F"),
|
|
4652
|
+
saving || authorizing ? h2(
|
|
4653
|
+
"span",
|
|
4654
|
+
{ className: "bxf-responseModeStatus dim-responseModeStatus" },
|
|
4655
|
+
saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026"
|
|
4656
|
+
) : null
|
|
4657
|
+
),
|
|
4658
|
+
h2(
|
|
4659
|
+
"select",
|
|
4660
|
+
{
|
|
4661
|
+
className: "bxf-responseModeSelect dim-responseModeSelect",
|
|
4662
|
+
value: current,
|
|
4663
|
+
disabled: disabled || saving,
|
|
4664
|
+
"aria-label": "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F",
|
|
4665
|
+
onChange: (event) => {
|
|
4666
|
+
void change(event);
|
|
4667
|
+
}
|
|
4668
|
+
},
|
|
4669
|
+
h2("option", { value: "mention" }, "\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09"),
|
|
4670
|
+
h2("option", { value: "all" }, "\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F")
|
|
4671
|
+
),
|
|
4672
|
+
h2(
|
|
4673
|
+
"small",
|
|
4674
|
+
{ className: "bxf-responseModeHelp dim-responseModeHelp" },
|
|
4675
|
+
current === "mention" ? permissionGranted ? "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002" : "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002" : permissionGranted ? "\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002" : "\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002"
|
|
4676
|
+
),
|
|
4677
|
+
current === "all" ? h2(
|
|
4678
|
+
"div",
|
|
4679
|
+
{ className: "bxf-responseModePermissionAction dim-responseModePermissionAction" },
|
|
4680
|
+
h2(Button5, {
|
|
4681
|
+
className: "bxf-responseModePermissionButton",
|
|
4682
|
+
size: "small",
|
|
4683
|
+
disabled: disabled || authorizationDisabled || saving || authorizing,
|
|
4684
|
+
"aria-busy": authorizing ? "true" : void 0,
|
|
4685
|
+
"aria-label": permissionGranted ? "\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650" : "\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650",
|
|
4686
|
+
onClick: () => {
|
|
4687
|
+
void authorize();
|
|
4688
|
+
}
|
|
4689
|
+
}, authorizing ? "\u6B63\u5728\u51C6\u5907\u2026" : permissionGranted ? "\u91CD\u65B0\u6388\u6743" : "\u53BB\u6388\u6743")
|
|
4690
|
+
) : null,
|
|
4691
|
+
error ? h2("p", {
|
|
4692
|
+
className: "bxf-responseModeError dim-responseModeError",
|
|
4693
|
+
role: "alert"
|
|
4694
|
+
}, error) : null
|
|
4695
|
+
);
|
|
4696
|
+
}
|
|
4295
4697
|
function BotCard({
|
|
4296
4698
|
connection,
|
|
4297
4699
|
busy,
|
|
4298
4700
|
repairDisabled,
|
|
4701
|
+
provisionContent,
|
|
4702
|
+
provisionRef,
|
|
4299
4703
|
actionError,
|
|
4300
4704
|
testNotice,
|
|
4301
4705
|
removing,
|
|
4302
4706
|
onReconnect,
|
|
4303
4707
|
onRepairCallback,
|
|
4304
4708
|
onWorkspaceSave,
|
|
4709
|
+
onAgentPresetSave,
|
|
4710
|
+
onGroupResponseModeSave,
|
|
4711
|
+
onGroupMessagePermissionAuthorize,
|
|
4305
4712
|
onRequestRemove,
|
|
4306
4713
|
onConfirmRemove,
|
|
4307
4714
|
onCancelRemove,
|
|
@@ -4371,6 +4778,26 @@ function BotCard({
|
|
|
4371
4778
|
disabled: Boolean(busy),
|
|
4372
4779
|
onSave: onWorkspaceSave
|
|
4373
4780
|
}),
|
|
4781
|
+
h2(AgentPresetEditor, {
|
|
4782
|
+
agentPreset: connection.agentPreset,
|
|
4783
|
+
disabled: Boolean(busy),
|
|
4784
|
+
onSave: onAgentPresetSave
|
|
4785
|
+
}),
|
|
4786
|
+
h2(GroupResponseModeEditor, {
|
|
4787
|
+
value: connection.groupResponseMode,
|
|
4788
|
+
permissionGranted: connection.groupMessagePermissionGranted,
|
|
4789
|
+
disabled: Boolean(busy),
|
|
4790
|
+
authorizationDisabled: repairDisabled,
|
|
4791
|
+
onSave: onGroupResponseModeSave,
|
|
4792
|
+
onAuthorize: onGroupMessagePermissionAuthorize
|
|
4793
|
+
}),
|
|
4794
|
+
provisionContent ? h2("section", {
|
|
4795
|
+
className: "bxf-botProvision dim-botProvision",
|
|
4796
|
+
"aria-label": `${bot.name}\u7684\u98DE\u4E66\u6388\u6743\u6D41\u7A0B`,
|
|
4797
|
+
"data-provision-for": connection.botId,
|
|
4798
|
+
ref: provisionRef,
|
|
4799
|
+
tabIndex: -1
|
|
4800
|
+
}, provisionContent) : null,
|
|
4374
4801
|
h2(
|
|
4375
4802
|
"div",
|
|
4376
4803
|
{ className: "bxf-connectedFooter dim-cardFooter" },
|
|
@@ -4436,14 +4863,19 @@ function BotList(props) {
|
|
|
4436
4863
|
{ key: bot.botId },
|
|
4437
4864
|
h2(BotCard, {
|
|
4438
4865
|
connection: bot,
|
|
4439
|
-
busy: props.busyByBot[bot.botId] ?? (
|
|
4866
|
+
busy: props.busyByBot[bot.botId] ?? (isTargetedAppUpdate2(props.provisioning) && props.provisioning.botId === bot.botId ? props.provisioning.operation : void 0),
|
|
4440
4867
|
repairDisabled: Boolean(props.provisioning),
|
|
4868
|
+
provisionContent: isTargetedAppUpdate2(props.provisioning) && props.provisioning.botId === bot.botId ? props.provisionContent : null,
|
|
4869
|
+
provisionRef: props.provisionRef,
|
|
4441
4870
|
actionError: props.errorsByBot[bot.botId],
|
|
4442
4871
|
testNotice: props.testNoticesByBot[bot.botId],
|
|
4443
4872
|
removing: props.removeTargetId === bot.botId,
|
|
4444
4873
|
onReconnect: () => props.onReconnect(bot),
|
|
4445
4874
|
onRepairCallback: () => props.onRepairCallback(bot),
|
|
4446
4875
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
|
|
4876
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
|
|
4877
|
+
onGroupResponseModeSave: (groupResponseMode) => props.onGroupResponseModeSave(bot, groupResponseMode),
|
|
4878
|
+
onGroupMessagePermissionAuthorize: () => props.onGroupMessagePermissionAuthorize(bot),
|
|
4447
4879
|
onRequestRemove: () => props.onRequestRemove(bot),
|
|
4448
4880
|
onConfirmRemove: () => props.onConfirmRemove(bot),
|
|
4449
4881
|
onCancelRemove: props.onCancelRemove,
|
|
@@ -4501,53 +4933,56 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
|
|
|
4501
4933
|
totals: snapshot.totals,
|
|
4502
4934
|
provisioning,
|
|
4503
4935
|
pageError: null,
|
|
4504
|
-
statusError: null
|
|
4936
|
+
statusError: null,
|
|
4937
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
4505
4938
|
};
|
|
4506
4939
|
}
|
|
4507
4940
|
function FeishuSettingsTab({ rpcCall }) {
|
|
4508
|
-
const [model, setModel] =
|
|
4941
|
+
const [model, setModel] = React11.useState({
|
|
4509
4942
|
phase: "loading",
|
|
4510
4943
|
revision: 0,
|
|
4511
4944
|
bots: [],
|
|
4512
4945
|
totals: EMPTY_TOTALS2,
|
|
4513
4946
|
provisioning: null,
|
|
4514
4947
|
pageError: null,
|
|
4515
|
-
statusError: null
|
|
4948
|
+
statusError: null,
|
|
4949
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
4516
4950
|
});
|
|
4517
|
-
const [pageBusy, setPageBusy] =
|
|
4518
|
-
const [provisionBusy, setProvisionBusy] =
|
|
4519
|
-
const [credentialOpen, setCredentialOpen] =
|
|
4520
|
-
const [credentialBusy, setCredentialBusy] =
|
|
4521
|
-
const [credentialError, setCredentialError] =
|
|
4522
|
-
const [busyByBot, setBusyByBot] =
|
|
4523
|
-
const [errorsByBot, setErrorsByBot] =
|
|
4524
|
-
const [testNoticesByBot, setTestNoticesByBot] =
|
|
4525
|
-
const [removeTargetId, setRemoveTargetId] =
|
|
4526
|
-
const [announcement, setAnnouncement] =
|
|
4527
|
-
const [now, setNow] =
|
|
4528
|
-
const [focusBotId, setFocusBotId] =
|
|
4529
|
-
const cardRefs =
|
|
4530
|
-
const removeButtonRefs =
|
|
4531
|
-
const
|
|
4532
|
-
const
|
|
4951
|
+
const [pageBusy, setPageBusy] = React11.useState(false);
|
|
4952
|
+
const [provisionBusy, setProvisionBusy] = React11.useState(false);
|
|
4953
|
+
const [credentialOpen, setCredentialOpen] = React11.useState(false);
|
|
4954
|
+
const [credentialBusy, setCredentialBusy] = React11.useState(false);
|
|
4955
|
+
const [credentialError, setCredentialError] = React11.useState(null);
|
|
4956
|
+
const [busyByBot, setBusyByBot] = React11.useState({});
|
|
4957
|
+
const [errorsByBot, setErrorsByBot] = React11.useState({});
|
|
4958
|
+
const [testNoticesByBot, setTestNoticesByBot] = React11.useState({});
|
|
4959
|
+
const [removeTargetId, setRemoveTargetId] = React11.useState(null);
|
|
4960
|
+
const [announcement, setAnnouncement] = React11.useState("");
|
|
4961
|
+
const [now, setNow] = React11.useState(() => Date.now());
|
|
4962
|
+
const [focusBotId, setFocusBotId] = React11.useState(null);
|
|
4963
|
+
const cardRefs = React11.useRef(/* @__PURE__ */ new Map());
|
|
4964
|
+
const removeButtonRefs = React11.useRef(/* @__PURE__ */ new Map());
|
|
4965
|
+
const targetedProvisionRef = React11.useRef(null);
|
|
4966
|
+
const addButtonRef = React11.useRef(null);
|
|
4967
|
+
const mountedRef = React11.useRef(true);
|
|
4533
4968
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
4534
4969
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
4535
|
-
|
|
4970
|
+
React11.useEffect(() => {
|
|
4536
4971
|
mountedRef.current = true;
|
|
4537
4972
|
return () => {
|
|
4538
4973
|
mountedRef.current = false;
|
|
4539
4974
|
};
|
|
4540
4975
|
}, []);
|
|
4541
|
-
const announce =
|
|
4976
|
+
const announce = React11.useCallback((message) => {
|
|
4542
4977
|
setAnnouncement("");
|
|
4543
4978
|
scheduleAnimationFrame(() => {
|
|
4544
4979
|
if (message) setAnnouncement(message);
|
|
4545
4980
|
}, "announcement");
|
|
4546
4981
|
}, [scheduleAnimationFrame]);
|
|
4547
|
-
const invoke =
|
|
4982
|
+
const invoke = React11.useCallback(async (endpoint, payload = {}, signal) => {
|
|
4548
4983
|
return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
|
|
4549
4984
|
}, [rpcCall]);
|
|
4550
|
-
const mergeSnapshot =
|
|
4985
|
+
const mergeSnapshot = React11.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
|
|
4551
4986
|
const now2 = Date.now();
|
|
4552
4987
|
setModel((current) => mergeFeishuSnapshotState(
|
|
4553
4988
|
current,
|
|
@@ -4555,7 +4990,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4555
4990
|
{ restoreProvisioning, now: now2 }
|
|
4556
4991
|
));
|
|
4557
4992
|
}, []);
|
|
4558
|
-
const loadStatus =
|
|
4993
|
+
const loadStatus = React11.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
|
|
4559
4994
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
4560
4995
|
if (workspaceVersion === null || !mountedRef.current) return void 0;
|
|
4561
4996
|
if (!silent) setPageBusy(true);
|
|
@@ -4573,12 +5008,12 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4573
5008
|
if (!silent && !signal?.aborted && mountedRef.current) setPageBusy(false);
|
|
4574
5009
|
}
|
|
4575
5010
|
}, [invoke, mergeSnapshot, workspaceFence]);
|
|
4576
|
-
|
|
5011
|
+
React11.useEffect(() => {
|
|
4577
5012
|
const controller = new AbortController();
|
|
4578
5013
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
4579
5014
|
return () => controller.abort();
|
|
4580
5015
|
}, [loadStatus]);
|
|
4581
|
-
|
|
5016
|
+
React11.useEffect(() => {
|
|
4582
5017
|
if (model.phase !== "ready") return void 0;
|
|
4583
5018
|
const controller = new AbortController();
|
|
4584
5019
|
let inFlight = false;
|
|
@@ -4597,7 +5032,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4597
5032
|
window.clearInterval(timer);
|
|
4598
5033
|
};
|
|
4599
5034
|
}, [loadStatus, model.phase]);
|
|
4600
|
-
|
|
5035
|
+
React11.useEffect(() => {
|
|
4601
5036
|
if (!focusBotId) return;
|
|
4602
5037
|
const node = cardRefs.current.get(focusBotId);
|
|
4603
5038
|
if (!node) return;
|
|
@@ -4605,15 +5040,27 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4605
5040
|
node.focus({ preventScroll: true });
|
|
4606
5041
|
setFocusBotId(null);
|
|
4607
5042
|
}, [focusBotId, model.bots]);
|
|
4608
|
-
const
|
|
5043
|
+
const targetedProvisionFocusKey = isTargetedAppUpdate2(model.provisioning) ? `${model.provisioning.botId}:${model.provisioning.attemptId ?? "preparing"}:${model.provisioning.phase}` : null;
|
|
5044
|
+
React11.useEffect(() => {
|
|
5045
|
+
if (!targetedProvisionFocusKey) return;
|
|
5046
|
+
scheduleAnimationFrame(() => {
|
|
5047
|
+
const node = targetedProvisionRef.current;
|
|
5048
|
+
if (!node) return;
|
|
5049
|
+
node.scrollIntoView?.({ block: "nearest", behavior: "smooth" });
|
|
5050
|
+
node.focus?.({ preventScroll: true });
|
|
5051
|
+
}, "targeted-provision-focus");
|
|
5052
|
+
}, [scheduleAnimationFrame, targetedProvisionFocusKey]);
|
|
5053
|
+
const startProvisioning = React11.useCallback(async ({
|
|
4609
5054
|
replace = false,
|
|
4610
5055
|
operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
|
|
4611
5056
|
bot
|
|
4612
5057
|
} = {}) => {
|
|
4613
5058
|
const repairing = operation === CALLBACK_REPAIR_OPERATION;
|
|
4614
|
-
const
|
|
4615
|
-
const
|
|
4616
|
-
|
|
5059
|
+
const grantingGroupMessages = operation === GROUP_MESSAGE_PERMISSION_OPERATION;
|
|
5060
|
+
const targetedUpdate = repairing || grantingGroupMessages;
|
|
5061
|
+
const botId = targetedUpdate ? bot?.botId ?? model.provisioning?.botId : void 0;
|
|
5062
|
+
const botName = targetedUpdate ? bot?.bot?.name ?? model.provisioning?.botName : void 0;
|
|
5063
|
+
if (targetedUpdate && !botId) return;
|
|
4617
5064
|
setCredentialOpen(false);
|
|
4618
5065
|
setCredentialError(null);
|
|
4619
5066
|
setProvisionBusy(true);
|
|
@@ -4636,12 +5083,13 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4636
5083
|
} catch {
|
|
4637
5084
|
}
|
|
4638
5085
|
}
|
|
5086
|
+
const endpoint = repairing ? FEISHU_ENDPOINTS.beginCallbackRepair : grantingGroupMessages ? FEISHU_ENDPOINTS.beginGroupMessagePermission : FEISHU_ENDPOINTS.beginProvisioning;
|
|
4639
5087
|
const provision2 = normalizeProvisioning2(await invoke(
|
|
4640
|
-
|
|
4641
|
-
|
|
5088
|
+
endpoint,
|
|
5089
|
+
targetedUpdate ? { botId } : { locale: "zh-CN" }
|
|
4642
5090
|
));
|
|
4643
|
-
if (
|
|
4644
|
-
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
|
|
5091
|
+
if (targetedUpdate && (provision2.operation !== operation || provision2.botId !== botId)) {
|
|
5092
|
+
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\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
|
|
4645
5093
|
}
|
|
4646
5094
|
const timestamp7 = Date.now();
|
|
4647
5095
|
setNow(timestamp7);
|
|
@@ -4655,7 +5103,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4655
5103
|
expired: false
|
|
4656
5104
|
}
|
|
4657
5105
|
}));
|
|
4658
|
-
announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
|
|
5106
|
+
announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : grantingGroupMessages ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
|
|
4659
5107
|
} catch (error) {
|
|
4660
5108
|
setModel((current) => ({
|
|
4661
5109
|
...current,
|
|
@@ -4678,7 +5126,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4678
5126
|
model.provisioning?.botId,
|
|
4679
5127
|
model.provisioning?.botName
|
|
4680
5128
|
]);
|
|
4681
|
-
const bindCredentials =
|
|
5129
|
+
const bindCredentials = React11.useCallback(async ({ identity, secret }) => {
|
|
4682
5130
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4683
5131
|
setCredentialBusy(true);
|
|
4684
5132
|
setCredentialError(null);
|
|
@@ -4700,16 +5148,18 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4700
5148
|
setCredentialBusy(false);
|
|
4701
5149
|
}
|
|
4702
5150
|
}, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
|
|
4703
|
-
const cancelProvisioning =
|
|
5151
|
+
const cancelProvisioning = React11.useCallback(async () => {
|
|
4704
5152
|
const activeProvision = model.provisioning;
|
|
4705
5153
|
const attemptId = activeProvision?.attemptId;
|
|
4706
5154
|
const repairing = isCallbackRepair(activeProvision);
|
|
4707
|
-
const
|
|
5155
|
+
const grantingGroupMessages = isGroupMessagePermission(activeProvision);
|
|
5156
|
+
const targetedUpdate = isTargetedAppUpdate2(activeProvision);
|
|
5157
|
+
const targetBot = targetedUpdate ? model.bots.find((bot) => bot.botId === activeProvision?.botId) : void 0;
|
|
4708
5158
|
setProvisionBusy(true);
|
|
4709
5159
|
try {
|
|
4710
5160
|
const result = attemptId ? normalizePollResult(await invoke(FEISHU_ENDPOINTS.cancelProvisioning, { attemptId })) : null;
|
|
4711
|
-
if (
|
|
4712
|
-
if (result.operation !==
|
|
5161
|
+
if (targetedUpdate && result) {
|
|
5162
|
+
if (result.operation !== activeProvision.operation || result.botId !== activeProvision.botId) {
|
|
4713
5163
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
|
|
4714
5164
|
}
|
|
4715
5165
|
if (result.status === "connecting") {
|
|
@@ -4723,23 +5173,23 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4723
5173
|
expired: false
|
|
4724
5174
|
}
|
|
4725
5175
|
} : current);
|
|
4726
|
-
announce("\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
|
|
5176
|
+
announce(grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
|
|
4727
5177
|
return;
|
|
4728
5178
|
}
|
|
4729
5179
|
if (result.status === "connected") {
|
|
4730
5180
|
const targetBotName = targetBot?.bot.name ?? activeProvision.botName ?? "\u673A\u5668\u4EBA";
|
|
4731
5181
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4732
|
-
announce(`${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
|
|
5182
|
+
announce(grantingGroupMessages ? `${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : `${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
|
|
4733
5183
|
if (activeProvision.botId) setFocusBotId(activeProvision.botId);
|
|
4734
5184
|
await loadStatus({ silent: true, restoreProvisioning: false });
|
|
4735
5185
|
return;
|
|
4736
5186
|
}
|
|
4737
5187
|
}
|
|
4738
5188
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4739
|
-
announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
|
|
5189
|
+
announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : grantingGroupMessages ? "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
|
|
4740
5190
|
await loadStatus({ silent: true, restoreProvisioning: false });
|
|
4741
5191
|
scheduleAnimationFrame(() => {
|
|
4742
|
-
if (
|
|
5192
|
+
if (targetedUpdate && activeProvision.botId) {
|
|
4743
5193
|
cardRefs.current.get(activeProvision.botId)?.focus();
|
|
4744
5194
|
} else {
|
|
4745
5195
|
addButtonRef.current?.focus();
|
|
@@ -4763,7 +5213,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4763
5213
|
const countdownPhase = model.provisioning?.phase;
|
|
4764
5214
|
const countdownExpiresAt = model.provisioning?.expiresAt;
|
|
4765
5215
|
const countdownExpired = model.provisioning?.expired;
|
|
4766
|
-
|
|
5216
|
+
React11.useEffect(() => {
|
|
4767
5217
|
if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
|
|
4768
5218
|
const tick = () => {
|
|
4769
5219
|
const timestamp7 = Date.now();
|
|
@@ -4776,7 +5226,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4776
5226
|
const timer = window.setInterval(tick, 1e3);
|
|
4777
5227
|
return () => window.clearInterval(timer);
|
|
4778
5228
|
}, [countdownAttemptId, countdownPhase, countdownExpiresAt, countdownExpired]);
|
|
4779
|
-
|
|
5229
|
+
React11.useEffect(() => {
|
|
4780
5230
|
const provision2 = model.provisioning;
|
|
4781
5231
|
if (!provision2 || !["qr", "connecting"].includes(provision2.phase) || !provision2.attemptId || provision2.expired) return void 0;
|
|
4782
5232
|
const controller = new AbortController();
|
|
@@ -4787,26 +5237,26 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4787
5237
|
{ attemptId: provision2.attemptId },
|
|
4788
5238
|
controller.signal
|
|
4789
5239
|
));
|
|
4790
|
-
if (result.operation !== provision2.operation ||
|
|
5240
|
+
if (result.operation !== provision2.operation || isTargetedAppUpdate2(provision2) && result.botId !== provision2.botId) {
|
|
4791
5241
|
throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
|
|
4792
5242
|
}
|
|
4793
5243
|
if (result.status === "connected") {
|
|
4794
5244
|
const snapshot = await loadStatus({ signal: controller.signal, silent: true, restoreProvisioning: false });
|
|
4795
5245
|
const targetBot = snapshot?.bots.find((bot) => bot.botId === result.botId);
|
|
4796
5246
|
if (!snapshot) {
|
|
4797
|
-
throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
|
|
5247
|
+
throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : isGroupMessagePermission(provision2) ? "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
|
|
4798
5248
|
}
|
|
4799
5249
|
if (!targetBot?.connected) {
|
|
4800
5250
|
setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? { ...current, provisioning: { ...current.provisioning, phase: "connecting" } } : current);
|
|
4801
5251
|
return;
|
|
4802
5252
|
}
|
|
4803
5253
|
setModel((current) => ({ ...current, provisioning: null }));
|
|
4804
|
-
announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
|
|
5254
|
+
announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : isGroupMessagePermission(provision2) ? `${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
|
|
4805
5255
|
if (result.botId) setFocusBotId(result.botId);
|
|
4806
5256
|
return;
|
|
4807
5257
|
}
|
|
4808
5258
|
if (result.status === "failed") {
|
|
4809
|
-
const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
|
|
5259
|
+
const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : isGroupMessagePermission(provision2) ? "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
|
|
4810
5260
|
error.code = "FEISHU_PROVISION_FAILED";
|
|
4811
5261
|
throw error;
|
|
4812
5262
|
}
|
|
@@ -4844,7 +5294,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4844
5294
|
window.clearTimeout(timer);
|
|
4845
5295
|
};
|
|
4846
5296
|
}, [announce, invoke, loadStatus, model.provisioning]);
|
|
4847
|
-
const setBotBusy =
|
|
5297
|
+
const setBotBusy = React11.useCallback((botId, value) => {
|
|
4848
5298
|
setBusyByBot((current) => {
|
|
4849
5299
|
const next = { ...current };
|
|
4850
5300
|
if (value) next[botId] = value;
|
|
@@ -4852,7 +5302,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4852
5302
|
return next;
|
|
4853
5303
|
});
|
|
4854
5304
|
}, []);
|
|
4855
|
-
const setBotError =
|
|
5305
|
+
const setBotError = React11.useCallback((botId, error) => {
|
|
4856
5306
|
setErrorsByBot((current) => {
|
|
4857
5307
|
const next = { ...current };
|
|
4858
5308
|
if (error) next[botId] = presentError3(error);
|
|
@@ -4860,7 +5310,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4860
5310
|
return next;
|
|
4861
5311
|
});
|
|
4862
5312
|
}, []);
|
|
4863
|
-
const repairCallback =
|
|
5313
|
+
const repairCallback = React11.useCallback((connection) => {
|
|
4864
5314
|
if (model.provisioning) return;
|
|
4865
5315
|
setRemoveTargetId(null);
|
|
4866
5316
|
setBotError(connection.botId, null);
|
|
@@ -4874,7 +5324,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4874
5324
|
bot: connection
|
|
4875
5325
|
});
|
|
4876
5326
|
}, [model.provisioning, setBotError, startProvisioning]);
|
|
4877
|
-
const reconnectOneBot =
|
|
5327
|
+
const reconnectOneBot = React11.useCallback(async (connection) => {
|
|
4878
5328
|
const { botId, bot } = connection;
|
|
4879
5329
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4880
5330
|
setBotBusy(botId, "reconnect");
|
|
@@ -4914,7 +5364,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4914
5364
|
setBotBusy(botId, null);
|
|
4915
5365
|
}
|
|
4916
5366
|
}, [announce, invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
4917
|
-
const saveWorkspace =
|
|
5367
|
+
const saveWorkspace = React11.useCallback(async (connection, workspace) => {
|
|
4918
5368
|
const { botId } = connection;
|
|
4919
5369
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
4920
5370
|
setBotBusy(botId, "workspace");
|
|
@@ -4933,15 +5383,82 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4933
5383
|
if (mountedRef.current) setBotBusy(botId, null);
|
|
4934
5384
|
}
|
|
4935
5385
|
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
4936
|
-
const
|
|
5386
|
+
const saveAgentPreset = React11.useCallback(async (connection, agentPreset) => {
|
|
5387
|
+
const { botId } = connection;
|
|
5388
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
5389
|
+
setBotBusy(botId, "preset");
|
|
5390
|
+
setBotError(botId, null);
|
|
5391
|
+
try {
|
|
5392
|
+
const snapshot = normalizeBotsSnapshot(await invoke(
|
|
5393
|
+
FEISHU_ENDPOINTS.setAgentPreset,
|
|
5394
|
+
{ botId, agentPreset }
|
|
5395
|
+
));
|
|
5396
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5397
|
+
mergeSnapshot(snapshot);
|
|
5398
|
+
}
|
|
5399
|
+
} finally {
|
|
5400
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
5401
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
5402
|
+
if (mountedRef.current) setBotBusy(botId, null);
|
|
5403
|
+
}
|
|
5404
|
+
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
5405
|
+
const authorizeGroupMessages = React11.useCallback(async (connection) => {
|
|
5406
|
+
const { botId } = connection;
|
|
5407
|
+
if (model.provisioning) {
|
|
5408
|
+
throw new Error("\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002");
|
|
5409
|
+
}
|
|
5410
|
+
setRemoveTargetId(null);
|
|
5411
|
+
setBotError(botId, null);
|
|
5412
|
+
setTestNoticesByBot((current) => {
|
|
5413
|
+
const next = { ...current };
|
|
5414
|
+
delete next[botId];
|
|
5415
|
+
return next;
|
|
5416
|
+
});
|
|
5417
|
+
await startProvisioning({
|
|
5418
|
+
operation: GROUP_MESSAGE_PERMISSION_OPERATION,
|
|
5419
|
+
bot: connection
|
|
5420
|
+
});
|
|
5421
|
+
}, [model.provisioning, setBotError, startProvisioning]);
|
|
5422
|
+
const saveGroupResponseMode = React11.useCallback(async (connection, groupResponseMode) => {
|
|
5423
|
+
const { botId } = connection;
|
|
5424
|
+
if (groupResponseMode === "all" && connection.groupMessagePermissionGranted !== true) {
|
|
5425
|
+
await authorizeGroupMessages(connection);
|
|
5426
|
+
return;
|
|
5427
|
+
}
|
|
5428
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
5429
|
+
setBotBusy(botId, "group-response-mode");
|
|
5430
|
+
setBotError(botId, null);
|
|
5431
|
+
try {
|
|
5432
|
+
const snapshot = normalizeBotsSnapshot(await invoke(
|
|
5433
|
+
FEISHU_ENDPOINTS.setGroupResponseMode,
|
|
5434
|
+
{ botId, groupResponseMode }
|
|
5435
|
+
));
|
|
5436
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5437
|
+
mergeSnapshot(snapshot);
|
|
5438
|
+
}
|
|
5439
|
+
} finally {
|
|
5440
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
5441
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
5442
|
+
if (mountedRef.current) setBotBusy(botId, null);
|
|
5443
|
+
}
|
|
5444
|
+
}, [
|
|
5445
|
+
invoke,
|
|
5446
|
+
authorizeGroupMessages,
|
|
5447
|
+
loadStatus,
|
|
5448
|
+
mergeSnapshot,
|
|
5449
|
+
setBotBusy,
|
|
5450
|
+
setBotError,
|
|
5451
|
+
workspaceFence
|
|
5452
|
+
]);
|
|
5453
|
+
const requestRemove = React11.useCallback((connection) => {
|
|
4937
5454
|
setRemoveTargetId(connection.botId);
|
|
4938
5455
|
}, []);
|
|
4939
|
-
const cancelRemove =
|
|
5456
|
+
const cancelRemove = React11.useCallback(() => {
|
|
4940
5457
|
const botId = removeTargetId;
|
|
4941
5458
|
setRemoveTargetId(null);
|
|
4942
5459
|
scheduleAnimationFrame(() => removeButtonRefs.current.get(botId)?.focus(), "focus");
|
|
4943
5460
|
}, [removeTargetId, scheduleAnimationFrame]);
|
|
4944
|
-
const confirmRemove =
|
|
5461
|
+
const confirmRemove = React11.useCallback(async (connection) => {
|
|
4945
5462
|
const { botId, bot } = connection;
|
|
4946
5463
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4947
5464
|
setBotBusy(botId, "delete");
|
|
@@ -4967,6 +5484,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4967
5484
|
}
|
|
4968
5485
|
}, [announce, invoke, loadStatus, mergeSnapshot, scheduleAnimationFrame, setBotBusy, setBotError, workspaceFence]);
|
|
4969
5486
|
const provision = model.provisioning;
|
|
5487
|
+
const targetedProvisioning = isTargetedAppUpdate2(provision);
|
|
4970
5488
|
const provisionBot = provision?.botId ? model.bots.find((bot) => bot.botId === provision.botId) ?? { botId: provision.botId, bot: { name: provision.botName ?? "\u6B64\u673A\u5668\u4EBA" } } : void 0;
|
|
4971
5489
|
const restartProvisioning = ({ replace = false } = {}) => startProvisioning({
|
|
4972
5490
|
replace,
|
|
@@ -4992,7 +5510,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4992
5510
|
provisionContent = h2(ProvisionProgress, {
|
|
4993
5511
|
phase: "connecting",
|
|
4994
5512
|
provision,
|
|
4995
|
-
onCancel:
|
|
5513
|
+
onCancel: isTargetedAppUpdate2(provision) ? void 0 : () => void cancelProvisioning(),
|
|
4996
5514
|
busy: provisionBusy
|
|
4997
5515
|
});
|
|
4998
5516
|
} else if (provision?.phase === "error") {
|
|
@@ -5026,15 +5544,17 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5026
5544
|
setCredentialError(null);
|
|
5027
5545
|
}
|
|
5028
5546
|
}) : null;
|
|
5029
|
-
const setCardRef =
|
|
5547
|
+
const setCardRef = React11.useCallback((botId, node) => {
|
|
5030
5548
|
if (node) cardRefs.current.set(botId, node);
|
|
5031
5549
|
else cardRefs.current.delete(botId);
|
|
5032
5550
|
}, []);
|
|
5033
|
-
const setRemoveButtonRef =
|
|
5551
|
+
const setRemoveButtonRef = React11.useCallback((botId, node) => {
|
|
5034
5552
|
if (node) removeButtonRefs.current.set(botId, node);
|
|
5035
5553
|
else removeButtonRefs.current.delete(botId);
|
|
5036
5554
|
}, []);
|
|
5037
|
-
return h2(
|
|
5555
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
5556
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
5557
|
+
}, h2(
|
|
5038
5558
|
"section",
|
|
5039
5559
|
{ className: "bxf-page dim-channelPage", "aria-label": "\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E" },
|
|
5040
5560
|
h2(Heading2, {
|
|
@@ -5067,10 +5587,10 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5067
5587
|
onRetry: () => void loadStatus(),
|
|
5068
5588
|
busy: pageBusy
|
|
5069
5589
|
}) : h2(
|
|
5070
|
-
|
|
5590
|
+
React11.Fragment,
|
|
5071
5591
|
null,
|
|
5072
5592
|
credentialContent,
|
|
5073
|
-
provisionContent,
|
|
5593
|
+
targetedProvisioning ? null : provisionContent,
|
|
5074
5594
|
model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView2, { onStart: () => void startProvisioning(), busy: provisionBusy }) : null,
|
|
5075
5595
|
model.bots.length > 0 ? h2(BotList, {
|
|
5076
5596
|
bots: model.bots,
|
|
@@ -5079,9 +5599,14 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5079
5599
|
testNoticesByBot,
|
|
5080
5600
|
removeTargetId,
|
|
5081
5601
|
provisioning: provision,
|
|
5602
|
+
provisionContent,
|
|
5603
|
+
provisionRef: targetedProvisionRef,
|
|
5082
5604
|
onReconnect: (bot) => void reconnectOneBot(bot),
|
|
5083
5605
|
onRepairCallback: repairCallback,
|
|
5084
5606
|
onWorkspaceSave: saveWorkspace,
|
|
5607
|
+
onAgentPresetSave: saveAgentPreset,
|
|
5608
|
+
onGroupResponseModeSave: saveGroupResponseMode,
|
|
5609
|
+
onGroupMessagePermissionAuthorize: authorizeGroupMessages,
|
|
5085
5610
|
onRequestRemove: requestRemove,
|
|
5086
5611
|
onConfirmRemove: (bot) => void confirmRemove(bot),
|
|
5087
5612
|
onCancelRemove: cancelRemove,
|
|
@@ -5089,7 +5614,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5089
5614
|
setRemoveButtonRef
|
|
5090
5615
|
}) : null
|
|
5091
5616
|
)
|
|
5092
|
-
);
|
|
5617
|
+
));
|
|
5093
5618
|
}
|
|
5094
5619
|
|
|
5095
5620
|
// plugin-src/client/channels/qq/api.js
|
|
@@ -5102,7 +5627,8 @@ var QQ_ENDPOINTS = Object.freeze({
|
|
|
5102
5627
|
bindCredentials: "bot.bind-credentials",
|
|
5103
5628
|
reconnectBot: "bot.reconnect",
|
|
5104
5629
|
deleteBot: "bot.delete",
|
|
5105
|
-
setWorkspace: "bot.workspace.set"
|
|
5630
|
+
setWorkspace: "bot.workspace.set",
|
|
5631
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
5106
5632
|
});
|
|
5107
5633
|
var PROVISION_STATES2 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
|
|
5108
5634
|
var ACCOUNT_STATES3 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -5166,6 +5692,7 @@ function normalizeBot3(value) {
|
|
|
5166
5692
|
connected,
|
|
5167
5693
|
state: connected ? "connected" : state,
|
|
5168
5694
|
workspace: text2(value.workspace, "", 4096),
|
|
5695
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
5169
5696
|
bot: {
|
|
5170
5697
|
name: text2(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
|
|
5171
5698
|
appIdMasked: text2(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
|
|
@@ -5199,6 +5726,7 @@ function normalizeSnapshot3(value) {
|
|
|
5199
5726
|
bots,
|
|
5200
5727
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
5201
5728
|
provisioning: source.provisioning ? normalizeProvisioning3(source.provisioning) : null,
|
|
5729
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
5202
5730
|
...testMessage ? { testMessage } : {}
|
|
5203
5731
|
};
|
|
5204
5732
|
}
|
|
@@ -5221,7 +5749,7 @@ function formatRemaining3(milliseconds) {
|
|
|
5221
5749
|
}
|
|
5222
5750
|
|
|
5223
5751
|
// plugin-src/client/channels/qq/index.js
|
|
5224
|
-
var
|
|
5752
|
+
var React12 = __toESM(require("react"), 1);
|
|
5225
5753
|
|
|
5226
5754
|
// plugin-src/client/channels/qq/styles.js
|
|
5227
5755
|
var QQ_STYLE_ID = "xmanrui-dsh-im-qq-settings";
|
|
@@ -5246,7 +5774,7 @@ function installQqStyles() {
|
|
|
5246
5774
|
|
|
5247
5775
|
// plugin-src/client/channels/qq/index.js
|
|
5248
5776
|
var ACTIVE_STATES = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
|
|
5249
|
-
var Button7 =
|
|
5777
|
+
var Button7 = React12.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
5250
5778
|
return h2("button", {
|
|
5251
5779
|
...props,
|
|
5252
5780
|
ref,
|
|
@@ -5460,6 +5988,7 @@ function AccountCard2({
|
|
|
5460
5988
|
removing,
|
|
5461
5989
|
onReconnect,
|
|
5462
5990
|
onWorkspaceSave,
|
|
5991
|
+
onAgentPresetSave,
|
|
5463
5992
|
onRequestRemove,
|
|
5464
5993
|
onConfirmRemove,
|
|
5465
5994
|
onCancelRemove
|
|
@@ -5505,6 +6034,11 @@ function AccountCard2({
|
|
|
5505
6034
|
disabled: Boolean(busy),
|
|
5506
6035
|
onSave: onWorkspaceSave
|
|
5507
6036
|
}),
|
|
6037
|
+
h2(AgentPresetEditor, {
|
|
6038
|
+
agentPreset: account.agentPreset,
|
|
6039
|
+
disabled: Boolean(busy),
|
|
6040
|
+
onSave: onAgentPresetSave
|
|
6041
|
+
}),
|
|
5508
6042
|
h2(
|
|
5509
6043
|
"div",
|
|
5510
6044
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -5531,19 +6065,25 @@ function AccountCard2({
|
|
|
5531
6065
|
);
|
|
5532
6066
|
}
|
|
5533
6067
|
function QqSettingsTab({ rpcCall }) {
|
|
5534
|
-
const [model, setModel] =
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
const [
|
|
5542
|
-
const [
|
|
5543
|
-
const
|
|
6068
|
+
const [model, setModel] = React12.useState({
|
|
6069
|
+
phase: "loading",
|
|
6070
|
+
bots: [],
|
|
6071
|
+
totals: { configured: 0, connected: 0 },
|
|
6072
|
+
error: null,
|
|
6073
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
6074
|
+
});
|
|
6075
|
+
const [provision, setProvision] = React12.useState(null);
|
|
6076
|
+
const [busy, setBusy] = React12.useState(false);
|
|
6077
|
+
const [busyByBot, setBusyByBot] = React12.useState({});
|
|
6078
|
+
const [feedbackByBot, setFeedbackByBot] = React12.useState({});
|
|
6079
|
+
const [removeTarget, setRemoveTarget] = React12.useState(null);
|
|
6080
|
+
const [credentialOpen, setCredentialOpen] = React12.useState(false);
|
|
6081
|
+
const [credentialError, setCredentialError] = React12.useState(null);
|
|
6082
|
+
const [now, setNow] = React12.useState(Date.now());
|
|
6083
|
+
const mounted = React12.useRef(true);
|
|
5544
6084
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
5545
|
-
const addButtonRef =
|
|
5546
|
-
|
|
6085
|
+
const addButtonRef = React12.useRef(null);
|
|
6086
|
+
React12.useEffect(() => {
|
|
5547
6087
|
const disposeDingtalk = installDingtalkStyles();
|
|
5548
6088
|
const disposeQq = installQqStyles();
|
|
5549
6089
|
mounted.current = true;
|
|
@@ -5553,18 +6093,24 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5553
6093
|
disposeDingtalk();
|
|
5554
6094
|
};
|
|
5555
6095
|
}, []);
|
|
5556
|
-
const invoke =
|
|
6096
|
+
const invoke = React12.useCallback(async (endpoint, payload = {}, signal) => {
|
|
5557
6097
|
if (typeof rpcCall !== "function") throw new TypeError("QQ \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
5558
6098
|
return unwrapRpcResult4(await rpcCall(endpoint, payload, signal));
|
|
5559
6099
|
}, [rpcCall]);
|
|
5560
|
-
const loadStatus =
|
|
6100
|
+
const loadStatus = React12.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
5561
6101
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
5562
6102
|
if (workspaceVersion === null) return void 0;
|
|
5563
6103
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
5564
6104
|
try {
|
|
5565
6105
|
const snapshot = normalizeSnapshot3(await invoke(QQ_ENDPOINTS.status, {}, signal));
|
|
5566
6106
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
5567
|
-
setModel({
|
|
6107
|
+
setModel({
|
|
6108
|
+
phase: "ready",
|
|
6109
|
+
bots: snapshot.bots,
|
|
6110
|
+
totals: snapshot.totals,
|
|
6111
|
+
error: null,
|
|
6112
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
6113
|
+
});
|
|
5568
6114
|
if (restore && snapshot.provisioning) setProvision({
|
|
5569
6115
|
...snapshot.provisioning,
|
|
5570
6116
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -5577,12 +6123,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5577
6123
|
return void 0;
|
|
5578
6124
|
}
|
|
5579
6125
|
}, [invoke, workspaceFence]);
|
|
5580
|
-
|
|
6126
|
+
React12.useEffect(() => {
|
|
5581
6127
|
const controller = new AbortController();
|
|
5582
6128
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
5583
6129
|
return () => controller.abort();
|
|
5584
6130
|
}, [loadStatus]);
|
|
5585
|
-
|
|
6131
|
+
React12.useEffect(() => {
|
|
5586
6132
|
if (model.phase !== "ready") return void 0;
|
|
5587
6133
|
const controller = new AbortController();
|
|
5588
6134
|
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
@@ -5591,12 +6137,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5591
6137
|
window.clearInterval(timer);
|
|
5592
6138
|
};
|
|
5593
6139
|
}, [loadStatus, model.phase]);
|
|
5594
|
-
|
|
6140
|
+
React12.useEffect(() => {
|
|
5595
6141
|
if (!provision || !ACTIVE_STATES.has(provision.status)) return void 0;
|
|
5596
6142
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
5597
6143
|
return () => window.clearInterval(timer);
|
|
5598
6144
|
}, [provision?.attemptId, provision?.status]);
|
|
5599
|
-
const startProvisioning =
|
|
6145
|
+
const startProvisioning = React12.useCallback(async (replace = false) => {
|
|
5600
6146
|
setCredentialOpen(false);
|
|
5601
6147
|
setCredentialError(null);
|
|
5602
6148
|
setBusy(true);
|
|
@@ -5614,7 +6160,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5614
6160
|
if (mounted.current) setBusy(false);
|
|
5615
6161
|
}
|
|
5616
6162
|
}, [invoke, provision?.attemptId]);
|
|
5617
|
-
const bindCredentials =
|
|
6163
|
+
const bindCredentials = React12.useCallback(async ({ identity, secret }) => {
|
|
5618
6164
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
5619
6165
|
setBusy(true);
|
|
5620
6166
|
setCredentialError(null);
|
|
@@ -5625,7 +6171,13 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5625
6171
|
));
|
|
5626
6172
|
if (!mounted.current) return;
|
|
5627
6173
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5628
|
-
setModel({
|
|
6174
|
+
setModel({
|
|
6175
|
+
phase: "ready",
|
|
6176
|
+
bots: snapshot.bots,
|
|
6177
|
+
totals: snapshot.totals,
|
|
6178
|
+
error: null,
|
|
6179
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
6180
|
+
});
|
|
5629
6181
|
}
|
|
5630
6182
|
setCredentialOpen(false);
|
|
5631
6183
|
} catch (error) {
|
|
@@ -5636,7 +6188,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5636
6188
|
if (mounted.current) setBusy(false);
|
|
5637
6189
|
}
|
|
5638
6190
|
}, [invoke, loadStatus, workspaceFence]);
|
|
5639
|
-
const closeProvision =
|
|
6191
|
+
const closeProvision = React12.useCallback(async () => {
|
|
5640
6192
|
setBusy(true);
|
|
5641
6193
|
try {
|
|
5642
6194
|
if (provision?.attemptId && ACTIVE_STATES.has(provision.status)) {
|
|
@@ -5647,7 +6199,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5647
6199
|
if (mounted.current) setBusy(false);
|
|
5648
6200
|
}
|
|
5649
6201
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
5650
|
-
|
|
6202
|
+
React12.useEffect(() => {
|
|
5651
6203
|
const attemptId = provision?.attemptId;
|
|
5652
6204
|
if (!attemptId || !ACTIVE_STATES.has(provision.status)) return void 0;
|
|
5653
6205
|
const controller = new AbortController();
|
|
@@ -5677,13 +6229,19 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5677
6229
|
window.clearTimeout(timer);
|
|
5678
6230
|
};
|
|
5679
6231
|
}, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
5680
|
-
const botAction =
|
|
6232
|
+
const botAction = React12.useCallback(async (account, operation, endpoint, payload) => {
|
|
5681
6233
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
5682
6234
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
5683
6235
|
try {
|
|
5684
6236
|
const snapshot = normalizeSnapshot3(await invoke(endpoint, payload));
|
|
5685
6237
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5686
|
-
setModel({
|
|
6238
|
+
setModel({
|
|
6239
|
+
phase: "ready",
|
|
6240
|
+
bots: snapshot.bots,
|
|
6241
|
+
totals: snapshot.totals,
|
|
6242
|
+
error: null,
|
|
6243
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
6244
|
+
});
|
|
5687
6245
|
}
|
|
5688
6246
|
return snapshot;
|
|
5689
6247
|
} finally {
|
|
@@ -5696,7 +6254,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5696
6254
|
});
|
|
5697
6255
|
}
|
|
5698
6256
|
}, [invoke, loadStatus, workspaceFence]);
|
|
5699
|
-
const reconnect =
|
|
6257
|
+
const reconnect = React12.useCallback(async (account) => {
|
|
5700
6258
|
setFeedbackByBot((current) => {
|
|
5701
6259
|
const next = { ...current };
|
|
5702
6260
|
delete next[account.botId];
|
|
@@ -5759,6 +6317,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5759
6317
|
QQ_ENDPOINTS.setWorkspace,
|
|
5760
6318
|
{ botId: account.botId, workspace }
|
|
5761
6319
|
),
|
|
6320
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
6321
|
+
account,
|
|
6322
|
+
"preset",
|
|
6323
|
+
QQ_ENDPOINTS.setAgentPreset,
|
|
6324
|
+
{ botId: account.botId, agentPreset }
|
|
6325
|
+
),
|
|
5762
6326
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
5763
6327
|
onCancelRemove: () => setRemoveTarget(null),
|
|
5764
6328
|
onConfirmRemove: async () => {
|
|
@@ -5781,7 +6345,9 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5781
6345
|
setCredentialError(null);
|
|
5782
6346
|
}
|
|
5783
6347
|
}) : null;
|
|
5784
|
-
return h2(
|
|
6348
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
6349
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
6350
|
+
}, h2(
|
|
5785
6351
|
"section",
|
|
5786
6352
|
{ className: "ddt-page dqq-page dim-channelPage", "aria-label": "QQ \u8BBE\u7F6E" },
|
|
5787
6353
|
h2(Heading3, {
|
|
@@ -5797,14 +6363,14 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5797
6363
|
addButtonRef
|
|
5798
6364
|
}),
|
|
5799
6365
|
model.phase === "loading" ? h2(LoadingView3) : model.phase === "error" ? h2("div", { className: "ddt-card dim-surfaceCard" }, h2("div", { className: "ddt-inlineError dim-inlineError" }, h2("h3", null, "\u65E0\u6CD5\u8BFB\u53D6 QQ \u673A\u5668\u4EBA\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button7, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
|
|
5800
|
-
|
|
6366
|
+
React12.Fragment,
|
|
5801
6367
|
null,
|
|
5802
6368
|
credentialView,
|
|
5803
6369
|
provisionView,
|
|
5804
6370
|
model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView3, { busy, onStart: () => void startProvisioning() }) : null,
|
|
5805
6371
|
botList
|
|
5806
6372
|
)
|
|
5807
|
-
);
|
|
6373
|
+
));
|
|
5808
6374
|
}
|
|
5809
6375
|
|
|
5810
6376
|
// src/channels/office/protocol.mjs
|
|
@@ -5886,7 +6452,7 @@ function normalizeOfficeStatus(value) {
|
|
|
5886
6452
|
}
|
|
5887
6453
|
|
|
5888
6454
|
// plugin-src/client/channels/office/index.js
|
|
5889
|
-
var
|
|
6455
|
+
var React13 = __toESM(require("react"), 1);
|
|
5890
6456
|
function Button9({ children, kind = "secondary", ...props }) {
|
|
5891
6457
|
return h2("button", { ...props, type: "button", className: "ddt-button", "data-kind": kind }, children);
|
|
5892
6458
|
}
|
|
@@ -5915,12 +6481,12 @@ function stateLabel(model) {
|
|
|
5915
6481
|
return "\u5DF2\u914D\u7F6E";
|
|
5916
6482
|
}
|
|
5917
6483
|
function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
5918
|
-
const [model, setModel] =
|
|
5919
|
-
const [phase, setPhase] =
|
|
5920
|
-
const [busy, setBusy] =
|
|
5921
|
-
const [error, setError] =
|
|
5922
|
-
const [notice, setNotice] =
|
|
5923
|
-
const [form, setForm] =
|
|
6484
|
+
const [model, setModel] = React13.useState(normalizeOfficeStatus(initialStatus));
|
|
6485
|
+
const [phase, setPhase] = React13.useState(initialStatus === void 0 ? "loading" : "ready");
|
|
6486
|
+
const [busy, setBusy] = React13.useState("");
|
|
6487
|
+
const [error, setError] = React13.useState("");
|
|
6488
|
+
const [notice, setNotice] = React13.useState("");
|
|
6489
|
+
const [form, setForm] = React13.useState({
|
|
5924
6490
|
baseUrl: "",
|
|
5925
6491
|
deviceId: "local-harness",
|
|
5926
6492
|
deviceToken: "",
|
|
@@ -5929,11 +6495,11 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5929
6495
|
workspaces: "",
|
|
5930
6496
|
instructionPresets: ""
|
|
5931
6497
|
});
|
|
5932
|
-
const invoke =
|
|
6498
|
+
const invoke = React13.useCallback(async (endpoint, payload = {}) => {
|
|
5933
6499
|
if (typeof rpcCall !== "function") throw new Error("AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
5934
6500
|
return unwrapOfficeRpc(await rpcCall(endpoint, payload));
|
|
5935
6501
|
}, [rpcCall]);
|
|
5936
|
-
const adopt =
|
|
6502
|
+
const adopt = React13.useCallback((value) => {
|
|
5937
6503
|
const next = normalizeOfficeStatus(value?.snapshot ?? value);
|
|
5938
6504
|
setModel(next);
|
|
5939
6505
|
if (next.config) setForm((current) => ({
|
|
@@ -5948,7 +6514,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5948
6514
|
}));
|
|
5949
6515
|
return next;
|
|
5950
6516
|
}, []);
|
|
5951
|
-
const load =
|
|
6517
|
+
const load = React13.useCallback(async () => {
|
|
5952
6518
|
try {
|
|
5953
6519
|
adopt(await invoke(OFFICE_RPC_ENDPOINTS.status));
|
|
5954
6520
|
setPhase("ready");
|
|
@@ -5958,7 +6524,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5958
6524
|
setError(caught.message);
|
|
5959
6525
|
}
|
|
5960
6526
|
}, [adopt, invoke]);
|
|
5961
|
-
|
|
6527
|
+
React13.useEffect(() => {
|
|
5962
6528
|
void load();
|
|
5963
6529
|
}, [load]);
|
|
5964
6530
|
const run = async (name2, operation) => {
|
|
@@ -5975,7 +6541,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5975
6541
|
setBusy("");
|
|
5976
6542
|
}
|
|
5977
6543
|
};
|
|
5978
|
-
const hooks =
|
|
6544
|
+
const hooks = React13.useMemo(() => {
|
|
5979
6545
|
try {
|
|
5980
6546
|
return officeHookUrls(form.baseUrl);
|
|
5981
6547
|
} catch {
|
|
@@ -6160,7 +6726,7 @@ var normalizeSnapshot4 = api2.normalizeSnapshot;
|
|
|
6160
6726
|
var presentError5 = api2.presentError;
|
|
6161
6727
|
|
|
6162
6728
|
// plugin-src/client/channels/slack/index.js
|
|
6163
|
-
var
|
|
6729
|
+
var React14 = __toESM(require("react"), 1);
|
|
6164
6730
|
|
|
6165
6731
|
// src/channels/slack/manifest.mjs
|
|
6166
6732
|
var SLACK_APP_MANIFEST_YAML = `_metadata:
|
|
@@ -6233,10 +6799,10 @@ function installSlackStyles() {
|
|
|
6233
6799
|
|
|
6234
6800
|
// plugin-src/client/channels/slack/index.js
|
|
6235
6801
|
function SlackCredentialPanel({ busy, error, onSubmit, onCancel }) {
|
|
6236
|
-
const [botToken, setBotToken] =
|
|
6237
|
-
const [appToken, setAppToken] =
|
|
6238
|
-
const [copied, setCopied] =
|
|
6239
|
-
const headingId =
|
|
6802
|
+
const [botToken, setBotToken] = React14.useState("");
|
|
6803
|
+
const [appToken, setAppToken] = React14.useState("");
|
|
6804
|
+
const [copied, setCopied] = React14.useState(false);
|
|
6805
|
+
const headingId = React14.useId();
|
|
6240
6806
|
const copyManifest = async () => {
|
|
6241
6807
|
try {
|
|
6242
6808
|
await navigator.clipboard.writeText(SLACK_APP_MANIFEST_YAML);
|
|
@@ -6392,7 +6958,7 @@ var normalizeSnapshot5 = api3.normalizeSnapshot;
|
|
|
6392
6958
|
var presentError6 = api3.presentError;
|
|
6393
6959
|
|
|
6394
6960
|
// plugin-src/client/channels/telegram/index.js
|
|
6395
|
-
var
|
|
6961
|
+
var React15 = __toESM(require("react"), 1);
|
|
6396
6962
|
|
|
6397
6963
|
// plugin-src/client/channels/telegram/styles.js
|
|
6398
6964
|
var TELEGRAM_STYLE_ID = "xmanrui-dsh-im-telegram-settings";
|
|
@@ -6458,11 +7024,11 @@ function allowedUsersFromText(value) {
|
|
|
6458
7024
|
function TelegramAccessSettings({ account, busy = false, onSave }) {
|
|
6459
7025
|
const policy = policyFor(account);
|
|
6460
7026
|
const sourceUsers = policy.allowedUsers.join("\n");
|
|
6461
|
-
const accessHelpId =
|
|
6462
|
-
const [accessMode, setAccessMode] =
|
|
6463
|
-
const [allowedUsers, setAllowedUsers] =
|
|
6464
|
-
const [error, setError] =
|
|
6465
|
-
|
|
7027
|
+
const accessHelpId = React15.useId();
|
|
7028
|
+
const [accessMode, setAccessMode] = React15.useState(policy.accessMode);
|
|
7029
|
+
const [allowedUsers, setAllowedUsers] = React15.useState(sourceUsers);
|
|
7030
|
+
const [error, setError] = React15.useState(null);
|
|
7031
|
+
React15.useEffect(() => {
|
|
6466
7032
|
setAccessMode(policy.accessMode);
|
|
6467
7033
|
setAllowedUsers(sourceUsers);
|
|
6468
7034
|
setError(null);
|
|
@@ -6611,7 +7177,8 @@ var WECOM_ENDPOINTS = Object.freeze({
|
|
|
6611
7177
|
bindCredentials: "bot.bind-credentials",
|
|
6612
7178
|
reconnectBot: "bot.reconnect",
|
|
6613
7179
|
deleteBot: "bot.delete",
|
|
6614
|
-
setWorkspace: "bot.workspace.set"
|
|
7180
|
+
setWorkspace: "bot.workspace.set",
|
|
7181
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
6615
7182
|
});
|
|
6616
7183
|
var PROVISION_STATES3 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
|
|
6617
7184
|
var ACCOUNT_STATES4 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -6681,6 +7248,7 @@ function normalizeBot4(value) {
|
|
|
6681
7248
|
connected,
|
|
6682
7249
|
state: connected ? "connected" : state,
|
|
6683
7250
|
workspace: text3(value.workspace, "", 4096),
|
|
7251
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
6684
7252
|
bot: {
|
|
6685
7253
|
name: text3(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
|
|
6686
7254
|
appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
|
|
@@ -6704,7 +7272,8 @@ function normalizeSnapshot6(value) {
|
|
|
6704
7272
|
bots,
|
|
6705
7273
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
6706
7274
|
provisioning: source.provisioning ? normalizeProvisioning4(source.provisioning) : null,
|
|
6707
|
-
testMessage: normalizeTestMessage3(source.testMessage)
|
|
7275
|
+
testMessage: normalizeTestMessage3(source.testMessage),
|
|
7276
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
6708
7277
|
};
|
|
6709
7278
|
}
|
|
6710
7279
|
function presentError7(error) {
|
|
@@ -6719,7 +7288,7 @@ function formatRemaining4(milliseconds) {
|
|
|
6719
7288
|
}
|
|
6720
7289
|
|
|
6721
7290
|
// plugin-src/client/channels/wecom/index.js
|
|
6722
|
-
var
|
|
7291
|
+
var React16 = __toESM(require("react"), 1);
|
|
6723
7292
|
|
|
6724
7293
|
// plugin-src/client/channels/wecom/styles.js
|
|
6725
7294
|
var WECOM_STYLE_ID = "xmanrui-dsh-im-wecom-settings";
|
|
@@ -6744,7 +7313,7 @@ function installWecomStyles() {
|
|
|
6744
7313
|
|
|
6745
7314
|
// plugin-src/client/channels/wecom/index.js
|
|
6746
7315
|
var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
|
|
6747
|
-
var Button10 =
|
|
7316
|
+
var Button10 = React16.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
6748
7317
|
return h2("button", {
|
|
6749
7318
|
...props,
|
|
6750
7319
|
ref,
|
|
@@ -6958,6 +7527,7 @@ function AccountCard3({
|
|
|
6958
7527
|
removing,
|
|
6959
7528
|
onReconnect,
|
|
6960
7529
|
onWorkspaceSave,
|
|
7530
|
+
onAgentPresetSave,
|
|
6961
7531
|
onRequestRemove,
|
|
6962
7532
|
onConfirmRemove,
|
|
6963
7533
|
onCancelRemove
|
|
@@ -7003,6 +7573,11 @@ function AccountCard3({
|
|
|
7003
7573
|
disabled: Boolean(busy),
|
|
7004
7574
|
onSave: onWorkspaceSave
|
|
7005
7575
|
}),
|
|
7576
|
+
h2(AgentPresetEditor, {
|
|
7577
|
+
agentPreset: account.agentPreset,
|
|
7578
|
+
disabled: Boolean(busy),
|
|
7579
|
+
onSave: onAgentPresetSave
|
|
7580
|
+
}),
|
|
7006
7581
|
h2(
|
|
7007
7582
|
"div",
|
|
7008
7583
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -7029,21 +7604,27 @@ function AccountCard3({
|
|
|
7029
7604
|
);
|
|
7030
7605
|
}
|
|
7031
7606
|
function WecomSettingsTab({ rpcCall }) {
|
|
7032
|
-
const [model, setModel] =
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
const [
|
|
7040
|
-
const [
|
|
7041
|
-
const [
|
|
7042
|
-
const
|
|
7607
|
+
const [model, setModel] = React16.useState({
|
|
7608
|
+
phase: "loading",
|
|
7609
|
+
bots: [],
|
|
7610
|
+
totals: { configured: 0, connected: 0 },
|
|
7611
|
+
error: null,
|
|
7612
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
7613
|
+
});
|
|
7614
|
+
const [provision, setProvision] = React16.useState(null);
|
|
7615
|
+
const [busy, setBusy] = React16.useState(false);
|
|
7616
|
+
const [busyByBot, setBusyByBot] = React16.useState({});
|
|
7617
|
+
const [feedbackByBot, setFeedbackByBot] = React16.useState({});
|
|
7618
|
+
const [removeTarget, setRemoveTarget] = React16.useState(null);
|
|
7619
|
+
const [credentialOpen, setCredentialOpen] = React16.useState(false);
|
|
7620
|
+
const [credentialError, setCredentialError] = React16.useState(null);
|
|
7621
|
+
const [notice, setNotice] = React16.useState("");
|
|
7622
|
+
const [now, setNow] = React16.useState(Date.now());
|
|
7623
|
+
const mounted = React16.useRef(true);
|
|
7043
7624
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
7044
|
-
const addButtonRef =
|
|
7045
|
-
const noticeFrameRef =
|
|
7046
|
-
const announce =
|
|
7625
|
+
const addButtonRef = React16.useRef(null);
|
|
7626
|
+
const noticeFrameRef = React16.useRef(null);
|
|
7627
|
+
const announce = React16.useCallback((message) => {
|
|
7047
7628
|
if (!mounted.current) return;
|
|
7048
7629
|
if (noticeFrameRef.current !== null) {
|
|
7049
7630
|
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
@@ -7057,7 +7638,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7057
7638
|
});
|
|
7058
7639
|
}
|
|
7059
7640
|
}, []);
|
|
7060
|
-
|
|
7641
|
+
React16.useEffect(() => {
|
|
7061
7642
|
const disposeDingtalk = installDingtalkStyles();
|
|
7062
7643
|
const disposeWecom = installWecomStyles();
|
|
7063
7644
|
mounted.current = true;
|
|
@@ -7071,18 +7652,24 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7071
7652
|
disposeDingtalk();
|
|
7072
7653
|
};
|
|
7073
7654
|
}, []);
|
|
7074
|
-
const invoke =
|
|
7655
|
+
const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
|
|
7075
7656
|
if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
7076
7657
|
return unwrapRpcResult7(await rpcCall(endpoint, payload, signal));
|
|
7077
7658
|
}, [rpcCall]);
|
|
7078
|
-
const loadStatus =
|
|
7659
|
+
const loadStatus = React16.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
7079
7660
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
7080
7661
|
if (workspaceVersion === null) return void 0;
|
|
7081
7662
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
7082
7663
|
try {
|
|
7083
7664
|
const snapshot = normalizeSnapshot6(await invoke(WECOM_ENDPOINTS.status, {}, signal));
|
|
7084
7665
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
7085
|
-
setModel({
|
|
7666
|
+
setModel({
|
|
7667
|
+
phase: "ready",
|
|
7668
|
+
bots: snapshot.bots,
|
|
7669
|
+
totals: snapshot.totals,
|
|
7670
|
+
error: null,
|
|
7671
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7672
|
+
});
|
|
7086
7673
|
if (restore && snapshot.provisioning) setProvision({
|
|
7087
7674
|
...snapshot.provisioning,
|
|
7088
7675
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -7095,12 +7682,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7095
7682
|
return void 0;
|
|
7096
7683
|
}
|
|
7097
7684
|
}, [invoke, workspaceFence]);
|
|
7098
|
-
|
|
7685
|
+
React16.useEffect(() => {
|
|
7099
7686
|
const controller = new AbortController();
|
|
7100
7687
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
7101
7688
|
return () => controller.abort();
|
|
7102
7689
|
}, [loadStatus]);
|
|
7103
|
-
|
|
7690
|
+
React16.useEffect(() => {
|
|
7104
7691
|
if (model.phase !== "ready") return void 0;
|
|
7105
7692
|
const controller = new AbortController();
|
|
7106
7693
|
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
@@ -7109,12 +7696,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7109
7696
|
window.clearInterval(timer);
|
|
7110
7697
|
};
|
|
7111
7698
|
}, [loadStatus, model.phase]);
|
|
7112
|
-
|
|
7699
|
+
React16.useEffect(() => {
|
|
7113
7700
|
if (!provision || !ACTIVE_STATES2.has(provision.status)) return void 0;
|
|
7114
7701
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
7115
7702
|
return () => window.clearInterval(timer);
|
|
7116
7703
|
}, [provision?.attemptId, provision?.status]);
|
|
7117
|
-
const startProvisioning =
|
|
7704
|
+
const startProvisioning = React16.useCallback(async (replace = false) => {
|
|
7118
7705
|
setCredentialOpen(false);
|
|
7119
7706
|
setCredentialError(null);
|
|
7120
7707
|
setBusy(true);
|
|
@@ -7132,7 +7719,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7132
7719
|
if (mounted.current) setBusy(false);
|
|
7133
7720
|
}
|
|
7134
7721
|
}, [invoke, provision?.attemptId]);
|
|
7135
|
-
const bindCredentials =
|
|
7722
|
+
const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
|
|
7136
7723
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
7137
7724
|
setBusy(true);
|
|
7138
7725
|
setCredentialError(null);
|
|
@@ -7143,7 +7730,13 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7143
7730
|
));
|
|
7144
7731
|
if (!mounted.current) return;
|
|
7145
7732
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
7146
|
-
setModel({
|
|
7733
|
+
setModel({
|
|
7734
|
+
phase: "ready",
|
|
7735
|
+
bots: snapshot.bots,
|
|
7736
|
+
totals: snapshot.totals,
|
|
7737
|
+
error: null,
|
|
7738
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7739
|
+
});
|
|
7147
7740
|
}
|
|
7148
7741
|
setCredentialOpen(false);
|
|
7149
7742
|
} catch (error) {
|
|
@@ -7154,7 +7747,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7154
7747
|
if (mounted.current) setBusy(false);
|
|
7155
7748
|
}
|
|
7156
7749
|
}, [invoke, loadStatus, workspaceFence]);
|
|
7157
|
-
const closeProvision =
|
|
7750
|
+
const closeProvision = React16.useCallback(async () => {
|
|
7158
7751
|
setBusy(true);
|
|
7159
7752
|
try {
|
|
7160
7753
|
if (provision?.attemptId && ACTIVE_STATES2.has(provision.status)) {
|
|
@@ -7165,7 +7758,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7165
7758
|
if (mounted.current) setBusy(false);
|
|
7166
7759
|
}
|
|
7167
7760
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
7168
|
-
|
|
7761
|
+
React16.useEffect(() => {
|
|
7169
7762
|
const attemptId = provision?.attemptId;
|
|
7170
7763
|
if (!attemptId || !ACTIVE_STATES2.has(provision.status)) return void 0;
|
|
7171
7764
|
const controller = new AbortController();
|
|
@@ -7195,13 +7788,19 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7195
7788
|
window.clearTimeout(timer);
|
|
7196
7789
|
};
|
|
7197
7790
|
}, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
7198
|
-
const botAction =
|
|
7791
|
+
const botAction = React16.useCallback(async (account, operation, endpoint, payload) => {
|
|
7199
7792
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
7200
7793
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
7201
7794
|
try {
|
|
7202
7795
|
const snapshot = normalizeSnapshot6(await invoke(endpoint, payload));
|
|
7203
7796
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
7204
|
-
setModel({
|
|
7797
|
+
setModel({
|
|
7798
|
+
phase: "ready",
|
|
7799
|
+
bots: snapshot.bots,
|
|
7800
|
+
totals: snapshot.totals,
|
|
7801
|
+
error: null,
|
|
7802
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7803
|
+
});
|
|
7205
7804
|
}
|
|
7206
7805
|
return snapshot;
|
|
7207
7806
|
} finally {
|
|
@@ -7214,7 +7813,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7214
7813
|
});
|
|
7215
7814
|
}
|
|
7216
7815
|
}, [invoke, loadStatus, workspaceFence]);
|
|
7217
|
-
const reconnect =
|
|
7816
|
+
const reconnect = React16.useCallback(async (account) => {
|
|
7218
7817
|
setFeedbackByBot((current) => {
|
|
7219
7818
|
const next = { ...current };
|
|
7220
7819
|
delete next[account.botId];
|
|
@@ -7288,6 +7887,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7288
7887
|
WECOM_ENDPOINTS.setWorkspace,
|
|
7289
7888
|
{ botId: account.botId, workspace }
|
|
7290
7889
|
),
|
|
7890
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
7891
|
+
account,
|
|
7892
|
+
"preset",
|
|
7893
|
+
WECOM_ENDPOINTS.setAgentPreset,
|
|
7894
|
+
{ botId: account.botId, agentPreset }
|
|
7895
|
+
),
|
|
7291
7896
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
7292
7897
|
onCancelRemove: () => setRemoveTarget(null),
|
|
7293
7898
|
onConfirmRemove: async () => {
|
|
@@ -7310,7 +7915,9 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7310
7915
|
setCredentialError(null);
|
|
7311
7916
|
}
|
|
7312
7917
|
}) : null;
|
|
7313
|
-
return h2(
|
|
7918
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
7919
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7920
|
+
}, h2(
|
|
7314
7921
|
"section",
|
|
7315
7922
|
{ className: "ddt-page dwecom-page dim-channelPage", "aria-label": "\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
7316
7923
|
h2(Heading4, {
|
|
@@ -7327,18 +7934,18 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7327
7934
|
}),
|
|
7328
7935
|
h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
7329
7936
|
model.phase === "loading" ? h2(LoadingView4) : 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\u673A\u5668\u4EBA\u72B6\u6001"), h2("p", null, model.error?.message), h2(Button10, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6"))) : h2(
|
|
7330
|
-
|
|
7937
|
+
React16.Fragment,
|
|
7331
7938
|
null,
|
|
7332
7939
|
credentialView,
|
|
7333
7940
|
provisionView,
|
|
7334
7941
|
model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView4, { busy, onStart: () => void startProvisioning() }) : null,
|
|
7335
7942
|
botList
|
|
7336
7943
|
)
|
|
7337
|
-
);
|
|
7944
|
+
));
|
|
7338
7945
|
}
|
|
7339
7946
|
|
|
7340
7947
|
// plugin-src/client/channels/weixin/index.js
|
|
7341
|
-
var
|
|
7948
|
+
var React17 = __toESM(require("react"), 1);
|
|
7342
7949
|
|
|
7343
7950
|
// plugin-src/client/channels/weixin/api.js
|
|
7344
7951
|
var WEIXIN_RPC_CHANNEL = "/weixin";
|
|
@@ -7350,7 +7957,8 @@ var WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
7350
7957
|
cancelProvisioning: "provision.cancel",
|
|
7351
7958
|
reconnectBot: "bot.reconnect",
|
|
7352
7959
|
deleteBot: "bot.delete",
|
|
7353
|
-
setWorkspace: "bot.workspace.set"
|
|
7960
|
+
setWorkspace: "bot.workspace.set",
|
|
7961
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
7354
7962
|
});
|
|
7355
7963
|
var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
7356
7964
|
var PROVISION_STATES4 = /* @__PURE__ */ new Set([
|
|
@@ -7448,6 +8056,7 @@ function normalizeBot5(value) {
|
|
|
7448
8056
|
connected,
|
|
7449
8057
|
configured: value.configured === true,
|
|
7450
8058
|
workspace: string(value.workspace).slice(0, 4096),
|
|
8059
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
7451
8060
|
bot: {
|
|
7452
8061
|
name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
|
|
7453
8062
|
accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
|
|
@@ -7483,7 +8092,8 @@ function normalizeSnapshot7(value) {
|
|
|
7483
8092
|
connected: bots.filter((bot) => bot.connected).length
|
|
7484
8093
|
},
|
|
7485
8094
|
provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
|
|
7486
|
-
testMessage: normalizeTestMessage4(value.testMessage)
|
|
8095
|
+
testMessage: normalizeTestMessage4(value.testMessage),
|
|
8096
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog)
|
|
7487
8097
|
};
|
|
7488
8098
|
}
|
|
7489
8099
|
function presentError8(error) {
|
|
@@ -7620,7 +8230,7 @@ function installWeixinStyles() {
|
|
|
7620
8230
|
}
|
|
7621
8231
|
|
|
7622
8232
|
// plugin-src/client/channels/weixin/index.js
|
|
7623
|
-
var Button12 =
|
|
8233
|
+
var Button12 = React17.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
7624
8234
|
return h2("button", {
|
|
7625
8235
|
...props,
|
|
7626
8236
|
ref,
|
|
@@ -7693,14 +8303,14 @@ function EmptyView5({ onStart, busy }) {
|
|
|
7693
8303
|
);
|
|
7694
8304
|
}
|
|
7695
8305
|
function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
7696
|
-
const [imageFailed, setImageFailed] =
|
|
8306
|
+
const [imageFailed, setImageFailed] = React17.useState(false);
|
|
7697
8307
|
const source = safeQrSource5(provision.qrCodeDataUrl);
|
|
7698
8308
|
const href = safeVerificationUrl(provision.verificationUrl);
|
|
7699
8309
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
7700
8310
|
const expired = remaining === 0 || provision.status === "expired";
|
|
7701
8311
|
const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
|
|
7702
8312
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
7703
|
-
|
|
8313
|
+
React17.useEffect(() => setImageFailed(false), [source]);
|
|
7704
8314
|
return h2(
|
|
7705
8315
|
"div",
|
|
7706
8316
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -7767,9 +8377,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
7767
8377
|
);
|
|
7768
8378
|
}
|
|
7769
8379
|
function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
7770
|
-
const [code, setCode] =
|
|
8380
|
+
const [code, setCode] = React17.useState("");
|
|
7771
8381
|
const valid = /^\d{4,8}$/.test(code);
|
|
7772
|
-
|
|
8382
|
+
React17.useEffect(() => setCode(""), [provision.attemptId]);
|
|
7773
8383
|
return h2(
|
|
7774
8384
|
"div",
|
|
7775
8385
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -7867,6 +8477,7 @@ function AccountCard4({
|
|
|
7867
8477
|
removing,
|
|
7868
8478
|
onReconnect,
|
|
7869
8479
|
onWorkspaceSave,
|
|
8480
|
+
onAgentPresetSave,
|
|
7870
8481
|
onRequestRemove,
|
|
7871
8482
|
onConfirmRemove,
|
|
7872
8483
|
onCancelRemove
|
|
@@ -7917,6 +8528,11 @@ function AccountCard4({
|
|
|
7917
8528
|
disabled: Boolean(busy),
|
|
7918
8529
|
onSave: onWorkspaceSave
|
|
7919
8530
|
}),
|
|
8531
|
+
h2(AgentPresetEditor, {
|
|
8532
|
+
agentPreset: account.agentPreset,
|
|
8533
|
+
disabled: Boolean(busy),
|
|
8534
|
+
onSave: onAgentPresetSave
|
|
8535
|
+
}),
|
|
7920
8536
|
h2(
|
|
7921
8537
|
"div",
|
|
7922
8538
|
{ className: "dxw-accountFooter dim-cardFooter" },
|
|
@@ -7975,6 +8591,7 @@ function AccountList2(props) {
|
|
|
7975
8591
|
removing: props.removeTarget === account.botId,
|
|
7976
8592
|
onReconnect: () => props.onReconnect(account),
|
|
7977
8593
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
8594
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
7978
8595
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
7979
8596
|
onConfirmRemove: () => props.onConfirmRemove(account),
|
|
7980
8597
|
onCancelRemove: props.onCancelRemove
|
|
@@ -7993,40 +8610,41 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
|
|
|
7993
8610
|
};
|
|
7994
8611
|
}
|
|
7995
8612
|
function WeixinSettingsTab({ rpcCall }) {
|
|
7996
|
-
const [model, setModel] =
|
|
8613
|
+
const [model, setModel] = React17.useState({
|
|
7997
8614
|
phase: "loading",
|
|
7998
8615
|
bots: [],
|
|
7999
8616
|
totals: EMPTY_TOTALS3,
|
|
8000
8617
|
revision: 0,
|
|
8001
|
-
error: null
|
|
8618
|
+
error: null,
|
|
8619
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
8002
8620
|
});
|
|
8003
|
-
const [provision, setProvision] =
|
|
8004
|
-
const [busy, setBusy] =
|
|
8005
|
-
const [busyByBot, setBusyByBot] =
|
|
8006
|
-
const [feedbackByBot, setFeedbackByBot] =
|
|
8007
|
-
const [removeTarget, setRemoveTarget] =
|
|
8008
|
-
const [notice, setNotice] =
|
|
8009
|
-
const [now, setNow] =
|
|
8010
|
-
const addButtonRef =
|
|
8011
|
-
const mountedRef =
|
|
8621
|
+
const [provision, setProvision] = React17.useState(null);
|
|
8622
|
+
const [busy, setBusy] = React17.useState(false);
|
|
8623
|
+
const [busyByBot, setBusyByBot] = React17.useState({});
|
|
8624
|
+
const [feedbackByBot, setFeedbackByBot] = React17.useState({});
|
|
8625
|
+
const [removeTarget, setRemoveTarget] = React17.useState(null);
|
|
8626
|
+
const [notice, setNotice] = React17.useState("");
|
|
8627
|
+
const [now, setNow] = React17.useState(() => Date.now());
|
|
8628
|
+
const addButtonRef = React17.useRef(null);
|
|
8629
|
+
const mountedRef = React17.useRef(true);
|
|
8012
8630
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
8013
8631
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
8014
|
-
|
|
8632
|
+
React17.useEffect(() => {
|
|
8015
8633
|
mountedRef.current = true;
|
|
8016
8634
|
return () => {
|
|
8017
8635
|
mountedRef.current = false;
|
|
8018
8636
|
};
|
|
8019
8637
|
}, []);
|
|
8020
|
-
const announce =
|
|
8638
|
+
const announce = React17.useCallback((value) => {
|
|
8021
8639
|
setNotice("");
|
|
8022
8640
|
scheduleAnimationFrame(() => {
|
|
8023
8641
|
if (value) setNotice(value);
|
|
8024
8642
|
}, "announcement");
|
|
8025
8643
|
}, [scheduleAnimationFrame]);
|
|
8026
|
-
const invoke =
|
|
8644
|
+
const invoke = React17.useCallback(async (endpoint, payload = {}, signal) => {
|
|
8027
8645
|
return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
|
|
8028
8646
|
}, [rpcCall]);
|
|
8029
|
-
const loadStatus =
|
|
8647
|
+
const loadStatus = React17.useCallback(async ({
|
|
8030
8648
|
signal,
|
|
8031
8649
|
silent = false,
|
|
8032
8650
|
restoreProvisioning = false
|
|
@@ -8042,7 +8660,8 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8042
8660
|
bots: snapshot.bots,
|
|
8043
8661
|
totals: snapshot.totals,
|
|
8044
8662
|
revision: snapshot.revision,
|
|
8045
|
-
error: null
|
|
8663
|
+
error: null,
|
|
8664
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8046
8665
|
});
|
|
8047
8666
|
if (snapshot.provisioning) {
|
|
8048
8667
|
setProvision((current) => mergeWeixinProvisioningSnapshot(
|
|
@@ -8062,12 +8681,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8062
8681
|
return void 0;
|
|
8063
8682
|
}
|
|
8064
8683
|
}, [invoke, workspaceFence]);
|
|
8065
|
-
|
|
8684
|
+
React17.useEffect(() => {
|
|
8066
8685
|
const controller = new AbortController();
|
|
8067
8686
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
8068
8687
|
return () => controller.abort();
|
|
8069
8688
|
}, [loadStatus]);
|
|
8070
|
-
|
|
8689
|
+
React17.useEffect(() => {
|
|
8071
8690
|
if (model.phase !== "ready") return void 0;
|
|
8072
8691
|
const controller = new AbortController();
|
|
8073
8692
|
let running = false;
|
|
@@ -8086,12 +8705,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8086
8705
|
window.clearInterval(timer);
|
|
8087
8706
|
};
|
|
8088
8707
|
}, [loadStatus, model.phase]);
|
|
8089
|
-
|
|
8708
|
+
React17.useEffect(() => {
|
|
8090
8709
|
if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
|
|
8091
8710
|
const timer = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
8092
8711
|
return () => window.clearInterval(timer);
|
|
8093
8712
|
}, [provision?.attemptId, provision?.status]);
|
|
8094
|
-
const startProvisioning =
|
|
8713
|
+
const startProvisioning = React17.useCallback(async ({ replace = false } = {}) => {
|
|
8095
8714
|
setBusy(true);
|
|
8096
8715
|
try {
|
|
8097
8716
|
if (replace && provision?.attemptId) {
|
|
@@ -8112,7 +8731,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8112
8731
|
setBusy(false);
|
|
8113
8732
|
}
|
|
8114
8733
|
}, [announce, invoke, provision?.attemptId]);
|
|
8115
|
-
const cancelProvisioning =
|
|
8734
|
+
const cancelProvisioning = React17.useCallback(async () => {
|
|
8116
8735
|
setBusy(true);
|
|
8117
8736
|
try {
|
|
8118
8737
|
if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
|
|
@@ -8127,7 +8746,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8127
8746
|
setBusy(false);
|
|
8128
8747
|
}
|
|
8129
8748
|
}, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
|
|
8130
|
-
const submitVerification =
|
|
8749
|
+
const submitVerification = React17.useCallback(async (verifyCode) => {
|
|
8131
8750
|
if (!provision?.attemptId) return;
|
|
8132
8751
|
setBusy(true);
|
|
8133
8752
|
try {
|
|
@@ -8143,7 +8762,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8143
8762
|
setBusy(false);
|
|
8144
8763
|
}
|
|
8145
8764
|
}, [announce, invoke, provision?.attemptId]);
|
|
8146
|
-
|
|
8765
|
+
React17.useEffect(() => {
|
|
8147
8766
|
const attemptId = provision?.attemptId;
|
|
8148
8767
|
if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
|
|
8149
8768
|
const controller = new AbortController();
|
|
@@ -8191,7 +8810,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8191
8810
|
controller.abort();
|
|
8192
8811
|
};
|
|
8193
8812
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
|
|
8194
|
-
const setBotBusy =
|
|
8813
|
+
const setBotBusy = React17.useCallback((botId, value) => {
|
|
8195
8814
|
setBusyByBot((current) => {
|
|
8196
8815
|
const next = { ...current };
|
|
8197
8816
|
if (value) next[botId] = value;
|
|
@@ -8199,7 +8818,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8199
8818
|
return next;
|
|
8200
8819
|
});
|
|
8201
8820
|
}, []);
|
|
8202
|
-
const reconnect =
|
|
8821
|
+
const reconnect = React17.useCallback(async (account) => {
|
|
8203
8822
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8204
8823
|
setBotBusy(account.botId, "reconnect");
|
|
8205
8824
|
setFeedbackByBot((current) => {
|
|
@@ -8213,7 +8832,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8213
8832
|
{ botId: account.botId, sendTest: true }
|
|
8214
8833
|
));
|
|
8215
8834
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8216
|
-
setModel((current) => ({
|
|
8835
|
+
setModel((current) => ({
|
|
8836
|
+
...current,
|
|
8837
|
+
bots: snapshot.bots,
|
|
8838
|
+
totals: snapshot.totals,
|
|
8839
|
+
revision: snapshot.revision,
|
|
8840
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
8841
|
+
}));
|
|
8217
8842
|
}
|
|
8218
8843
|
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
8219
8844
|
let feedback;
|
|
@@ -8244,7 +8869,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8244
8869
|
setBotBusy(account.botId, null);
|
|
8245
8870
|
}
|
|
8246
8871
|
}, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8247
|
-
const saveWorkspace =
|
|
8872
|
+
const saveWorkspace = React17.useCallback(async (account, workspace) => {
|
|
8248
8873
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
8249
8874
|
setBotBusy(account.botId, "workspace");
|
|
8250
8875
|
try {
|
|
@@ -8258,7 +8883,32 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8258
8883
|
bots: snapshot.bots,
|
|
8259
8884
|
totals: snapshot.totals,
|
|
8260
8885
|
revision: snapshot.revision,
|
|
8261
|
-
error: null
|
|
8886
|
+
error: null,
|
|
8887
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8888
|
+
});
|
|
8889
|
+
}
|
|
8890
|
+
} finally {
|
|
8891
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
8892
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
8893
|
+
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
8894
|
+
}
|
|
8895
|
+
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8896
|
+
const saveAgentPreset = React17.useCallback(async (account, agentPreset) => {
|
|
8897
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
8898
|
+
setBotBusy(account.botId, "preset");
|
|
8899
|
+
try {
|
|
8900
|
+
const snapshot = normalizeSnapshot7(await invoke(
|
|
8901
|
+
WEIXIN_ENDPOINTS.setAgentPreset,
|
|
8902
|
+
{ botId: account.botId, agentPreset }
|
|
8903
|
+
));
|
|
8904
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8905
|
+
setModel({
|
|
8906
|
+
phase: "ready",
|
|
8907
|
+
bots: snapshot.bots,
|
|
8908
|
+
totals: snapshot.totals,
|
|
8909
|
+
revision: snapshot.revision,
|
|
8910
|
+
error: null,
|
|
8911
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8262
8912
|
});
|
|
8263
8913
|
}
|
|
8264
8914
|
} finally {
|
|
@@ -8267,7 +8917,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8267
8917
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
8268
8918
|
}
|
|
8269
8919
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8270
|
-
const remove =
|
|
8920
|
+
const remove = React17.useCallback(async (account) => {
|
|
8271
8921
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8272
8922
|
setBotBusy(account.botId, "delete");
|
|
8273
8923
|
try {
|
|
@@ -8276,7 +8926,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8276
8926
|
confirm: true
|
|
8277
8927
|
}));
|
|
8278
8928
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8279
|
-
setModel((current) => ({
|
|
8929
|
+
setModel((current) => ({
|
|
8930
|
+
...current,
|
|
8931
|
+
bots: snapshot.bots,
|
|
8932
|
+
totals: snapshot.totals,
|
|
8933
|
+
revision: snapshot.revision,
|
|
8934
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
8935
|
+
}));
|
|
8280
8936
|
}
|
|
8281
8937
|
setRemoveTarget(null);
|
|
8282
8938
|
announce("\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002");
|
|
@@ -8320,7 +8976,9 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8320
8976
|
onClose: () => void cancelProvisioning()
|
|
8321
8977
|
});
|
|
8322
8978
|
}
|
|
8323
|
-
return h2(
|
|
8979
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
8980
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8981
|
+
}, h2(
|
|
8324
8982
|
"section",
|
|
8325
8983
|
{ className: "dxw-page dim-channelPage", "aria-label": "\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
8326
8984
|
h2(Heading5, {
|
|
@@ -8343,7 +9001,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8343
9001
|
h2(Button12, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
8344
9002
|
)
|
|
8345
9003
|
) : h2(
|
|
8346
|
-
|
|
9004
|
+
React17.Fragment,
|
|
8347
9005
|
null,
|
|
8348
9006
|
provisionView,
|
|
8349
9007
|
model.bots.length === 0 && !provision ? h2(EmptyView5, { onStart: () => void startProvisioning(), busy }) : null,
|
|
@@ -8354,12 +9012,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8354
9012
|
removeTarget,
|
|
8355
9013
|
onReconnect: (account) => void reconnect(account),
|
|
8356
9014
|
onWorkspaceSave: saveWorkspace,
|
|
9015
|
+
onAgentPresetSave: saveAgentPreset,
|
|
8357
9016
|
onRequestRemove: (account) => setRemoveTarget(account.botId),
|
|
8358
9017
|
onConfirmRemove: (account) => void remove(account),
|
|
8359
9018
|
onCancelRemove: () => setRemoveTarget(null)
|
|
8360
9019
|
}) : null
|
|
8361
9020
|
)
|
|
8362
|
-
);
|
|
9021
|
+
));
|
|
8363
9022
|
}
|
|
8364
9023
|
|
|
8365
9024
|
// plugin-src/client/channels/whatsapp/api.js
|
|
@@ -8371,7 +9030,8 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
8371
9030
|
cancelProvisioning: "provision.cancel",
|
|
8372
9031
|
reconnectBot: "bot.reconnect",
|
|
8373
9032
|
deleteBot: "bot.delete",
|
|
8374
|
-
setWorkspace: "bot.workspace.set"
|
|
9033
|
+
setWorkspace: "bot.workspace.set",
|
|
9034
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
8375
9035
|
});
|
|
8376
9036
|
var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
|
|
8377
9037
|
var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -8436,6 +9096,7 @@ function normalizeBot6(value) {
|
|
|
8436
9096
|
connected,
|
|
8437
9097
|
state: connected ? "connected" : state,
|
|
8438
9098
|
workspace: text4(value.workspace, "", 4096),
|
|
9099
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
8439
9100
|
bot: {
|
|
8440
9101
|
name: text4(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
|
|
8441
9102
|
idMasked: text4(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
|
|
@@ -8460,7 +9121,8 @@ function normalizeSnapshot8(value) {
|
|
|
8460
9121
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
8461
9122
|
bots,
|
|
8462
9123
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
8463
|
-
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null
|
|
9124
|
+
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null,
|
|
9125
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
8464
9126
|
};
|
|
8465
9127
|
}
|
|
8466
9128
|
function presentError9(error) {
|
|
@@ -8475,7 +9137,7 @@ function formatRemaining6(milliseconds) {
|
|
|
8475
9137
|
}
|
|
8476
9138
|
|
|
8477
9139
|
// plugin-src/client/channels/whatsapp/index.js
|
|
8478
|
-
var
|
|
9140
|
+
var React18 = __toESM(require("react"), 1);
|
|
8479
9141
|
|
|
8480
9142
|
// plugin-src/client/channels/whatsapp/styles.js
|
|
8481
9143
|
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
|
@@ -8500,7 +9162,7 @@ function installWhatsappStyles() {
|
|
|
8500
9162
|
|
|
8501
9163
|
// plugin-src/client/channels/whatsapp/index.js
|
|
8502
9164
|
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
|
8503
|
-
var Button14 =
|
|
9165
|
+
var Button14 = React18.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
8504
9166
|
return h2("button", {
|
|
8505
9167
|
...props,
|
|
8506
9168
|
ref,
|
|
@@ -8722,6 +9384,7 @@ function WhatsappAccountCard({
|
|
|
8722
9384
|
removing,
|
|
8723
9385
|
onReconnect,
|
|
8724
9386
|
onWorkspaceSave,
|
|
9387
|
+
onAgentPresetSave,
|
|
8725
9388
|
onRequestRemove,
|
|
8726
9389
|
onConfirmRemove,
|
|
8727
9390
|
onCancelRemove
|
|
@@ -8781,6 +9444,11 @@ function WhatsappAccountCard({
|
|
|
8781
9444
|
disabled: Boolean(busy),
|
|
8782
9445
|
onSave: onWorkspaceSave
|
|
8783
9446
|
}),
|
|
9447
|
+
h2(AgentPresetEditor, {
|
|
9448
|
+
agentPreset: account.agentPreset,
|
|
9449
|
+
disabled: Boolean(busy),
|
|
9450
|
+
onSave: onAgentPresetSave
|
|
9451
|
+
}),
|
|
8784
9452
|
h2(
|
|
8785
9453
|
"div",
|
|
8786
9454
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -8815,22 +9483,23 @@ function WhatsappAccountCard({
|
|
|
8815
9483
|
);
|
|
8816
9484
|
}
|
|
8817
9485
|
function WhatsappSettingsTab({ rpcCall }) {
|
|
8818
|
-
const [model, setModel] =
|
|
9486
|
+
const [model, setModel] = React18.useState({
|
|
8819
9487
|
phase: "loading",
|
|
8820
9488
|
bots: [],
|
|
8821
9489
|
totals: { configured: 0, connected: 0 },
|
|
8822
|
-
error: null
|
|
9490
|
+
error: null,
|
|
9491
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
8823
9492
|
});
|
|
8824
|
-
const [provision, setProvision] =
|
|
8825
|
-
const [busy, setBusy] =
|
|
8826
|
-
const [busyByBot, setBusyByBot] =
|
|
8827
|
-
const [testNoticeByBot, setTestNoticeByBot] =
|
|
8828
|
-
const [removeTarget, setRemoveTarget] =
|
|
8829
|
-
const [now, setNow] =
|
|
8830
|
-
const mounted =
|
|
9493
|
+
const [provision, setProvision] = React18.useState(null);
|
|
9494
|
+
const [busy, setBusy] = React18.useState(false);
|
|
9495
|
+
const [busyByBot, setBusyByBot] = React18.useState({});
|
|
9496
|
+
const [testNoticeByBot, setTestNoticeByBot] = React18.useState({});
|
|
9497
|
+
const [removeTarget, setRemoveTarget] = React18.useState(null);
|
|
9498
|
+
const [now, setNow] = React18.useState(Date.now());
|
|
9499
|
+
const mounted = React18.useRef(true);
|
|
8831
9500
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
8832
|
-
const addButtonRef =
|
|
8833
|
-
|
|
9501
|
+
const addButtonRef = React18.useRef(null);
|
|
9502
|
+
React18.useEffect(() => {
|
|
8834
9503
|
const disposeDingtalk = installDingtalkStyles();
|
|
8835
9504
|
const disposeWhatsapp = installWhatsappStyles();
|
|
8836
9505
|
mounted.current = true;
|
|
@@ -8840,18 +9509,24 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8840
9509
|
disposeDingtalk();
|
|
8841
9510
|
};
|
|
8842
9511
|
}, []);
|
|
8843
|
-
const invoke =
|
|
9512
|
+
const invoke = React18.useCallback(async (endpoint, payload = {}, signal) => {
|
|
8844
9513
|
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
8845
9514
|
return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
|
|
8846
9515
|
}, [rpcCall]);
|
|
8847
|
-
const loadStatus =
|
|
9516
|
+
const loadStatus = React18.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
8848
9517
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
8849
9518
|
if (workspaceVersion === null) return void 0;
|
|
8850
9519
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
8851
9520
|
try {
|
|
8852
9521
|
const snapshot = normalizeSnapshot8(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
8853
9522
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
8854
|
-
setModel({
|
|
9523
|
+
setModel({
|
|
9524
|
+
phase: "ready",
|
|
9525
|
+
bots: snapshot.bots,
|
|
9526
|
+
totals: snapshot.totals,
|
|
9527
|
+
error: null,
|
|
9528
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9529
|
+
});
|
|
8855
9530
|
if (restore && snapshot.provisioning) setProvision({
|
|
8856
9531
|
...snapshot.provisioning,
|
|
8857
9532
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -8868,12 +9543,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8868
9543
|
return void 0;
|
|
8869
9544
|
}
|
|
8870
9545
|
}, [invoke, workspaceFence]);
|
|
8871
|
-
|
|
9546
|
+
React18.useEffect(() => {
|
|
8872
9547
|
const controller = new AbortController();
|
|
8873
9548
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
8874
9549
|
return () => controller.abort();
|
|
8875
9550
|
}, [loadStatus]);
|
|
8876
|
-
|
|
9551
|
+
React18.useEffect(() => {
|
|
8877
9552
|
if (model.phase !== "ready") return void 0;
|
|
8878
9553
|
const controller = new AbortController();
|
|
8879
9554
|
const timer = window.setInterval(
|
|
@@ -8885,12 +9560,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8885
9560
|
window.clearInterval(timer);
|
|
8886
9561
|
};
|
|
8887
9562
|
}, [loadStatus, model.phase]);
|
|
8888
|
-
|
|
9563
|
+
React18.useEffect(() => {
|
|
8889
9564
|
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
8890
9565
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
8891
9566
|
return () => window.clearInterval(timer);
|
|
8892
9567
|
}, [provision?.attemptId, provision?.status]);
|
|
8893
|
-
const startProvisioning =
|
|
9568
|
+
const startProvisioning = React18.useCallback(async (replace = false) => {
|
|
8894
9569
|
setBusy(true);
|
|
8895
9570
|
try {
|
|
8896
9571
|
if (replace && provision?.attemptId) {
|
|
@@ -8908,7 +9583,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8908
9583
|
if (mounted.current) setBusy(false);
|
|
8909
9584
|
}
|
|
8910
9585
|
}, [invoke, provision?.attemptId]);
|
|
8911
|
-
const closeProvision =
|
|
9586
|
+
const closeProvision = React18.useCallback(async () => {
|
|
8912
9587
|
setBusy(true);
|
|
8913
9588
|
try {
|
|
8914
9589
|
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
|
@@ -8919,7 +9594,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8919
9594
|
if (mounted.current) setBusy(false);
|
|
8920
9595
|
}
|
|
8921
9596
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
8922
|
-
|
|
9597
|
+
React18.useEffect(() => {
|
|
8923
9598
|
const attemptId = provision?.attemptId;
|
|
8924
9599
|
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
8925
9600
|
const controller = new AbortController();
|
|
@@ -8960,7 +9635,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8960
9635
|
if (timer) window.clearTimeout(timer);
|
|
8961
9636
|
};
|
|
8962
9637
|
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
|
8963
|
-
const botAction =
|
|
9638
|
+
const botAction = React18.useCallback(async (account, operation, endpoint, payload) => {
|
|
8964
9639
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8965
9640
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
8966
9641
|
if (operation === "reconnect") {
|
|
@@ -8974,7 +9649,13 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8974
9649
|
const value = await invoke(endpoint, payload);
|
|
8975
9650
|
const snapshot = normalizeSnapshot8(value);
|
|
8976
9651
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8977
|
-
setModel({
|
|
9652
|
+
setModel({
|
|
9653
|
+
phase: "ready",
|
|
9654
|
+
bots: snapshot.bots,
|
|
9655
|
+
totals: snapshot.totals,
|
|
9656
|
+
error: null,
|
|
9657
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9658
|
+
});
|
|
8978
9659
|
if (operation === "reconnect") {
|
|
8979
9660
|
setTestNoticeByBot((current) => ({
|
|
8980
9661
|
...current,
|
|
@@ -9025,6 +9706,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9025
9706
|
WHATSAPP_ENDPOINTS.setWorkspace,
|
|
9026
9707
|
{ botId: account.botId, workspace }
|
|
9027
9708
|
),
|
|
9709
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
9710
|
+
account,
|
|
9711
|
+
"preset",
|
|
9712
|
+
WHATSAPP_ENDPOINTS.setAgentPreset,
|
|
9713
|
+
{ botId: account.botId, agentPreset }
|
|
9714
|
+
),
|
|
9028
9715
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
9029
9716
|
onCancelRemove: () => setRemoveTarget(null),
|
|
9030
9717
|
onConfirmRemove: async () => {
|
|
@@ -9036,7 +9723,9 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9036
9723
|
}
|
|
9037
9724
|
}))))
|
|
9038
9725
|
) : null;
|
|
9039
|
-
return h2(
|
|
9726
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
9727
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9728
|
+
}, h2(
|
|
9040
9729
|
"section",
|
|
9041
9730
|
{
|
|
9042
9731
|
className: "ddt-page dwa-page dim-channelPage",
|
|
@@ -9059,7 +9748,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9059
9748
|
h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
9060
9749
|
)
|
|
9061
9750
|
) : h2(
|
|
9062
|
-
|
|
9751
|
+
React18.Fragment,
|
|
9063
9752
|
null,
|
|
9064
9753
|
provision?.status === "pending" ? h2(QrPanel5, {
|
|
9065
9754
|
provision,
|
|
@@ -9075,7 +9764,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9075
9764
|
}) : model.bots.length === 0 ? h2(EmptyView6, { busy, onStart: () => void startProvisioning(false) }) : null,
|
|
9076
9765
|
botList
|
|
9077
9766
|
)
|
|
9078
|
-
);
|
|
9767
|
+
));
|
|
9079
9768
|
}
|
|
9080
9769
|
|
|
9081
9770
|
// plugin-src/client/styles.js
|
|
@@ -9222,6 +9911,14 @@ var CSS11 = String.raw`
|
|
|
9222
9911
|
.dim-panel .dim-workspaceEdit { grid-column: 2; grid-row: 1; padding: 0; border: 0; color: #1677ff; background: transparent; font: inherit; font-weight: 560; white-space: nowrap; cursor: pointer; }
|
|
9223
9912
|
.dim-panel .dim-workspaceEdit:disabled { cursor: not-allowed; opacity: .55; }
|
|
9224
9913
|
.dim-panel .dim-workspacePath { min-width: 0; max-width: 100%; grid-column: 1 / -1; grid-row: 2; display: block; overflow-x: auto; overflow-y: hidden; color: var(--dsw-alias-label-primary, #1f2329); font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
|
|
9914
|
+
.dim-panel .dim-preset { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 4px; margin-top: 6px; padding: 6px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
|
|
9915
|
+
.dim-panel .dim-presetHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
|
9916
|
+
.dim-panel .dim-presetHeader > span { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
|
9917
|
+
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
9918
|
+
.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; }
|
|
9919
|
+
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
9920
|
+
.dim-panel .dim-presetHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.4; }
|
|
9921
|
+
.dim-panel .dim-presetError { grid-column: 1 / -1; grid-row: 4; margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.4; }
|
|
9225
9922
|
.dim-directoryPickerBackdrop { --dim-blue: var(--dsw-alias-state-business-primary, #3370ff); --dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent); position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 24px; background: rgb(15 17 21 / 42%); backdrop-filter: blur(3px); }
|
|
9226
9923
|
.dim-directoryPickerBackdrop, .dim-directoryPickerBackdrop *, .dim-directoryPickerBackdrop *::before, .dim-directoryPickerBackdrop *::after { box-sizing: border-box; }
|
|
9227
9924
|
.dim-directoryPicker { width: min(720px, 100%); height: min(620px, calc(100vh - 48px)); min-height: 420px; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 18px; outline: none; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 24px 72px rgb(15 17 21 / 24%); }
|
|
@@ -9452,8 +10149,8 @@ function IMSettingsTab({
|
|
|
9452
10149
|
officeRpcCall,
|
|
9453
10150
|
workspaceDirectoryPicker
|
|
9454
10151
|
}) {
|
|
9455
|
-
const [selected, setSelected] =
|
|
9456
|
-
const githubTooltipId =
|
|
10152
|
+
const [selected, setSelected] = React19.useState("weixin");
|
|
10153
|
+
const githubTooltipId = React19.useId();
|
|
9457
10154
|
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
|
9458
10155
|
return h2(
|
|
9459
10156
|
WorkspaceDirectoryPickerContext.Provider,
|