@xmanrui/dsh-im 0.17.0 → 0.18.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 +964 -538
- package/lib/index.js +189 -144
- 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 +5 -0
- package/plugin-src/client/channels/feishu/index.js +39 -2
- 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 +15 -0
- package/plugin-src/client/channels/weixin/index.js +54 -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 +29 -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 +6 -3
- package/plugin-src/host/channels/feishu/rpc.mjs +17 -0
- 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/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/shared/image-prompt.mjs +32 -1
- package/src/channels/weixin/weixin-api.mjs +1 -1
- package/src/channels/weixin/weixin-bridge.mjs +23 -3
- package/src/channels/weixin/weixin-controller.mjs +15 -0
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
|
|
@@ -507,6 +307,15 @@ var EN = Object.freeze({
|
|
|
507
307
|
"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002": "The workspace path does not exist.",
|
|
508
308
|
"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002": "The workspace path must point to a directory.",
|
|
509
309
|
"\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002": "The bot could not be found.",
|
|
310
|
+
"Agent Preset": "Agent Preset",
|
|
311
|
+
"\u8DDF\u968F Host \u9ED8\u8BA4": "Follow the Host default",
|
|
312
|
+
"\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09": " (unavailable)",
|
|
313
|
+
"\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.",
|
|
314
|
+
"\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.",
|
|
315
|
+
"Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the Agent Preset. Try again.",
|
|
316
|
+
"\u8BF7\u9009\u62E9 Agent Preset\u3002": "Choose an Agent Preset.",
|
|
317
|
+
"Agent Preset \u65E0\u6548\u3002": "The Agent Preset is invalid.",
|
|
318
|
+
"Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002": "The Agent Preset does not exist or is unavailable.",
|
|
510
319
|
"\u5C1A\u672A\u68C0\u67E5": "Not checked yet",
|
|
511
320
|
"\u521A\u521A": "Just now",
|
|
512
321
|
"\u68C0\u67E5\u8FDE\u63A5": "Check connection",
|
|
@@ -839,6 +648,20 @@ var EN = Object.freeze({
|
|
|
839
648
|
"\u5FAE\u4FE1\u7ED1\u5B9A\u6CA1\u6709\u5B8C\u6210": "WeChat setup did not complete",
|
|
840
649
|
"\u5FAE\u4FE1\u8FDE\u63A5\u6B63\u5E38": "WeChat connection is healthy",
|
|
841
650
|
"\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA": "WeChat connection is not ready",
|
|
651
|
+
"\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\uFF0C\u8BF7\u7528 /models \u67E5\u770B\u53EF\u7528\u6A21\u578B\uFF0C\u518D\u7528 /model <\u5E8F\u53F7> \u5207\u6362\u540E\u91CD\u53D1\u3002": "The current model does not support images. Use /models to list models, then /model <number> to switch and resend.",
|
|
652
|
+
"\u56FE\u7247\u8D85\u8FC7\u5BBF\u4E3B\u5141\u8BB8\u7684\u5927\u5C0F\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002": "The image exceeds the Host size limit. Compress it and try again.",
|
|
653
|
+
"\u56FE\u7247\u5206\u8FA8\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002": "The image resolution is too high. Compress it and try again.",
|
|
654
|
+
"\u56FE\u7247\u5185\u5BB9\u65E0\u6548\u6216\u683C\u5F0F\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002": "The image is invalid or unsupported. Send it again.",
|
|
655
|
+
"\u672A\u80FD\u8BFB\u53D6\u56FE\u7247\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002": "The image could not be read. Send it again.",
|
|
656
|
+
"\u56FE\u7247\u683C\u5F0F\u4E0E\u5B9E\u9645\u5185\u5BB9\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u3002": "The declared image format does not match its content. Send it again.",
|
|
657
|
+
"\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u6570\u91CF\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u540E\u91CD\u8BD5\u3002": "The message exceeds the Host image-count limit. Remove some images and try again.",
|
|
658
|
+
"\u56FE\u7247\u603B\u5927\u5C0F\u8D85\u8FC7\u5BBF\u4E3B\u9650\u5236\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002": "The images exceed the Host total-size limit. Remove or compress some images and try again.",
|
|
659
|
+
"\u56FE\u7247\u4E0B\u8F7D\u5730\u5740\u53D1\u751F\u4E86\u91CD\u5B9A\u5411\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u3002": "The image download redirected and cannot be read.",
|
|
660
|
+
"\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002": "The image exceeds 5 MB. Compress it and try again.",
|
|
661
|
+
"\u4E00\u6B21\u53D1\u9001\u7684\u56FE\u7247\u603B\u5927\u5C0F\u8FC7\u5927\uFF0C\u8BF7\u51CF\u5C11\u56FE\u7247\u6570\u91CF\u6216\u538B\u7F29\u540E\u91CD\u8BD5\u3002": "The images are too large in total. Remove or compress some images and try again.",
|
|
662
|
+
"\u56FE\u7247\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u540E\u518D\u8BD5\u3002": "The image download failed. Send it again.",
|
|
663
|
+
"\u6682\u4E0D\u652F\u6301\u8BE5\u56FE\u7247\u683C\u5F0F\uFF0C\u8BF7\u53D1\u9001 JPEG\u3001PNG\u3001WebP \u6216 GIF \u56FE\u7247\u3002": "This image format is unsupported. Send a JPEG, PNG, WebP, or GIF image.",
|
|
664
|
+
"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002": "Message processing failed. Try again later.",
|
|
842
665
|
"\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u8D26\u53F7\u5217\u8868": "WeChat did not return a valid account list",
|
|
843
666
|
"\u5C1A\u672A\u7ED1\u5B9A\u5FAE\u4FE1": "No WeChat account connected yet",
|
|
844
667
|
"\u7528\u4E8E\u628A\u5FAE\u4FE1\u673A\u5668\u4EBA\u7ED1\u5B9A\u5230 DeepSeek Harness \u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801": "One-time QR code for connecting a WeChat bot to DeepSeek Harness",
|
|
@@ -906,6 +729,12 @@ function translateDynamic(text5) {
|
|
|
906
729
|
}
|
|
907
730
|
match = /^二维码剩余 (.+)$/.exec(text5);
|
|
908
731
|
if (match) return `QR code expires in ${match[1]}`;
|
|
732
|
+
match = /^最近一条消息处理失败:(.+)$/.exec(text5);
|
|
733
|
+
if (match) return `Latest message failed: ${localizeText(match[1])}`;
|
|
734
|
+
match = /^图片下载失败(HTTP (.+)),请重新发送后再试。$/.exec(text5);
|
|
735
|
+
if (match) return `The image download failed (HTTP ${match[1]}). Send it again.`;
|
|
736
|
+
match = /^一次最多只能处理 (\d+) 张图片。$/.exec(text5);
|
|
737
|
+
if (match) return `A message can contain at most ${match[1]} images.`;
|
|
909
738
|
match = /^状态刷新失败:(.+)$/.exec(text5);
|
|
910
739
|
if (match) return `Status refresh failed: ${match[1]}`;
|
|
911
740
|
match = /^状态自动刷新失败:(.+)$/.exec(text5);
|
|
@@ -985,7 +814,310 @@ function h2(type, props, ...children) {
|
|
|
985
814
|
return React2.createElement(type, localizedProps, ...children.map(localizeChild));
|
|
986
815
|
}
|
|
987
816
|
|
|
817
|
+
// plugin-src/client/agent-preset.js
|
|
818
|
+
var SET_AGENT_PRESET_ENDPOINT = "bot.preset.set";
|
|
819
|
+
var PRESET_ID = /^[a-z0-9][a-z0-9-]*$/;
|
|
820
|
+
var EMPTY_AGENT_PRESET_CATALOG = Object.freeze({
|
|
821
|
+
defaultId: "",
|
|
822
|
+
items: Object.freeze([])
|
|
823
|
+
});
|
|
824
|
+
var AgentPresetCatalogContext = React3.createContext(EMPTY_AGENT_PRESET_CATALOG);
|
|
825
|
+
function normalizeAgentPresetId(value) {
|
|
826
|
+
if (typeof value !== "string") return "";
|
|
827
|
+
const id5 = value.trim();
|
|
828
|
+
return PRESET_ID.test(id5) ? id5 : "";
|
|
829
|
+
}
|
|
830
|
+
function normalizeAgentPresetCatalog(value) {
|
|
831
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
832
|
+
return { defaultId: "", items: [] };
|
|
833
|
+
}
|
|
834
|
+
const items = [];
|
|
835
|
+
const seen = /* @__PURE__ */ new Set();
|
|
836
|
+
for (const entry of Array.isArray(value.items) ? value.items : []) {
|
|
837
|
+
const id5 = typeof entry === "string" ? normalizeAgentPresetId(entry) : normalizeAgentPresetId(entry?.id);
|
|
838
|
+
if (!id5 || seen.has(id5)) continue;
|
|
839
|
+
seen.add(id5);
|
|
840
|
+
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;
|
|
841
|
+
items.push({ id: id5, label });
|
|
842
|
+
}
|
|
843
|
+
return {
|
|
844
|
+
defaultId: normalizeAgentPresetId(value.defaultId),
|
|
845
|
+
items
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
function AgentPresetEditor({ agentPreset = "", disabled = false, onSave }) {
|
|
849
|
+
const catalog = React3.useContext(AgentPresetCatalogContext) ?? EMPTY_AGENT_PRESET_CATALOG;
|
|
850
|
+
const current = normalizeAgentPresetId(agentPreset);
|
|
851
|
+
const [saving, setSaving] = React3.useState(false);
|
|
852
|
+
const [error, setError] = React3.useState(null);
|
|
853
|
+
const items = [];
|
|
854
|
+
const seen = /* @__PURE__ */ new Set();
|
|
855
|
+
for (const item of Array.isArray(catalog.items) ? catalog.items : []) {
|
|
856
|
+
if (!item?.id || seen.has(item.id)) continue;
|
|
857
|
+
seen.add(item.id);
|
|
858
|
+
items.push(item);
|
|
859
|
+
}
|
|
860
|
+
const currentUnavailable = Boolean(current && !seen.has(current));
|
|
861
|
+
if (currentUnavailable) items.push({ id: current, label: current, unavailable: true });
|
|
862
|
+
const inheritLabel = "\u8DDF\u968F Host \u9ED8\u8BA4";
|
|
863
|
+
const change = async (event) => {
|
|
864
|
+
const next = event.target.value;
|
|
865
|
+
if (next === current || saving || disabled) return;
|
|
866
|
+
setSaving(true);
|
|
867
|
+
setError(null);
|
|
868
|
+
try {
|
|
869
|
+
await onSave?.(next || null);
|
|
870
|
+
} catch (cause) {
|
|
871
|
+
setError(cause?.message ?? "Agent Preset \u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
|
872
|
+
} finally {
|
|
873
|
+
setSaving(false);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
return h2(
|
|
877
|
+
"div",
|
|
878
|
+
{ className: "dim-preset" },
|
|
879
|
+
h2(
|
|
880
|
+
"div",
|
|
881
|
+
{ className: "dim-presetHeader" },
|
|
882
|
+
h2("span", null, "Agent Preset"),
|
|
883
|
+
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
|
884
|
+
),
|
|
885
|
+
React3.createElement(
|
|
886
|
+
"select",
|
|
887
|
+
{
|
|
888
|
+
className: "dim-presetSelect",
|
|
889
|
+
value: current,
|
|
890
|
+
disabled: disabled || saving,
|
|
891
|
+
"aria-label": "Agent Preset",
|
|
892
|
+
onChange: (event) => {
|
|
893
|
+
void change(event);
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
h2("option", { value: "" }, inheritLabel),
|
|
897
|
+
...items.map((item) => h2(
|
|
898
|
+
"option",
|
|
899
|
+
{ key: item.id, value: item.id },
|
|
900
|
+
item.unavailable ? [item.id, "\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09"] : item.label && item.label !== item.id ? `${item.label}\uFF08${item.id}\uFF09` : item.id
|
|
901
|
+
))
|
|
902
|
+
),
|
|
903
|
+
h2(
|
|
904
|
+
"small",
|
|
905
|
+
{ className: "dim-presetHelp" },
|
|
906
|
+
"\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"
|
|
907
|
+
),
|
|
908
|
+
error || currentUnavailable ? h2(
|
|
909
|
+
"p",
|
|
910
|
+
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
|
911
|
+
error ?? "\u5F53\u524D Agent Preset \u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6 Preset \u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002"
|
|
912
|
+
) : null
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// plugin-src/client/channels/dingtalk/api.js
|
|
917
|
+
var DINGTALK_RPC_CHANNEL = "/dingtalk";
|
|
918
|
+
var DINGTALK_ENDPOINTS = Object.freeze({
|
|
919
|
+
status: "connection.status",
|
|
920
|
+
beginProvisioning: "provision.begin",
|
|
921
|
+
pollProvisioning: "provision.poll",
|
|
922
|
+
cancelProvisioning: "provision.cancel",
|
|
923
|
+
bindCredentials: "bot.bind-credentials",
|
|
924
|
+
reconnectBot: "bot.reconnect",
|
|
925
|
+
deleteBot: "bot.delete",
|
|
926
|
+
setWorkspace: "bot.workspace.set",
|
|
927
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
928
|
+
});
|
|
929
|
+
var ACCOUNT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
930
|
+
var SNAPSHOT_STATES = /* @__PURE__ */ new Set(["disconnected", "offline", "provisioning", "connected", "degraded"]);
|
|
931
|
+
var PROVISION_STATES = /* @__PURE__ */ new Set([
|
|
932
|
+
"starting",
|
|
933
|
+
"pending",
|
|
934
|
+
"scanned",
|
|
935
|
+
"authorizing",
|
|
936
|
+
"creating",
|
|
937
|
+
"connecting",
|
|
938
|
+
"connected",
|
|
939
|
+
"expired",
|
|
940
|
+
"failed",
|
|
941
|
+
"cancelled"
|
|
942
|
+
]);
|
|
943
|
+
var HEALTH_STATES = /* @__PURE__ */ new Set(["healthy", "checking", "degraded", "offline"]);
|
|
944
|
+
var FORBIDDEN_ERROR_FIELDS = /(client[_-]?secret|secret[_-]?ref|device[_-]?code|app[_-]?secret|access[_-]?token|token)/i;
|
|
945
|
+
var QR_DATA_URL = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
946
|
+
var MAX_QR_SOURCE_LENGTH = 2 * 1024 * 1024;
|
|
947
|
+
function isRecord(value) {
|
|
948
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
949
|
+
}
|
|
950
|
+
function optionalString(value, maxLength = 240) {
|
|
951
|
+
if (typeof value !== "string") return void 0;
|
|
952
|
+
const trimmed = value.trim();
|
|
953
|
+
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
954
|
+
}
|
|
955
|
+
function opaqueId(value) {
|
|
956
|
+
const id5 = optionalString(value, 128);
|
|
957
|
+
return id5 && /^[a-z\d_-]+$/i.test(id5) ? id5 : void 0;
|
|
958
|
+
}
|
|
959
|
+
function timestamp(value) {
|
|
960
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
961
|
+
if (typeof value === "string" && value.trim()) {
|
|
962
|
+
const parsed = Date.parse(value);
|
|
963
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
964
|
+
}
|
|
965
|
+
return void 0;
|
|
966
|
+
}
|
|
967
|
+
function nonNegativeInteger(value) {
|
|
968
|
+
const number = Number(value);
|
|
969
|
+
return Number.isSafeInteger(number) && number >= 0 ? number : 0;
|
|
970
|
+
}
|
|
971
|
+
function clamp(value, min, max, fallback) {
|
|
972
|
+
const number = Number(value);
|
|
973
|
+
return Number.isFinite(number) ? Math.min(max, Math.max(min, number)) : fallback;
|
|
974
|
+
}
|
|
975
|
+
function safeErrorCode(value, fallback) {
|
|
976
|
+
const code = optionalString(value, 80);
|
|
977
|
+
return code && /^[a-z][a-z\d_.:-]*$/i.test(code) && !FORBIDDEN_ERROR_FIELDS.test(code) ? code : fallback;
|
|
978
|
+
}
|
|
979
|
+
function sanitizeMessage(value, fallback) {
|
|
980
|
+
const message = optionalString(value, 480) ?? fallback;
|
|
981
|
+
if (FORBIDDEN_ERROR_FIELDS.test(message)) return fallback;
|
|
982
|
+
return message.replace(/([=:]\s*)[^\s,;,。]+/g, "$1\u2022\u2022\u2022\u2022\u2022\u2022").slice(0, 240);
|
|
983
|
+
}
|
|
984
|
+
function normalizeError(value, fallbackCode, fallbackMessage) {
|
|
985
|
+
if (!isRecord(value)) return void 0;
|
|
986
|
+
return {
|
|
987
|
+
code: safeErrorCode(value.code, fallbackCode),
|
|
988
|
+
message: sanitizeMessage(value.message, fallbackMessage)
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
function normalizeTestMessage(value) {
|
|
992
|
+
if (!isRecord(value)) return null;
|
|
993
|
+
if (value.sent === true) return { sent: true };
|
|
994
|
+
if (value.sent !== false) return null;
|
|
995
|
+
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
996
|
+
return { sent: false, code };
|
|
997
|
+
}
|
|
998
|
+
function unwrapRpcResult(result) {
|
|
999
|
+
if (!isRecord(result) || typeof result.ok !== "boolean") {
|
|
1000
|
+
throw new Error("\u9489\u9489\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
1001
|
+
}
|
|
1002
|
+
if (!result.ok) {
|
|
1003
|
+
const error = new Error(sanitizeMessage(result.error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25"));
|
|
1004
|
+
error.code = safeErrorCode(result.error?.code, "DINGTALK_RPC_ERROR");
|
|
1005
|
+
throw error;
|
|
1006
|
+
}
|
|
1007
|
+
return result.value;
|
|
1008
|
+
}
|
|
1009
|
+
function safeQrSource(value) {
|
|
1010
|
+
if (typeof value !== "string" || value.length > MAX_QR_SOURCE_LENGTH) return void 0;
|
|
1011
|
+
return QR_DATA_URL.test(value) ? value : void 0;
|
|
1012
|
+
}
|
|
1013
|
+
function normalizeProvisioning(value, now = Date.now()) {
|
|
1014
|
+
const source = isRecord(value?.provisioning) ? value.provisioning : value;
|
|
1015
|
+
if (!isRecord(source)) throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u7ED1\u5B9A\u8FDB\u5EA6");
|
|
1016
|
+
const attemptId = opaqueId(source.attemptId);
|
|
1017
|
+
if (!attemptId) throw new Error("\u9489\u9489\u626B\u7801\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u7ED1\u5B9A\u4EFB\u52A1");
|
|
1018
|
+
const reportedStatus = optionalString(source.status, 32) ?? optionalString(source.state, 32);
|
|
1019
|
+
const status = PROVISION_STATES.has(reportedStatus) ? reportedStatus : "failed";
|
|
1020
|
+
const expiresAt = timestamp(source.expiresAt) ?? now + clamp(source.expiresIn, 1, 2 * 60 * 60, 10 * 60) * 1e3;
|
|
1021
|
+
const result = {
|
|
1022
|
+
attemptId,
|
|
1023
|
+
status,
|
|
1024
|
+
expiresAt,
|
|
1025
|
+
pollIntervalMs: clamp(source.pollIntervalMs, 1e3, 1e4, 3e3)
|
|
1026
|
+
};
|
|
1027
|
+
const qrCodeDataUrl = safeQrSource(source.qrCodeDataUrl);
|
|
1028
|
+
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
1029
|
+
if (opaqueId(source.botId)) result.botId = opaqueId(source.botId);
|
|
1030
|
+
if (source.alreadyConnected === true) result.alreadyConnected = true;
|
|
1031
|
+
const error = normalizeError(
|
|
1032
|
+
source.error,
|
|
1033
|
+
"DINGTALK_PROVISION_FAILED",
|
|
1034
|
+
"\u9489\u9489\u673A\u5668\u4EBA\u6CA1\u6709\u63A5\u5165\u5B8C\u6210"
|
|
1035
|
+
);
|
|
1036
|
+
if (error) result.error = error;
|
|
1037
|
+
return result;
|
|
1038
|
+
}
|
|
1039
|
+
function normalizeBot(value) {
|
|
1040
|
+
if (!isRecord(value)) return void 0;
|
|
1041
|
+
const botId = opaqueId(value.botId);
|
|
1042
|
+
if (!botId) return void 0;
|
|
1043
|
+
const bot = isRecord(value.bot) ? value.bot : {};
|
|
1044
|
+
const connected = value.connected === true;
|
|
1045
|
+
const reportedState = ACCOUNT_STATES.has(value.state) ? value.state : "offline";
|
|
1046
|
+
const state = connected ? "connected" : reportedState === "connected" ? "connecting" : reportedState;
|
|
1047
|
+
const health = isRecord(value.health) ? value.health : {};
|
|
1048
|
+
const stats = isRecord(value.stats) ? value.stats : {};
|
|
1049
|
+
return {
|
|
1050
|
+
botId,
|
|
1051
|
+
state,
|
|
1052
|
+
connected,
|
|
1053
|
+
configured: value.configured !== false,
|
|
1054
|
+
workspace: optionalString(value.workspace, 4096) ?? "",
|
|
1055
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
1056
|
+
bot: {
|
|
1057
|
+
name: optionalString(bot.name, 100) ?? "\u9489\u9489\u673A\u5668\u4EBA",
|
|
1058
|
+
clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? "\u5DF2\u5B89\u5168\u4FDD\u5B58"
|
|
1059
|
+
},
|
|
1060
|
+
health: {
|
|
1061
|
+
status: HEALTH_STATES.has(health.status) ? health.status : connected ? "healthy" : "offline",
|
|
1062
|
+
summary: optionalString(health.summary, 200) ?? (connected ? "\u9489\u9489 Stream \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38" : "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
1063
|
+
lastCheckedAt: timestamp(health.lastCheckedAt),
|
|
1064
|
+
lastConnectedAt: timestamp(health.lastConnectedAt)
|
|
1065
|
+
},
|
|
1066
|
+
stats: {
|
|
1067
|
+
messagesReceived: nonNegativeInteger(stats.messagesReceived),
|
|
1068
|
+
messagesReplied: nonNegativeInteger(stats.messagesReplied)
|
|
1069
|
+
},
|
|
1070
|
+
error: normalizeError(value.error, "DINGTALK_ACCOUNT_ERROR", "\u9489\u9489\u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA") ?? null
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
function normalizeSnapshot(value) {
|
|
1074
|
+
const source = isRecord(value?.snapshot) ? value.snapshot : value;
|
|
1075
|
+
if (!isRecord(source) || !Array.isArray(source.bots)) {
|
|
1076
|
+
throw new Error("\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
1077
|
+
}
|
|
1078
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1079
|
+
const bots = source.bots.map(normalizeBot).filter((bot) => {
|
|
1080
|
+
if (!bot || seen.has(bot.botId)) return false;
|
|
1081
|
+
seen.add(bot.botId);
|
|
1082
|
+
return true;
|
|
1083
|
+
});
|
|
1084
|
+
return {
|
|
1085
|
+
schemaVersion: Number.isSafeInteger(source.schemaVersion) ? source.schemaVersion : 1,
|
|
1086
|
+
revision: nonNegativeInteger(source.revision),
|
|
1087
|
+
state: SNAPSHOT_STATES.has(source.state) ? source.state : "offline",
|
|
1088
|
+
bots,
|
|
1089
|
+
totals: {
|
|
1090
|
+
configured: bots.length,
|
|
1091
|
+
connected: bots.filter((bot) => bot.connected).length
|
|
1092
|
+
},
|
|
1093
|
+
provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
|
|
1094
|
+
testMessage: normalizeTestMessage(source.testMessage),
|
|
1095
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
function connectionTestFeedback(result) {
|
|
1099
|
+
if (result?.sent === true) return "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\u3002";
|
|
1100
|
+
if (result?.code === "test-target-unavailable") {
|
|
1101
|
+
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";
|
|
1102
|
+
}
|
|
1103
|
+
return result ? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
1104
|
+
}
|
|
1105
|
+
function presentError(error) {
|
|
1106
|
+
return {
|
|
1107
|
+
code: safeErrorCode(error?.code, "DINGTALK_ERROR"),
|
|
1108
|
+
message: sanitizeMessage(error?.message, "\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function formatRemaining(milliseconds) {
|
|
1112
|
+
const seconds = Math.max(0, Math.ceil(Number(milliseconds) / 1e3) || 0);
|
|
1113
|
+
return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// plugin-src/client/channels/dingtalk/index.js
|
|
1117
|
+
var React8 = __toESM(require("react"), 1);
|
|
1118
|
+
|
|
988
1119
|
// plugin-src/client/credential-binding.js
|
|
1120
|
+
var React4 = __toESM(require("react"), 1);
|
|
989
1121
|
function ActionIcon({ children }) {
|
|
990
1122
|
return h2("svg", {
|
|
991
1123
|
className: "dim-actionIcon",
|
|
@@ -1045,9 +1177,9 @@ function CredentialBindingPanel({
|
|
|
1045
1177
|
onSubmit,
|
|
1046
1178
|
onCancel
|
|
1047
1179
|
}) {
|
|
1048
|
-
const [identity, setIdentity] =
|
|
1049
|
-
const [secret, setSecret] =
|
|
1050
|
-
const headingId =
|
|
1180
|
+
const [identity, setIdentity] = React4.useState("");
|
|
1181
|
+
const [secret, setSecret] = React4.useState("");
|
|
1182
|
+
const headingId = React4.useId();
|
|
1051
1183
|
const hasIdentity = Boolean(identityLabel);
|
|
1052
1184
|
const submit = (event) => {
|
|
1053
1185
|
event.preventDefault();
|
|
@@ -1126,10 +1258,10 @@ function CredentialBindingPanel({
|
|
|
1126
1258
|
}
|
|
1127
1259
|
|
|
1128
1260
|
// plugin-src/client/workspace-editor.js
|
|
1129
|
-
var
|
|
1261
|
+
var React6 = __toESM(require("react"), 1);
|
|
1130
1262
|
|
|
1131
1263
|
// plugin-src/client/workspace-directory-picker.js
|
|
1132
|
-
var
|
|
1264
|
+
var React5 = __toESM(require("react"), 1);
|
|
1133
1265
|
var import_react_dom = require("react-dom");
|
|
1134
1266
|
function pickerErrorCode(error) {
|
|
1135
1267
|
return error?.rpcError?.code ?? error?.code;
|
|
@@ -1141,7 +1273,7 @@ function pickerErrorMessage(error) {
|
|
|
1141
1273
|
return error?.rpcError?.message ?? error?.message ?? "\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002";
|
|
1142
1274
|
}
|
|
1143
1275
|
function FolderIcon() {
|
|
1144
|
-
return
|
|
1276
|
+
return React5.createElement(
|
|
1145
1277
|
"svg",
|
|
1146
1278
|
{
|
|
1147
1279
|
viewBox: "0 0 24 24",
|
|
@@ -1152,11 +1284,11 @@ function FolderIcon() {
|
|
|
1152
1284
|
strokeLinejoin: "round",
|
|
1153
1285
|
"aria-hidden": "true"
|
|
1154
1286
|
},
|
|
1155
|
-
|
|
1287
|
+
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" })
|
|
1156
1288
|
);
|
|
1157
1289
|
}
|
|
1158
1290
|
function ChevronIcon() {
|
|
1159
|
-
return
|
|
1291
|
+
return React5.createElement("svg", {
|
|
1160
1292
|
viewBox: "0 0 20 20",
|
|
1161
1293
|
fill: "none",
|
|
1162
1294
|
stroke: "currentColor",
|
|
@@ -1164,7 +1296,7 @@ function ChevronIcon() {
|
|
|
1164
1296
|
strokeLinecap: "round",
|
|
1165
1297
|
strokeLinejoin: "round",
|
|
1166
1298
|
"aria-hidden": "true"
|
|
1167
|
-
},
|
|
1299
|
+
}, React5.createElement("path", { d: "m7.5 4.5 5 5.5-5 5.5" }));
|
|
1168
1300
|
}
|
|
1169
1301
|
function displayCrumbs(listing) {
|
|
1170
1302
|
const homeIndex = listing.crumbs.findIndex((crumb) => crumb.path === listing.home);
|
|
@@ -1180,25 +1312,25 @@ function WorkspaceDirectoryPicker({
|
|
|
1180
1312
|
onPicked,
|
|
1181
1313
|
onCancel
|
|
1182
1314
|
}) {
|
|
1183
|
-
const [listing, setListing] =
|
|
1184
|
-
const [loading, setLoading] =
|
|
1185
|
-
const [error, setError] =
|
|
1186
|
-
const [showHidden, setShowHidden] =
|
|
1187
|
-
const [retryKey, setRetryKey] =
|
|
1188
|
-
const requestRef =
|
|
1189
|
-
const controllerRef =
|
|
1190
|
-
const dialogRef =
|
|
1191
|
-
const bodyRef =
|
|
1192
|
-
const titleId =
|
|
1193
|
-
const noticeId =
|
|
1194
|
-
const initialPathRef =
|
|
1195
|
-
const onPickedRef =
|
|
1196
|
-
const onCancelRef =
|
|
1197
|
-
const busyRef =
|
|
1315
|
+
const [listing, setListing] = React5.useState(null);
|
|
1316
|
+
const [loading, setLoading] = React5.useState(false);
|
|
1317
|
+
const [error, setError] = React5.useState(null);
|
|
1318
|
+
const [showHidden, setShowHidden] = React5.useState(false);
|
|
1319
|
+
const [retryKey, setRetryKey] = React5.useState(0);
|
|
1320
|
+
const requestRef = React5.useRef(0);
|
|
1321
|
+
const controllerRef = React5.useRef(null);
|
|
1322
|
+
const dialogRef = React5.useRef(null);
|
|
1323
|
+
const bodyRef = React5.useRef(null);
|
|
1324
|
+
const titleId = React5.useId();
|
|
1325
|
+
const noticeId = React5.useId();
|
|
1326
|
+
const initialPathRef = React5.useRef(startPath);
|
|
1327
|
+
const onPickedRef = React5.useRef(onPicked);
|
|
1328
|
+
const onCancelRef = React5.useRef(onCancel);
|
|
1329
|
+
const busyRef = React5.useRef(busy);
|
|
1198
1330
|
onPickedRef.current = onPicked;
|
|
1199
1331
|
onCancelRef.current = onCancel;
|
|
1200
1332
|
busyRef.current = busy;
|
|
1201
|
-
const loadDirectory =
|
|
1333
|
+
const loadDirectory = React5.useCallback(async (path, { reportError = true } = {}) => {
|
|
1202
1334
|
const request = requestRef.current + 1;
|
|
1203
1335
|
requestRef.current = request;
|
|
1204
1336
|
controllerRef.current?.abort();
|
|
@@ -1221,7 +1353,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1221
1353
|
if (request === requestRef.current) setLoading(false);
|
|
1222
1354
|
}
|
|
1223
1355
|
}, [picker]);
|
|
1224
|
-
|
|
1356
|
+
React5.useEffect(() => {
|
|
1225
1357
|
if (!open) return void 0;
|
|
1226
1358
|
let active = true;
|
|
1227
1359
|
setListing(null);
|
|
@@ -1299,10 +1431,10 @@ function WorkspaceDirectoryPicker({
|
|
|
1299
1431
|
"nav",
|
|
1300
1432
|
{ className: "dim-directoryCrumbs", "aria-label": "\u5F53\u524D\u76EE\u5F55" },
|
|
1301
1433
|
crumbs.map((crumb, index) => h2(
|
|
1302
|
-
|
|
1434
|
+
React5.Fragment,
|
|
1303
1435
|
{ key: crumb.path },
|
|
1304
1436
|
index > 0 ? h2("span", { className: "dim-directoryCrumbSeparator", "aria-hidden": "true" }, "\u203A") : null,
|
|
1305
|
-
|
|
1437
|
+
React5.createElement("button", {
|
|
1306
1438
|
type: "button",
|
|
1307
1439
|
title: crumb.path,
|
|
1308
1440
|
disabled: loading || busy,
|
|
@@ -1323,7 +1455,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1323
1455
|
) : listing ? entries.length > 0 ? h2("ul", { className: "dim-directoryList" }, entries.map((entry) => h2(
|
|
1324
1456
|
"li",
|
|
1325
1457
|
{ key: entry.path },
|
|
1326
|
-
|
|
1458
|
+
React5.createElement(
|
|
1327
1459
|
"button",
|
|
1328
1460
|
{
|
|
1329
1461
|
type: "button",
|
|
@@ -1332,7 +1464,7 @@ function WorkspaceDirectoryPicker({
|
|
|
1332
1464
|
onClick: () => void loadDirectory(entry.path)
|
|
1333
1465
|
},
|
|
1334
1466
|
h2("span", { className: "dim-directoryFolder" }, h2(FolderIcon)),
|
|
1335
|
-
|
|
1467
|
+
React5.createElement("span", { className: "dim-directoryName" }, entry.name),
|
|
1336
1468
|
h2("span", { className: "dim-directoryChevron" }, h2(ChevronIcon))
|
|
1337
1469
|
)
|
|
1338
1470
|
))) : h2(
|
|
@@ -1385,21 +1517,21 @@ function WorkspaceDirectoryPicker({
|
|
|
1385
1517
|
}
|
|
1386
1518
|
|
|
1387
1519
|
// plugin-src/client/workspace-editor.js
|
|
1388
|
-
var WorkspaceDirectoryPickerContext =
|
|
1520
|
+
var WorkspaceDirectoryPickerContext = React6.createContext(null);
|
|
1389
1521
|
function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave }) {
|
|
1390
|
-
const sharedDirectoryPicker =
|
|
1522
|
+
const sharedDirectoryPicker = React6.useContext(WorkspaceDirectoryPickerContext);
|
|
1391
1523
|
const activeDirectoryPicker = directoryPicker ?? sharedDirectoryPicker;
|
|
1392
|
-
const [open, setOpen] =
|
|
1393
|
-
const [saving, setSaving] =
|
|
1394
|
-
const [error, setError] =
|
|
1395
|
-
const editButtonRef =
|
|
1396
|
-
const savingRef =
|
|
1397
|
-
const close =
|
|
1524
|
+
const [open, setOpen] = React6.useState(false);
|
|
1525
|
+
const [saving, setSaving] = React6.useState(false);
|
|
1526
|
+
const [error, setError] = React6.useState(null);
|
|
1527
|
+
const editButtonRef = React6.useRef(null);
|
|
1528
|
+
const savingRef = React6.useRef(false);
|
|
1529
|
+
const close = React6.useCallback(() => {
|
|
1398
1530
|
setOpen(false);
|
|
1399
1531
|
setError(null);
|
|
1400
1532
|
queueMicrotask(() => editButtonRef.current?.focus?.());
|
|
1401
1533
|
}, []);
|
|
1402
|
-
const pick =
|
|
1534
|
+
const pick = React6.useCallback(async (value) => {
|
|
1403
1535
|
if (!value || savingRef.current || disabled) return;
|
|
1404
1536
|
if (value === workspace) {
|
|
1405
1537
|
close();
|
|
@@ -1436,7 +1568,7 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
|
|
|
1436
1568
|
disabled: disabled || !activeDirectoryPicker
|
|
1437
1569
|
}, "\u9009\u62E9\u76EE\u5F55")
|
|
1438
1570
|
),
|
|
1439
|
-
workspace ?
|
|
1571
|
+
workspace ? React6.createElement("code", {
|
|
1440
1572
|
className: "dim-workspacePath",
|
|
1441
1573
|
title: workspace
|
|
1442
1574
|
}, workspace) : h2("code", { className: "dim-workspacePath" }, "\u672A\u8BBE\u7F6E"),
|
|
@@ -1453,10 +1585,10 @@ function WorkspaceEditor({ workspace, directoryPicker, disabled = false, onSave
|
|
|
1453
1585
|
}
|
|
1454
1586
|
|
|
1455
1587
|
// plugin-src/client/workspace-snapshot-fence.js
|
|
1456
|
-
var
|
|
1588
|
+
var React7 = __toESM(require("react"), 1);
|
|
1457
1589
|
function useWorkspaceSnapshotFence() {
|
|
1458
|
-
const state =
|
|
1459
|
-
return
|
|
1590
|
+
const state = React7.useRef({ version: 0, pendingMutations: 0 });
|
|
1591
|
+
return React7.useMemo(() => Object.freeze({
|
|
1460
1592
|
beginStatus() {
|
|
1461
1593
|
return state.current.pendingMutations === 0 ? state.current.version : null;
|
|
1462
1594
|
},
|
|
@@ -1636,7 +1768,7 @@ function DingtalkIcon({ size = 28 }) {
|
|
|
1636
1768
|
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"
|
|
1637
1769
|
}));
|
|
1638
1770
|
}
|
|
1639
|
-
var Button =
|
|
1771
|
+
var Button = React8.forwardRef(function Button2({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
1640
1772
|
return h2("button", {
|
|
1641
1773
|
...props,
|
|
1642
1774
|
ref,
|
|
@@ -1732,13 +1864,13 @@ function EmptyView({ busy, onStart }) {
|
|
|
1732
1864
|
);
|
|
1733
1865
|
}
|
|
1734
1866
|
function QrPanel({ provision, now, busy, onRefresh, onCancel }) {
|
|
1735
|
-
const [imageFailed, setImageFailed] =
|
|
1867
|
+
const [imageFailed, setImageFailed] = React8.useState(false);
|
|
1736
1868
|
const source = safeQrSource(provision.qrCodeDataUrl);
|
|
1737
1869
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
1738
1870
|
const expired = remaining === 0 || provision.status === "expired";
|
|
1739
1871
|
const duration = Math.max(1, provision.durationMs ?? 10 * 6e4);
|
|
1740
1872
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
1741
|
-
|
|
1873
|
+
React8.useEffect(() => setImageFailed(false), [source]);
|
|
1742
1874
|
return h2(
|
|
1743
1875
|
"div",
|
|
1744
1876
|
{ className: "ddt-card dim-surfaceCard" },
|
|
@@ -1855,8 +1987,8 @@ function checkedTime(value) {
|
|
|
1855
1987
|
}
|
|
1856
1988
|
}
|
|
1857
1989
|
function RemoveConfirmation({ account, busy, onConfirm, onCancel }) {
|
|
1858
|
-
const cancelRef =
|
|
1859
|
-
|
|
1990
|
+
const cancelRef = React8.useRef(null);
|
|
1991
|
+
React8.useEffect(() => cancelRef.current?.focus(), []);
|
|
1860
1992
|
return h2(
|
|
1861
1993
|
"div",
|
|
1862
1994
|
{
|
|
@@ -1888,6 +2020,7 @@ function AccountCard({
|
|
|
1888
2020
|
removing,
|
|
1889
2021
|
onReconnect,
|
|
1890
2022
|
onWorkspaceSave,
|
|
2023
|
+
onAgentPresetSave,
|
|
1891
2024
|
onRequestRemove,
|
|
1892
2025
|
onConfirmRemove,
|
|
1893
2026
|
onCancelRemove
|
|
@@ -1944,6 +2077,11 @@ function AccountCard({
|
|
|
1944
2077
|
disabled: Boolean(busy),
|
|
1945
2078
|
onSave: onWorkspaceSave
|
|
1946
2079
|
}),
|
|
2080
|
+
h2(AgentPresetEditor, {
|
|
2081
|
+
agentPreset: account.agentPreset,
|
|
2082
|
+
disabled: Boolean(busy),
|
|
2083
|
+
onSave: onAgentPresetSave
|
|
2084
|
+
}),
|
|
1947
2085
|
h2(
|
|
1948
2086
|
"div",
|
|
1949
2087
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -1995,6 +2133,7 @@ function AccountList(props) {
|
|
|
1995
2133
|
removing: props.removeTarget === account.botId,
|
|
1996
2134
|
onReconnect: () => props.onReconnect(account),
|
|
1997
2135
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
2136
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
1998
2137
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
1999
2138
|
onConfirmRemove: () => props.onConfirmRemove(account),
|
|
2000
2139
|
onCancelRemove: props.onCancelRemove
|
|
@@ -2004,29 +2143,30 @@ function AccountList(props) {
|
|
|
2004
2143
|
}
|
|
2005
2144
|
var EMPTY_TOTALS = Object.freeze({ configured: 0, connected: 0 });
|
|
2006
2145
|
function DingtalkSettingsTab({ rpcCall }) {
|
|
2007
|
-
const [model, setModel] =
|
|
2146
|
+
const [model, setModel] = React8.useState({
|
|
2008
2147
|
phase: "loading",
|
|
2009
2148
|
bots: [],
|
|
2010
2149
|
totals: EMPTY_TOTALS,
|
|
2011
2150
|
revision: 0,
|
|
2012
|
-
error: null
|
|
2151
|
+
error: null,
|
|
2152
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
2013
2153
|
});
|
|
2014
|
-
const [provision, setProvision] =
|
|
2015
|
-
const [busy, setBusy] =
|
|
2016
|
-
const [busyByBot, setBusyByBot] =
|
|
2017
|
-
const [feedbackByBot, setFeedbackByBot] =
|
|
2018
|
-
const [removeTarget, setRemoveTarget] =
|
|
2019
|
-
const [credentialOpen, setCredentialOpen] =
|
|
2020
|
-
const [credentialError, setCredentialError] =
|
|
2021
|
-
const [notice, setNotice] =
|
|
2022
|
-
const [now, setNow] =
|
|
2023
|
-
const addButtonRef =
|
|
2024
|
-
const mountedRef =
|
|
2025
|
-
const statusRequestRef =
|
|
2154
|
+
const [provision, setProvision] = React8.useState(null);
|
|
2155
|
+
const [busy, setBusy] = React8.useState(false);
|
|
2156
|
+
const [busyByBot, setBusyByBot] = React8.useState({});
|
|
2157
|
+
const [feedbackByBot, setFeedbackByBot] = React8.useState({});
|
|
2158
|
+
const [removeTarget, setRemoveTarget] = React8.useState(null);
|
|
2159
|
+
const [credentialOpen, setCredentialOpen] = React8.useState(false);
|
|
2160
|
+
const [credentialError, setCredentialError] = React8.useState(null);
|
|
2161
|
+
const [notice, setNotice] = React8.useState("");
|
|
2162
|
+
const [now, setNow] = React8.useState(() => Date.now());
|
|
2163
|
+
const addButtonRef = React8.useRef(null);
|
|
2164
|
+
const mountedRef = React8.useRef(true);
|
|
2165
|
+
const statusRequestRef = React8.useRef(0);
|
|
2026
2166
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
2027
|
-
const noticeFrameRef =
|
|
2028
|
-
const focusFrameRef =
|
|
2029
|
-
|
|
2167
|
+
const noticeFrameRef = React8.useRef(null);
|
|
2168
|
+
const focusFrameRef = React8.useRef(null);
|
|
2169
|
+
React8.useEffect(() => {
|
|
2030
2170
|
mountedRef.current = true;
|
|
2031
2171
|
return () => {
|
|
2032
2172
|
mountedRef.current = false;
|
|
@@ -2041,8 +2181,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2041
2181
|
}
|
|
2042
2182
|
};
|
|
2043
2183
|
}, []);
|
|
2044
|
-
|
|
2045
|
-
const announce =
|
|
2184
|
+
React8.useEffect(() => installDingtalkStyles(), []);
|
|
2185
|
+
const announce = React8.useCallback((message) => {
|
|
2046
2186
|
if (!mountedRef.current) return;
|
|
2047
2187
|
if (noticeFrameRef.current !== null) {
|
|
2048
2188
|
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
@@ -2056,7 +2196,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2056
2196
|
});
|
|
2057
2197
|
}
|
|
2058
2198
|
}, []);
|
|
2059
|
-
const discardStaleFeedback =
|
|
2199
|
+
const discardStaleFeedback = React8.useCallback((snapshot) => {
|
|
2060
2200
|
const botsById = new Map(snapshot.bots.map((bot) => [bot.botId, bot]));
|
|
2061
2201
|
setFeedbackByBot((current) => {
|
|
2062
2202
|
let changed = false;
|
|
@@ -2071,7 +2211,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2071
2211
|
return changed ? next : current;
|
|
2072
2212
|
});
|
|
2073
2213
|
}, []);
|
|
2074
|
-
const focusAddButton =
|
|
2214
|
+
const focusAddButton = React8.useCallback(() => {
|
|
2075
2215
|
if (!mountedRef.current) return;
|
|
2076
2216
|
if (focusFrameRef.current !== null) window.cancelAnimationFrame(focusFrameRef.current);
|
|
2077
2217
|
focusFrameRef.current = window.requestAnimationFrame(() => {
|
|
@@ -2079,11 +2219,11 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2079
2219
|
if (mountedRef.current) addButtonRef.current?.focus();
|
|
2080
2220
|
});
|
|
2081
2221
|
}, []);
|
|
2082
|
-
const invoke =
|
|
2222
|
+
const invoke = React8.useCallback(async (endpoint, payload = {}, signal) => {
|
|
2083
2223
|
if (typeof rpcCall !== "function") throw new TypeError("\u9489\u9489\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
2084
2224
|
return unwrapRpcResult(await rpcCall(endpoint, payload, signal));
|
|
2085
2225
|
}, [rpcCall]);
|
|
2086
|
-
const loadStatus =
|
|
2226
|
+
const loadStatus = React8.useCallback(async ({
|
|
2087
2227
|
signal,
|
|
2088
2228
|
silent = false,
|
|
2089
2229
|
restoreProvisioning = false
|
|
@@ -2105,7 +2245,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2105
2245
|
bots: snapshot.bots,
|
|
2106
2246
|
totals: snapshot.totals,
|
|
2107
2247
|
revision: snapshot.revision,
|
|
2108
|
-
error: null
|
|
2248
|
+
error: null,
|
|
2249
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2109
2250
|
});
|
|
2110
2251
|
discardStaleFeedback(snapshot);
|
|
2111
2252
|
if (restoreProvisioning && snapshot.provisioning) {
|
|
@@ -2126,12 +2267,12 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2126
2267
|
return void 0;
|
|
2127
2268
|
}
|
|
2128
2269
|
}, [discardStaleFeedback, invoke, workspaceFence]);
|
|
2129
|
-
|
|
2270
|
+
React8.useEffect(() => {
|
|
2130
2271
|
const controller = new AbortController();
|
|
2131
2272
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
2132
2273
|
return () => controller.abort();
|
|
2133
2274
|
}, [loadStatus]);
|
|
2134
|
-
|
|
2275
|
+
React8.useEffect(() => {
|
|
2135
2276
|
if (model.phase !== "ready") return void 0;
|
|
2136
2277
|
const controller = new AbortController();
|
|
2137
2278
|
let running = false;
|
|
@@ -2150,14 +2291,14 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2150
2291
|
window.clearInterval(timer);
|
|
2151
2292
|
};
|
|
2152
2293
|
}, [loadStatus, model.phase]);
|
|
2153
|
-
|
|
2294
|
+
React8.useEffect(() => {
|
|
2154
2295
|
if (!provision || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
|
|
2155
2296
|
const timer = window.setInterval(() => {
|
|
2156
2297
|
if (mountedRef.current) setNow(Date.now());
|
|
2157
2298
|
}, 1e3);
|
|
2158
2299
|
return () => window.clearInterval(timer);
|
|
2159
2300
|
}, [provision?.attemptId, provision?.status]);
|
|
2160
|
-
const startProvisioning =
|
|
2301
|
+
const startProvisioning = React8.useCallback(async ({ replace = false } = {}) => {
|
|
2161
2302
|
if (!mountedRef.current) return;
|
|
2162
2303
|
setCredentialOpen(false);
|
|
2163
2304
|
setCredentialError(null);
|
|
@@ -2195,7 +2336,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2195
2336
|
if (mountedRef.current) setBusy(false);
|
|
2196
2337
|
}
|
|
2197
2338
|
}, [announce, invoke, provision?.attemptId]);
|
|
2198
|
-
const bindCredentials =
|
|
2339
|
+
const bindCredentials = React8.useCallback(async ({ identity, secret }) => {
|
|
2199
2340
|
if (!mountedRef.current) return;
|
|
2200
2341
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2201
2342
|
setBusy(true);
|
|
@@ -2212,7 +2353,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2212
2353
|
bots: snapshot.bots,
|
|
2213
2354
|
totals: snapshot.totals,
|
|
2214
2355
|
revision: snapshot.revision,
|
|
2215
|
-
error: null
|
|
2356
|
+
error: null,
|
|
2357
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2216
2358
|
});
|
|
2217
2359
|
discardStaleFeedback(snapshot);
|
|
2218
2360
|
}
|
|
@@ -2226,7 +2368,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2226
2368
|
if (mountedRef.current) setBusy(false);
|
|
2227
2369
|
}
|
|
2228
2370
|
}, [announce, discardStaleFeedback, invoke, loadStatus, workspaceFence]);
|
|
2229
|
-
const cancelProvisioning =
|
|
2371
|
+
const cancelProvisioning = React8.useCallback(async () => {
|
|
2230
2372
|
if (!mountedRef.current) return;
|
|
2231
2373
|
setBusy(true);
|
|
2232
2374
|
try {
|
|
@@ -2244,7 +2386,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2244
2386
|
if (mountedRef.current) setBusy(false);
|
|
2245
2387
|
}
|
|
2246
2388
|
}, [announce, focusAddButton, invoke, provision?.attemptId, provision?.status]);
|
|
2247
|
-
|
|
2389
|
+
React8.useEffect(() => {
|
|
2248
2390
|
const attemptId = provision?.attemptId;
|
|
2249
2391
|
if (!attemptId || !ACTIVE_PROVISION_STATES.has(provision.status)) return void 0;
|
|
2250
2392
|
const controller = new AbortController();
|
|
@@ -2303,7 +2445,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2303
2445
|
timer = null;
|
|
2304
2446
|
};
|
|
2305
2447
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
2306
|
-
const setBotBusy =
|
|
2448
|
+
const setBotBusy = React8.useCallback((botId, operation) => {
|
|
2307
2449
|
if (!mountedRef.current) return;
|
|
2308
2450
|
setBusyByBot((current) => {
|
|
2309
2451
|
const next = { ...current };
|
|
@@ -2312,7 +2454,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2312
2454
|
return next;
|
|
2313
2455
|
});
|
|
2314
2456
|
}, []);
|
|
2315
|
-
const runBotAction =
|
|
2457
|
+
const runBotAction = React8.useCallback(async ({ account, operation, endpoint, payload, success }) => {
|
|
2316
2458
|
if (!mountedRef.current) return void 0;
|
|
2317
2459
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2318
2460
|
setBotBusy(account.botId, operation);
|
|
@@ -2332,7 +2474,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2332
2474
|
bots: snapshot.bots,
|
|
2333
2475
|
totals: snapshot.totals,
|
|
2334
2476
|
revision: snapshot.revision,
|
|
2335
|
-
error: null
|
|
2477
|
+
error: null,
|
|
2478
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2336
2479
|
});
|
|
2337
2480
|
discardStaleFeedback(snapshot);
|
|
2338
2481
|
}
|
|
@@ -2365,7 +2508,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2365
2508
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2366
2509
|
}
|
|
2367
2510
|
}, [announce, discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2368
|
-
const reconnect =
|
|
2511
|
+
const reconnect = React8.useCallback((account) => runBotAction({
|
|
2369
2512
|
account,
|
|
2370
2513
|
operation: "reconnect",
|
|
2371
2514
|
endpoint: DINGTALK_ENDPOINTS.reconnectBot,
|
|
@@ -2376,7 +2519,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2376
2519
|
return connectionTestFeedback(snapshot.testMessage) ?? "\u9489\u9489\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\u3002";
|
|
2377
2520
|
}
|
|
2378
2521
|
}), [runBotAction]);
|
|
2379
|
-
const saveWorkspace =
|
|
2522
|
+
const saveWorkspace = React8.useCallback(async (account, workspace) => {
|
|
2380
2523
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
2381
2524
|
setBotBusy(account.botId, "workspace");
|
|
2382
2525
|
try {
|
|
@@ -2390,7 +2533,8 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2390
2533
|
bots: snapshot.bots,
|
|
2391
2534
|
totals: snapshot.totals,
|
|
2392
2535
|
revision: snapshot.revision,
|
|
2393
|
-
error: null
|
|
2536
|
+
error: null,
|
|
2537
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2394
2538
|
});
|
|
2395
2539
|
discardStaleFeedback(snapshot);
|
|
2396
2540
|
}
|
|
@@ -2400,7 +2544,32 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2400
2544
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2401
2545
|
}
|
|
2402
2546
|
}, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2403
|
-
const
|
|
2547
|
+
const saveAgentPreset = React8.useCallback(async (account, agentPreset) => {
|
|
2548
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
2549
|
+
setBotBusy(account.botId, "preset");
|
|
2550
|
+
try {
|
|
2551
|
+
const snapshot = normalizeSnapshot(await invoke(
|
|
2552
|
+
DINGTALK_ENDPOINTS.setAgentPreset,
|
|
2553
|
+
{ botId: account.botId, agentPreset }
|
|
2554
|
+
));
|
|
2555
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2556
|
+
setModel({
|
|
2557
|
+
phase: "ready",
|
|
2558
|
+
bots: snapshot.bots,
|
|
2559
|
+
totals: snapshot.totals,
|
|
2560
|
+
revision: snapshot.revision,
|
|
2561
|
+
error: null,
|
|
2562
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2563
|
+
});
|
|
2564
|
+
discardStaleFeedback(snapshot);
|
|
2565
|
+
}
|
|
2566
|
+
} finally {
|
|
2567
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
2568
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
2569
|
+
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
2570
|
+
}
|
|
2571
|
+
}, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
2572
|
+
const remove = React8.useCallback(async (account) => {
|
|
2404
2573
|
const snapshot = await runBotAction({
|
|
2405
2574
|
account,
|
|
2406
2575
|
operation: "delete",
|
|
@@ -2454,7 +2623,9 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2454
2623
|
setCredentialError(null);
|
|
2455
2624
|
}
|
|
2456
2625
|
}) : null;
|
|
2457
|
-
return h2(
|
|
2626
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
2627
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2628
|
+
}, h2(
|
|
2458
2629
|
"section",
|
|
2459
2630
|
{ className: "ddt-page dim-channelPage", "aria-label": "\u9489\u9489\u8BBE\u7F6E" },
|
|
2460
2631
|
h2(Heading, {
|
|
@@ -2482,7 +2653,7 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2482
2653
|
h2(Button, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
2483
2654
|
)
|
|
2484
2655
|
) : h2(
|
|
2485
|
-
|
|
2656
|
+
React8.Fragment,
|
|
2486
2657
|
null,
|
|
2487
2658
|
credentialView,
|
|
2488
2659
|
provisionView,
|
|
@@ -2494,12 +2665,13 @@ function DingtalkSettingsTab({ rpcCall }) {
|
|
|
2494
2665
|
removeTarget,
|
|
2495
2666
|
onReconnect: (account) => void reconnect(account),
|
|
2496
2667
|
onWorkspaceSave: saveWorkspace,
|
|
2668
|
+
onAgentPresetSave: saveAgentPreset,
|
|
2497
2669
|
onRequestRemove: (account) => setRemoveTarget(account.botId),
|
|
2498
2670
|
onConfirmRemove: (account) => void remove(account),
|
|
2499
2671
|
onCancelRemove: () => setRemoveTarget(null)
|
|
2500
2672
|
}) : null
|
|
2501
2673
|
)
|
|
2502
|
-
);
|
|
2674
|
+
));
|
|
2503
2675
|
}
|
|
2504
2676
|
|
|
2505
2677
|
// plugin-src/client/channels/shared/token-api.js
|
|
@@ -2524,7 +2696,8 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
2524
2696
|
bindCredentials: "bot.bind-credentials",
|
|
2525
2697
|
reconnectBot: "bot.reconnect",
|
|
2526
2698
|
deleteBot: "bot.delete",
|
|
2527
|
-
setWorkspace: "bot.workspace.set"
|
|
2699
|
+
setWorkspace: "bot.workspace.set",
|
|
2700
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
2528
2701
|
});
|
|
2529
2702
|
function createTokenChannelApi(channel4, connectionSummary, {
|
|
2530
2703
|
normalizeBotExtension = () => ({})
|
|
@@ -2550,6 +2723,7 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
2550
2723
|
connected,
|
|
2551
2724
|
state: connected ? "connected" : state,
|
|
2552
2725
|
workspace: text(value.workspace, "", 4096),
|
|
2726
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
2553
2727
|
bot: {
|
|
2554
2728
|
name: text(value.bot?.name, `${channel4}\u673A\u5668\u4EBA`, 100),
|
|
2555
2729
|
username: text(value.bot?.username, "", 100),
|
|
@@ -2578,7 +2752,8 @@ function createTokenChannelApi(channel4, connectionSummary, {
|
|
|
2578
2752
|
return {
|
|
2579
2753
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
2580
2754
|
bots,
|
|
2581
|
-
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length }
|
|
2755
|
+
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
2756
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
2582
2757
|
};
|
|
2583
2758
|
};
|
|
2584
2759
|
const presentError10 = (error) => ({
|
|
@@ -2597,8 +2772,8 @@ var normalizeSnapshot2 = api.normalizeSnapshot;
|
|
|
2597
2772
|
var presentError2 = api.presentError;
|
|
2598
2773
|
|
|
2599
2774
|
// plugin-src/client/channels/shared/token-channel.js
|
|
2600
|
-
var
|
|
2601
|
-
var Button3 =
|
|
2775
|
+
var React9 = __toESM(require("react"), 1);
|
|
2776
|
+
var Button3 = React9.forwardRef(function Button4({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
2602
2777
|
return h2("button", {
|
|
2603
2778
|
...props,
|
|
2604
2779
|
ref,
|
|
@@ -2650,7 +2825,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2650
2825
|
AccountSettings = null,
|
|
2651
2826
|
accountSettingsEndpoint = null
|
|
2652
2827
|
} = definition;
|
|
2653
|
-
function AccountCard5({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
2828
|
+
function AccountCard5({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
2654
2829
|
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
2655
2830
|
const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
|
|
2656
2831
|
const stateLabel2 = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
@@ -2708,6 +2883,11 @@ function createTokenChannelSettings(definition) {
|
|
|
2708
2883
|
disabled: Boolean(busy),
|
|
2709
2884
|
onSave: onWorkspaceSave
|
|
2710
2885
|
}),
|
|
2886
|
+
h2(AgentPresetEditor, {
|
|
2887
|
+
agentPreset: account.agentPreset,
|
|
2888
|
+
disabled: Boolean(busy),
|
|
2889
|
+
onSave: onAgentPresetSave
|
|
2890
|
+
}),
|
|
2711
2891
|
AccountSettings ? h2(AccountSettings, {
|
|
2712
2892
|
account,
|
|
2713
2893
|
busy: Boolean(busy),
|
|
@@ -2754,21 +2934,22 @@ function createTokenChannelSettings(definition) {
|
|
|
2754
2934
|
);
|
|
2755
2935
|
}
|
|
2756
2936
|
function SettingsTab({ rpcCall }) {
|
|
2757
|
-
const [model, setModel] =
|
|
2937
|
+
const [model, setModel] = React9.useState({
|
|
2758
2938
|
phase: "loading",
|
|
2759
2939
|
bots: [],
|
|
2760
2940
|
totals: { configured: 0, connected: 0 },
|
|
2761
|
-
error: null
|
|
2941
|
+
error: null,
|
|
2942
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
2762
2943
|
});
|
|
2763
|
-
const [credentialOpen, setCredentialOpen] =
|
|
2764
|
-
const [credentialError, setCredentialError] =
|
|
2765
|
-
const [busy, setBusy] =
|
|
2766
|
-
const [busyByBot, setBusyByBot] =
|
|
2767
|
-
const [testNoticeByBot, setTestNoticeByBot] =
|
|
2768
|
-
const [removeTarget, setRemoveTarget] =
|
|
2769
|
-
const mounted =
|
|
2944
|
+
const [credentialOpen, setCredentialOpen] = React9.useState(false);
|
|
2945
|
+
const [credentialError, setCredentialError] = React9.useState(null);
|
|
2946
|
+
const [busy, setBusy] = React9.useState(false);
|
|
2947
|
+
const [busyByBot, setBusyByBot] = React9.useState({});
|
|
2948
|
+
const [testNoticeByBot, setTestNoticeByBot] = React9.useState({});
|
|
2949
|
+
const [removeTarget, setRemoveTarget] = React9.useState(null);
|
|
2950
|
+
const mounted = React9.useRef(true);
|
|
2770
2951
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
2771
|
-
|
|
2952
|
+
React9.useEffect(() => {
|
|
2772
2953
|
const disposeDingtalk = installDingtalkStyles();
|
|
2773
2954
|
const disposeChannel = installStyles();
|
|
2774
2955
|
mounted.current = true;
|
|
@@ -2778,18 +2959,24 @@ function createTokenChannelSettings(definition) {
|
|
|
2778
2959
|
disposeDingtalk();
|
|
2779
2960
|
};
|
|
2780
2961
|
}, []);
|
|
2781
|
-
const invoke =
|
|
2962
|
+
const invoke = React9.useCallback(async (endpoint, payload = {}, signal) => {
|
|
2782
2963
|
if (typeof rpcCall !== "function") throw new TypeError(`${channel4} \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5`);
|
|
2783
2964
|
return api4.unwrapRpcResult(await rpcCall(endpoint, payload, signal));
|
|
2784
2965
|
}, [rpcCall]);
|
|
2785
|
-
const loadStatus =
|
|
2966
|
+
const loadStatus = React9.useCallback(async ({ signal, silent = false } = {}) => {
|
|
2786
2967
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
2787
2968
|
if (workspaceVersion === null) return;
|
|
2788
2969
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
2789
2970
|
try {
|
|
2790
2971
|
const snapshot = api4.normalizeSnapshot(await invoke(endpoints.status, {}, signal));
|
|
2791
2972
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return;
|
|
2792
|
-
setModel({
|
|
2973
|
+
setModel({
|
|
2974
|
+
phase: "ready",
|
|
2975
|
+
bots: snapshot.bots,
|
|
2976
|
+
totals: snapshot.totals,
|
|
2977
|
+
error: null,
|
|
2978
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
2979
|
+
});
|
|
2793
2980
|
} catch (error) {
|
|
2794
2981
|
if (error?.name !== "AbortError" && mounted.current && !signal?.aborted && workspaceFence.canCommitStatus(workspaceVersion)) {
|
|
2795
2982
|
setModel((current) => ({
|
|
@@ -2800,12 +2987,12 @@ function createTokenChannelSettings(definition) {
|
|
|
2800
2987
|
}
|
|
2801
2988
|
}
|
|
2802
2989
|
}, [invoke, workspaceFence]);
|
|
2803
|
-
|
|
2990
|
+
React9.useEffect(() => {
|
|
2804
2991
|
const controller = new AbortController();
|
|
2805
2992
|
void loadStatus({ signal: controller.signal });
|
|
2806
2993
|
return () => controller.abort();
|
|
2807
2994
|
}, [loadStatus]);
|
|
2808
|
-
|
|
2995
|
+
React9.useEffect(() => {
|
|
2809
2996
|
if (model.phase !== "ready") return void 0;
|
|
2810
2997
|
const controller = new AbortController();
|
|
2811
2998
|
const timer = window.setInterval(
|
|
@@ -2817,7 +3004,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2817
3004
|
window.clearInterval(timer);
|
|
2818
3005
|
};
|
|
2819
3006
|
}, [loadStatus, model.phase]);
|
|
2820
|
-
const bindCredentials =
|
|
3007
|
+
const bindCredentials = React9.useCallback(async (values) => {
|
|
2821
3008
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2822
3009
|
setBusy(true);
|
|
2823
3010
|
setCredentialError(null);
|
|
@@ -2828,7 +3015,13 @@ function createTokenChannelSettings(definition) {
|
|
|
2828
3015
|
));
|
|
2829
3016
|
if (!mounted.current) return;
|
|
2830
3017
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2831
|
-
setModel({
|
|
3018
|
+
setModel({
|
|
3019
|
+
phase: "ready",
|
|
3020
|
+
bots: snapshot.bots,
|
|
3021
|
+
totals: snapshot.totals,
|
|
3022
|
+
error: null,
|
|
3023
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3024
|
+
});
|
|
2832
3025
|
}
|
|
2833
3026
|
setCredentialOpen(false);
|
|
2834
3027
|
} catch (error) {
|
|
@@ -2839,14 +3032,20 @@ function createTokenChannelSettings(definition) {
|
|
|
2839
3032
|
if (mounted.current) setBusy(false);
|
|
2840
3033
|
}
|
|
2841
3034
|
}, [invoke, loadStatus, workspaceFence]);
|
|
2842
|
-
const botAction =
|
|
3035
|
+
const botAction = React9.useCallback(async (account, operation, endpoint, payload) => {
|
|
2843
3036
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
2844
3037
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
2845
3038
|
try {
|
|
2846
3039
|
const value = await invoke(endpoint, payload);
|
|
2847
3040
|
const snapshot = api4.normalizeSnapshot(value);
|
|
2848
3041
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
2849
|
-
setModel({
|
|
3042
|
+
setModel({
|
|
3043
|
+
phase: "ready",
|
|
3044
|
+
bots: snapshot.bots,
|
|
3045
|
+
totals: snapshot.totals,
|
|
3046
|
+
error: null,
|
|
3047
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3048
|
+
});
|
|
2850
3049
|
}
|
|
2851
3050
|
if (mounted.current && operation === "reconnect") {
|
|
2852
3051
|
setTestNoticeByBot((current) => ({
|
|
@@ -2897,6 +3096,12 @@ function createTokenChannelSettings(definition) {
|
|
|
2897
3096
|
endpoints.setWorkspace,
|
|
2898
3097
|
{ botId: account.botId, workspace }
|
|
2899
3098
|
),
|
|
3099
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
3100
|
+
account,
|
|
3101
|
+
"preset",
|
|
3102
|
+
endpoints.setAgentPreset,
|
|
3103
|
+
{ botId: account.botId, agentPreset }
|
|
3104
|
+
),
|
|
2900
3105
|
onAccountSettingsSave: AccountSettings && accountSettingsEndpoint ? (payload) => botAction(
|
|
2901
3106
|
account,
|
|
2902
3107
|
"settings",
|
|
@@ -2914,7 +3119,9 @@ function createTokenChannelSettings(definition) {
|
|
|
2914
3119
|
}
|
|
2915
3120
|
}))))
|
|
2916
3121
|
) : null;
|
|
2917
|
-
return h2(
|
|
3122
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
3123
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
3124
|
+
}, h2(
|
|
2918
3125
|
"section",
|
|
2919
3126
|
{
|
|
2920
3127
|
className: `ddt-page ${pageClass} dim-channelPage`,
|
|
@@ -2962,7 +3169,7 @@ function createTokenChannelSettings(definition) {
|
|
|
2962
3169
|
h2(Button3, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
2963
3170
|
)
|
|
2964
3171
|
) : h2(
|
|
2965
|
-
|
|
3172
|
+
React9.Fragment,
|
|
2966
3173
|
null,
|
|
2967
3174
|
credentialOpen ? CredentialPanel ? h2(CredentialPanel, {
|
|
2968
3175
|
busy,
|
|
@@ -3018,7 +3225,7 @@ function createTokenChannelSettings(definition) {
|
|
|
3018
3225
|
) : null,
|
|
3019
3226
|
botList
|
|
3020
3227
|
)
|
|
3021
|
-
);
|
|
3228
|
+
));
|
|
3022
3229
|
}
|
|
3023
3230
|
return { SettingsTab, AccountCard: AccountCard5 };
|
|
3024
3231
|
}
|
|
@@ -3063,7 +3270,7 @@ var DiscordSettingsTab = channel.SettingsTab;
|
|
|
3063
3270
|
var DiscordAccountCard = channel.AccountCard;
|
|
3064
3271
|
|
|
3065
3272
|
// plugin-src/client/channels/feishu/index.js
|
|
3066
|
-
var
|
|
3273
|
+
var React11 = __toESM(require("react"), 1);
|
|
3067
3274
|
|
|
3068
3275
|
// plugin-src/client/channels/feishu/api.js
|
|
3069
3276
|
var FEISHU_RPC_CHANNEL = "/feishu";
|
|
@@ -3078,6 +3285,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
|
|
|
3078
3285
|
disconnectBot: "bot.disconnect",
|
|
3079
3286
|
deleteBot: "bot.delete",
|
|
3080
3287
|
setWorkspace: "bot.workspace.set",
|
|
3288
|
+
setAgentPreset: "bot.preset.set",
|
|
3081
3289
|
// Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
|
|
3082
3290
|
testConnection: "connection.test",
|
|
3083
3291
|
disconnect: "connection.disconnect"
|
|
@@ -3211,6 +3419,7 @@ function normalizeBotConnection(value, fallbackBotId) {
|
|
|
3211
3419
|
connected,
|
|
3212
3420
|
configured: value.configured !== false,
|
|
3213
3421
|
workspace: optionalString2(value.workspace)?.slice(0, 4096) ?? "",
|
|
3422
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
3214
3423
|
bot: normalizeBot2(value.bot),
|
|
3215
3424
|
health: normalizeHealth(value.health, connected),
|
|
3216
3425
|
error: normalizeError2(value.error)
|
|
@@ -3251,7 +3460,8 @@ function normalizeBotsSnapshot(value) {
|
|
|
3251
3460
|
// make the UI claim that an unavailable bot is online.
|
|
3252
3461
|
totals: { configured, connected },
|
|
3253
3462
|
provisioning: value.provisioning ? normalizeProvisioning2(value.provisioning) : void 0,
|
|
3254
|
-
error: normalizeError2(value.error)
|
|
3463
|
+
error: normalizeError2(value.error),
|
|
3464
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog)
|
|
3255
3465
|
};
|
|
3256
3466
|
}
|
|
3257
3467
|
function normalizeConnectionSnapshot(value) {
|
|
@@ -3301,7 +3511,7 @@ function formatRemaining2(milliseconds) {
|
|
|
3301
3511
|
}
|
|
3302
3512
|
|
|
3303
3513
|
// plugin-src/client/lifecycle.js
|
|
3304
|
-
var
|
|
3514
|
+
var React10 = __toESM(require("react"), 1);
|
|
3305
3515
|
function createPollScheduler({ setTimeoutFn, clearTimeoutFn }) {
|
|
3306
3516
|
let disposed = false;
|
|
3307
3517
|
let timer;
|
|
@@ -3363,8 +3573,8 @@ function createAnimationFrameScheduler({ requestFrame, cancelFrame }) {
|
|
|
3363
3573
|
};
|
|
3364
3574
|
}
|
|
3365
3575
|
function useAnimationFrameScheduler() {
|
|
3366
|
-
const schedulerRef =
|
|
3367
|
-
|
|
3576
|
+
const schedulerRef = React10.useRef(null);
|
|
3577
|
+
React10.useEffect(() => {
|
|
3368
3578
|
const scheduler = createAnimationFrameScheduler({
|
|
3369
3579
|
requestFrame: (callback) => window.requestAnimationFrame(callback),
|
|
3370
3580
|
cancelFrame: (frame) => window.cancelAnimationFrame(frame)
|
|
@@ -3375,7 +3585,7 @@ function useAnimationFrameScheduler() {
|
|
|
3375
3585
|
if (schedulerRef.current === scheduler) schedulerRef.current = null;
|
|
3376
3586
|
};
|
|
3377
3587
|
}, []);
|
|
3378
|
-
return
|
|
3588
|
+
return React10.useCallback(
|
|
3379
3589
|
(callback, key) => schedulerRef.current?.schedule(callback, key) ?? false,
|
|
3380
3590
|
[]
|
|
3381
3591
|
);
|
|
@@ -3949,7 +4159,7 @@ function QrIcon({ size = 58 }) {
|
|
|
3949
4159
|
fill: "currentColor"
|
|
3950
4160
|
}));
|
|
3951
4161
|
}
|
|
3952
|
-
var Button5 =
|
|
4162
|
+
var Button5 = React11.forwardRef(function Button6({ children, kind = "secondary", size, icon, className = "", ...props }, ref) {
|
|
3953
4163
|
return h2("button", {
|
|
3954
4164
|
...props,
|
|
3955
4165
|
ref,
|
|
@@ -4066,7 +4276,7 @@ function safeQrSource2(value) {
|
|
|
4066
4276
|
return /^data:image\/(?:png|webp|svg\+xml)(?:;charset=[^;,]+)?;base64,/i.test(value) ? value : void 0;
|
|
4067
4277
|
}
|
|
4068
4278
|
function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
4069
|
-
const [imageFailed, setImageFailed] =
|
|
4279
|
+
const [imageFailed, setImageFailed] = React11.useState(false);
|
|
4070
4280
|
const qrSource = safeQrSource2(provision.qrCodeDataUrl);
|
|
4071
4281
|
const href = safeVerificationHref(provision.verificationUrl);
|
|
4072
4282
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
@@ -4074,7 +4284,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
|
|
|
4074
4284
|
const progress = Math.min(1, remaining / Math.max(1, provision.durationMs ?? remaining));
|
|
4075
4285
|
const repairing = isCallbackRepair(provision);
|
|
4076
4286
|
const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
|
|
4077
|
-
|
|
4287
|
+
React11.useEffect(() => setImageFailed(false), [qrSource]);
|
|
4078
4288
|
return h2(
|
|
4079
4289
|
"div",
|
|
4080
4290
|
{ className: "bxf-card bxf-provisionCard dim-surfaceCard" },
|
|
@@ -4235,11 +4445,11 @@ function connectionTestNotice2(value) {
|
|
|
4235
4445
|
return value?.testMessage ? "\u8FDE\u63A5\u68C0\u67E5\u5B8C\u6210\uFF0C\u4F46\u6D4B\u8BD5\u6D88\u606F\u53D1\u9001\u5931\u8D25\u3002" : null;
|
|
4236
4446
|
}
|
|
4237
4447
|
function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
|
|
4238
|
-
const cancelRef =
|
|
4448
|
+
const cancelRef = React11.useRef(null);
|
|
4239
4449
|
const idPart = bot.botId.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
4240
4450
|
const titleId = `bxf-remove-title-${idPart}`;
|
|
4241
4451
|
const descriptionId = `bxf-remove-description-${idPart}`;
|
|
4242
|
-
|
|
4452
|
+
React11.useEffect(() => cancelRef.current?.focus(), []);
|
|
4243
4453
|
return h2(
|
|
4244
4454
|
"div",
|
|
4245
4455
|
{
|
|
@@ -4282,6 +4492,7 @@ function BotCard({
|
|
|
4282
4492
|
onReconnect,
|
|
4283
4493
|
onRepairCallback,
|
|
4284
4494
|
onWorkspaceSave,
|
|
4495
|
+
onAgentPresetSave,
|
|
4285
4496
|
onRequestRemove,
|
|
4286
4497
|
onConfirmRemove,
|
|
4287
4498
|
onCancelRemove,
|
|
@@ -4351,6 +4562,11 @@ function BotCard({
|
|
|
4351
4562
|
disabled: Boolean(busy),
|
|
4352
4563
|
onSave: onWorkspaceSave
|
|
4353
4564
|
}),
|
|
4565
|
+
h2(AgentPresetEditor, {
|
|
4566
|
+
agentPreset: connection.agentPreset,
|
|
4567
|
+
disabled: Boolean(busy),
|
|
4568
|
+
onSave: onAgentPresetSave
|
|
4569
|
+
}),
|
|
4354
4570
|
h2(
|
|
4355
4571
|
"div",
|
|
4356
4572
|
{ className: "bxf-connectedFooter dim-cardFooter" },
|
|
@@ -4424,6 +4640,7 @@ function BotList(props) {
|
|
|
4424
4640
|
onReconnect: () => props.onReconnect(bot),
|
|
4425
4641
|
onRepairCallback: () => props.onRepairCallback(bot),
|
|
4426
4642
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
|
|
4643
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
|
|
4427
4644
|
onRequestRemove: () => props.onRequestRemove(bot),
|
|
4428
4645
|
onConfirmRemove: () => props.onConfirmRemove(bot),
|
|
4429
4646
|
onCancelRemove: props.onCancelRemove,
|
|
@@ -4481,53 +4698,55 @@ function mergeFeishuSnapshotState(current, snapshot, { restoreProvisioning = fal
|
|
|
4481
4698
|
totals: snapshot.totals,
|
|
4482
4699
|
provisioning,
|
|
4483
4700
|
pageError: null,
|
|
4484
|
-
statusError: null
|
|
4701
|
+
statusError: null,
|
|
4702
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
4485
4703
|
};
|
|
4486
4704
|
}
|
|
4487
4705
|
function FeishuSettingsTab({ rpcCall }) {
|
|
4488
|
-
const [model, setModel] =
|
|
4706
|
+
const [model, setModel] = React11.useState({
|
|
4489
4707
|
phase: "loading",
|
|
4490
4708
|
revision: 0,
|
|
4491
4709
|
bots: [],
|
|
4492
4710
|
totals: EMPTY_TOTALS2,
|
|
4493
4711
|
provisioning: null,
|
|
4494
4712
|
pageError: null,
|
|
4495
|
-
statusError: null
|
|
4713
|
+
statusError: null,
|
|
4714
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
4496
4715
|
});
|
|
4497
|
-
const [pageBusy, setPageBusy] =
|
|
4498
|
-
const [provisionBusy, setProvisionBusy] =
|
|
4499
|
-
const [credentialOpen, setCredentialOpen] =
|
|
4500
|
-
const [credentialBusy, setCredentialBusy] =
|
|
4501
|
-
const [credentialError, setCredentialError] =
|
|
4502
|
-
const [busyByBot, setBusyByBot] =
|
|
4503
|
-
const [errorsByBot, setErrorsByBot] =
|
|
4504
|
-
const [testNoticesByBot, setTestNoticesByBot] =
|
|
4505
|
-
const [removeTargetId, setRemoveTargetId] =
|
|
4506
|
-
const [announcement, setAnnouncement] =
|
|
4507
|
-
const [now, setNow] =
|
|
4508
|
-
const [focusBotId, setFocusBotId] =
|
|
4509
|
-
const cardRefs =
|
|
4510
|
-
const removeButtonRefs =
|
|
4511
|
-
const addButtonRef =
|
|
4512
|
-
const mountedRef =
|
|
4716
|
+
const [pageBusy, setPageBusy] = React11.useState(false);
|
|
4717
|
+
const [provisionBusy, setProvisionBusy] = React11.useState(false);
|
|
4718
|
+
const [credentialOpen, setCredentialOpen] = React11.useState(false);
|
|
4719
|
+
const [credentialBusy, setCredentialBusy] = React11.useState(false);
|
|
4720
|
+
const [credentialError, setCredentialError] = React11.useState(null);
|
|
4721
|
+
const [busyByBot, setBusyByBot] = React11.useState({});
|
|
4722
|
+
const [errorsByBot, setErrorsByBot] = React11.useState({});
|
|
4723
|
+
const [testNoticesByBot, setTestNoticesByBot] = React11.useState({});
|
|
4724
|
+
const [removeTargetId, setRemoveTargetId] = React11.useState(null);
|
|
4725
|
+
const [announcement, setAnnouncement] = React11.useState("");
|
|
4726
|
+
const [now, setNow] = React11.useState(() => Date.now());
|
|
4727
|
+
const [focusBotId, setFocusBotId] = React11.useState(null);
|
|
4728
|
+
const cardRefs = React11.useRef(/* @__PURE__ */ new Map());
|
|
4729
|
+
const removeButtonRefs = React11.useRef(/* @__PURE__ */ new Map());
|
|
4730
|
+
const addButtonRef = React11.useRef(null);
|
|
4731
|
+
const mountedRef = React11.useRef(true);
|
|
4513
4732
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
4514
4733
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
4515
|
-
|
|
4734
|
+
React11.useEffect(() => {
|
|
4516
4735
|
mountedRef.current = true;
|
|
4517
4736
|
return () => {
|
|
4518
4737
|
mountedRef.current = false;
|
|
4519
4738
|
};
|
|
4520
4739
|
}, []);
|
|
4521
|
-
const announce =
|
|
4740
|
+
const announce = React11.useCallback((message) => {
|
|
4522
4741
|
setAnnouncement("");
|
|
4523
4742
|
scheduleAnimationFrame(() => {
|
|
4524
4743
|
if (message) setAnnouncement(message);
|
|
4525
4744
|
}, "announcement");
|
|
4526
4745
|
}, [scheduleAnimationFrame]);
|
|
4527
|
-
const invoke =
|
|
4746
|
+
const invoke = React11.useCallback(async (endpoint, payload = {}, signal) => {
|
|
4528
4747
|
return unwrapRpcResult3(await rpcCall(endpoint, payload, signal));
|
|
4529
4748
|
}, [rpcCall]);
|
|
4530
|
-
const mergeSnapshot =
|
|
4749
|
+
const mergeSnapshot = React11.useCallback((snapshot, { restoreProvisioning = false } = {}) => {
|
|
4531
4750
|
const now2 = Date.now();
|
|
4532
4751
|
setModel((current) => mergeFeishuSnapshotState(
|
|
4533
4752
|
current,
|
|
@@ -4535,7 +4754,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4535
4754
|
{ restoreProvisioning, now: now2 }
|
|
4536
4755
|
));
|
|
4537
4756
|
}, []);
|
|
4538
|
-
const loadStatus =
|
|
4757
|
+
const loadStatus = React11.useCallback(async ({ signal, silent = false, restoreProvisioning = false } = {}) => {
|
|
4539
4758
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
4540
4759
|
if (workspaceVersion === null || !mountedRef.current) return void 0;
|
|
4541
4760
|
if (!silent) setPageBusy(true);
|
|
@@ -4553,12 +4772,12 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4553
4772
|
if (!silent && !signal?.aborted && mountedRef.current) setPageBusy(false);
|
|
4554
4773
|
}
|
|
4555
4774
|
}, [invoke, mergeSnapshot, workspaceFence]);
|
|
4556
|
-
|
|
4775
|
+
React11.useEffect(() => {
|
|
4557
4776
|
const controller = new AbortController();
|
|
4558
4777
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
4559
4778
|
return () => controller.abort();
|
|
4560
4779
|
}, [loadStatus]);
|
|
4561
|
-
|
|
4780
|
+
React11.useEffect(() => {
|
|
4562
4781
|
if (model.phase !== "ready") return void 0;
|
|
4563
4782
|
const controller = new AbortController();
|
|
4564
4783
|
let inFlight = false;
|
|
@@ -4577,7 +4796,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4577
4796
|
window.clearInterval(timer);
|
|
4578
4797
|
};
|
|
4579
4798
|
}, [loadStatus, model.phase]);
|
|
4580
|
-
|
|
4799
|
+
React11.useEffect(() => {
|
|
4581
4800
|
if (!focusBotId) return;
|
|
4582
4801
|
const node = cardRefs.current.get(focusBotId);
|
|
4583
4802
|
if (!node) return;
|
|
@@ -4585,7 +4804,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4585
4804
|
node.focus({ preventScroll: true });
|
|
4586
4805
|
setFocusBotId(null);
|
|
4587
4806
|
}, [focusBotId, model.bots]);
|
|
4588
|
-
const startProvisioning =
|
|
4807
|
+
const startProvisioning = React11.useCallback(async ({
|
|
4589
4808
|
replace = false,
|
|
4590
4809
|
operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
|
|
4591
4810
|
bot
|
|
@@ -4658,7 +4877,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4658
4877
|
model.provisioning?.botId,
|
|
4659
4878
|
model.provisioning?.botName
|
|
4660
4879
|
]);
|
|
4661
|
-
const bindCredentials =
|
|
4880
|
+
const bindCredentials = React11.useCallback(async ({ identity, secret }) => {
|
|
4662
4881
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4663
4882
|
setCredentialBusy(true);
|
|
4664
4883
|
setCredentialError(null);
|
|
@@ -4680,7 +4899,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4680
4899
|
setCredentialBusy(false);
|
|
4681
4900
|
}
|
|
4682
4901
|
}, [announce, invoke, loadStatus, mergeSnapshot, workspaceFence]);
|
|
4683
|
-
const cancelProvisioning =
|
|
4902
|
+
const cancelProvisioning = React11.useCallback(async () => {
|
|
4684
4903
|
const activeProvision = model.provisioning;
|
|
4685
4904
|
const attemptId = activeProvision?.attemptId;
|
|
4686
4905
|
const repairing = isCallbackRepair(activeProvision);
|
|
@@ -4743,7 +4962,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4743
4962
|
const countdownPhase = model.provisioning?.phase;
|
|
4744
4963
|
const countdownExpiresAt = model.provisioning?.expiresAt;
|
|
4745
4964
|
const countdownExpired = model.provisioning?.expired;
|
|
4746
|
-
|
|
4965
|
+
React11.useEffect(() => {
|
|
4747
4966
|
if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
|
|
4748
4967
|
const tick = () => {
|
|
4749
4968
|
const timestamp7 = Date.now();
|
|
@@ -4756,7 +4975,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4756
4975
|
const timer = window.setInterval(tick, 1e3);
|
|
4757
4976
|
return () => window.clearInterval(timer);
|
|
4758
4977
|
}, [countdownAttemptId, countdownPhase, countdownExpiresAt, countdownExpired]);
|
|
4759
|
-
|
|
4978
|
+
React11.useEffect(() => {
|
|
4760
4979
|
const provision2 = model.provisioning;
|
|
4761
4980
|
if (!provision2 || !["qr", "connecting"].includes(provision2.phase) || !provision2.attemptId || provision2.expired) return void 0;
|
|
4762
4981
|
const controller = new AbortController();
|
|
@@ -4824,7 +5043,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4824
5043
|
window.clearTimeout(timer);
|
|
4825
5044
|
};
|
|
4826
5045
|
}, [announce, invoke, loadStatus, model.provisioning]);
|
|
4827
|
-
const setBotBusy =
|
|
5046
|
+
const setBotBusy = React11.useCallback((botId, value) => {
|
|
4828
5047
|
setBusyByBot((current) => {
|
|
4829
5048
|
const next = { ...current };
|
|
4830
5049
|
if (value) next[botId] = value;
|
|
@@ -4832,7 +5051,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4832
5051
|
return next;
|
|
4833
5052
|
});
|
|
4834
5053
|
}, []);
|
|
4835
|
-
const setBotError =
|
|
5054
|
+
const setBotError = React11.useCallback((botId, error) => {
|
|
4836
5055
|
setErrorsByBot((current) => {
|
|
4837
5056
|
const next = { ...current };
|
|
4838
5057
|
if (error) next[botId] = presentError3(error);
|
|
@@ -4840,7 +5059,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4840
5059
|
return next;
|
|
4841
5060
|
});
|
|
4842
5061
|
}, []);
|
|
4843
|
-
const repairCallback =
|
|
5062
|
+
const repairCallback = React11.useCallback((connection) => {
|
|
4844
5063
|
if (model.provisioning) return;
|
|
4845
5064
|
setRemoveTargetId(null);
|
|
4846
5065
|
setBotError(connection.botId, null);
|
|
@@ -4854,7 +5073,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4854
5073
|
bot: connection
|
|
4855
5074
|
});
|
|
4856
5075
|
}, [model.provisioning, setBotError, startProvisioning]);
|
|
4857
|
-
const reconnectOneBot =
|
|
5076
|
+
const reconnectOneBot = React11.useCallback(async (connection) => {
|
|
4858
5077
|
const { botId, bot } = connection;
|
|
4859
5078
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4860
5079
|
setBotBusy(botId, "reconnect");
|
|
@@ -4894,7 +5113,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4894
5113
|
setBotBusy(botId, null);
|
|
4895
5114
|
}
|
|
4896
5115
|
}, [announce, invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
4897
|
-
const saveWorkspace =
|
|
5116
|
+
const saveWorkspace = React11.useCallback(async (connection, workspace) => {
|
|
4898
5117
|
const { botId } = connection;
|
|
4899
5118
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
4900
5119
|
setBotBusy(botId, "workspace");
|
|
@@ -4913,15 +5132,34 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
4913
5132
|
if (mountedRef.current) setBotBusy(botId, null);
|
|
4914
5133
|
}
|
|
4915
5134
|
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
4916
|
-
const
|
|
5135
|
+
const saveAgentPreset = React11.useCallback(async (connection, agentPreset) => {
|
|
5136
|
+
const { botId } = connection;
|
|
5137
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
5138
|
+
setBotBusy(botId, "preset");
|
|
5139
|
+
setBotError(botId, null);
|
|
5140
|
+
try {
|
|
5141
|
+
const snapshot = normalizeBotsSnapshot(await invoke(
|
|
5142
|
+
FEISHU_ENDPOINTS.setAgentPreset,
|
|
5143
|
+
{ botId, agentPreset }
|
|
5144
|
+
));
|
|
5145
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5146
|
+
mergeSnapshot(snapshot);
|
|
5147
|
+
}
|
|
5148
|
+
} finally {
|
|
5149
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
5150
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
5151
|
+
if (mountedRef.current) setBotBusy(botId, null);
|
|
5152
|
+
}
|
|
5153
|
+
}, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
|
|
5154
|
+
const requestRemove = React11.useCallback((connection) => {
|
|
4917
5155
|
setRemoveTargetId(connection.botId);
|
|
4918
5156
|
}, []);
|
|
4919
|
-
const cancelRemove =
|
|
5157
|
+
const cancelRemove = React11.useCallback(() => {
|
|
4920
5158
|
const botId = removeTargetId;
|
|
4921
5159
|
setRemoveTargetId(null);
|
|
4922
5160
|
scheduleAnimationFrame(() => removeButtonRefs.current.get(botId)?.focus(), "focus");
|
|
4923
5161
|
}, [removeTargetId, scheduleAnimationFrame]);
|
|
4924
|
-
const confirmRemove =
|
|
5162
|
+
const confirmRemove = React11.useCallback(async (connection) => {
|
|
4925
5163
|
const { botId, bot } = connection;
|
|
4926
5164
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
4927
5165
|
setBotBusy(botId, "delete");
|
|
@@ -5006,15 +5244,17 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5006
5244
|
setCredentialError(null);
|
|
5007
5245
|
}
|
|
5008
5246
|
}) : null;
|
|
5009
|
-
const setCardRef =
|
|
5247
|
+
const setCardRef = React11.useCallback((botId, node) => {
|
|
5010
5248
|
if (node) cardRefs.current.set(botId, node);
|
|
5011
5249
|
else cardRefs.current.delete(botId);
|
|
5012
5250
|
}, []);
|
|
5013
|
-
const setRemoveButtonRef =
|
|
5251
|
+
const setRemoveButtonRef = React11.useCallback((botId, node) => {
|
|
5014
5252
|
if (node) removeButtonRefs.current.set(botId, node);
|
|
5015
5253
|
else removeButtonRefs.current.delete(botId);
|
|
5016
5254
|
}, []);
|
|
5017
|
-
return h2(
|
|
5255
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
5256
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
5257
|
+
}, h2(
|
|
5018
5258
|
"section",
|
|
5019
5259
|
{ className: "bxf-page dim-channelPage", "aria-label": "\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E" },
|
|
5020
5260
|
h2(Heading2, {
|
|
@@ -5047,7 +5287,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5047
5287
|
onRetry: () => void loadStatus(),
|
|
5048
5288
|
busy: pageBusy
|
|
5049
5289
|
}) : h2(
|
|
5050
|
-
|
|
5290
|
+
React11.Fragment,
|
|
5051
5291
|
null,
|
|
5052
5292
|
credentialContent,
|
|
5053
5293
|
provisionContent,
|
|
@@ -5062,6 +5302,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5062
5302
|
onReconnect: (bot) => void reconnectOneBot(bot),
|
|
5063
5303
|
onRepairCallback: repairCallback,
|
|
5064
5304
|
onWorkspaceSave: saveWorkspace,
|
|
5305
|
+
onAgentPresetSave: saveAgentPreset,
|
|
5065
5306
|
onRequestRemove: requestRemove,
|
|
5066
5307
|
onConfirmRemove: (bot) => void confirmRemove(bot),
|
|
5067
5308
|
onCancelRemove: cancelRemove,
|
|
@@ -5069,7 +5310,7 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
5069
5310
|
setRemoveButtonRef
|
|
5070
5311
|
}) : null
|
|
5071
5312
|
)
|
|
5072
|
-
);
|
|
5313
|
+
));
|
|
5073
5314
|
}
|
|
5074
5315
|
|
|
5075
5316
|
// plugin-src/client/channels/qq/api.js
|
|
@@ -5082,7 +5323,8 @@ var QQ_ENDPOINTS = Object.freeze({
|
|
|
5082
5323
|
bindCredentials: "bot.bind-credentials",
|
|
5083
5324
|
reconnectBot: "bot.reconnect",
|
|
5084
5325
|
deleteBot: "bot.delete",
|
|
5085
|
-
setWorkspace: "bot.workspace.set"
|
|
5326
|
+
setWorkspace: "bot.workspace.set",
|
|
5327
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
5086
5328
|
});
|
|
5087
5329
|
var PROVISION_STATES2 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
|
|
5088
5330
|
var ACCOUNT_STATES3 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -5146,6 +5388,7 @@ function normalizeBot3(value) {
|
|
|
5146
5388
|
connected,
|
|
5147
5389
|
state: connected ? "connected" : state,
|
|
5148
5390
|
workspace: text2(value.workspace, "", 4096),
|
|
5391
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
5149
5392
|
bot: {
|
|
5150
5393
|
name: text2(value.bot?.name, "QQ\u673A\u5668\u4EBA", 100),
|
|
5151
5394
|
appIdMasked: text2(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
|
|
@@ -5179,6 +5422,7 @@ function normalizeSnapshot3(value) {
|
|
|
5179
5422
|
bots,
|
|
5180
5423
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
5181
5424
|
provisioning: source.provisioning ? normalizeProvisioning3(source.provisioning) : null,
|
|
5425
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
|
5182
5426
|
...testMessage ? { testMessage } : {}
|
|
5183
5427
|
};
|
|
5184
5428
|
}
|
|
@@ -5201,7 +5445,7 @@ function formatRemaining3(milliseconds) {
|
|
|
5201
5445
|
}
|
|
5202
5446
|
|
|
5203
5447
|
// plugin-src/client/channels/qq/index.js
|
|
5204
|
-
var
|
|
5448
|
+
var React12 = __toESM(require("react"), 1);
|
|
5205
5449
|
|
|
5206
5450
|
// plugin-src/client/channels/qq/styles.js
|
|
5207
5451
|
var QQ_STYLE_ID = "xmanrui-dsh-im-qq-settings";
|
|
@@ -5226,7 +5470,7 @@ function installQqStyles() {
|
|
|
5226
5470
|
|
|
5227
5471
|
// plugin-src/client/channels/qq/index.js
|
|
5228
5472
|
var ACTIVE_STATES = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
|
|
5229
|
-
var Button7 =
|
|
5473
|
+
var Button7 = React12.forwardRef(function Button8({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
5230
5474
|
return h2("button", {
|
|
5231
5475
|
...props,
|
|
5232
5476
|
ref,
|
|
@@ -5440,6 +5684,7 @@ function AccountCard2({
|
|
|
5440
5684
|
removing,
|
|
5441
5685
|
onReconnect,
|
|
5442
5686
|
onWorkspaceSave,
|
|
5687
|
+
onAgentPresetSave,
|
|
5443
5688
|
onRequestRemove,
|
|
5444
5689
|
onConfirmRemove,
|
|
5445
5690
|
onCancelRemove
|
|
@@ -5485,6 +5730,11 @@ function AccountCard2({
|
|
|
5485
5730
|
disabled: Boolean(busy),
|
|
5486
5731
|
onSave: onWorkspaceSave
|
|
5487
5732
|
}),
|
|
5733
|
+
h2(AgentPresetEditor, {
|
|
5734
|
+
agentPreset: account.agentPreset,
|
|
5735
|
+
disabled: Boolean(busy),
|
|
5736
|
+
onSave: onAgentPresetSave
|
|
5737
|
+
}),
|
|
5488
5738
|
h2(
|
|
5489
5739
|
"div",
|
|
5490
5740
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -5511,19 +5761,25 @@ function AccountCard2({
|
|
|
5511
5761
|
);
|
|
5512
5762
|
}
|
|
5513
5763
|
function QqSettingsTab({ rpcCall }) {
|
|
5514
|
-
const [model, setModel] =
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
const [
|
|
5522
|
-
const [
|
|
5523
|
-
const
|
|
5764
|
+
const [model, setModel] = React12.useState({
|
|
5765
|
+
phase: "loading",
|
|
5766
|
+
bots: [],
|
|
5767
|
+
totals: { configured: 0, connected: 0 },
|
|
5768
|
+
error: null,
|
|
5769
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
5770
|
+
});
|
|
5771
|
+
const [provision, setProvision] = React12.useState(null);
|
|
5772
|
+
const [busy, setBusy] = React12.useState(false);
|
|
5773
|
+
const [busyByBot, setBusyByBot] = React12.useState({});
|
|
5774
|
+
const [feedbackByBot, setFeedbackByBot] = React12.useState({});
|
|
5775
|
+
const [removeTarget, setRemoveTarget] = React12.useState(null);
|
|
5776
|
+
const [credentialOpen, setCredentialOpen] = React12.useState(false);
|
|
5777
|
+
const [credentialError, setCredentialError] = React12.useState(null);
|
|
5778
|
+
const [now, setNow] = React12.useState(Date.now());
|
|
5779
|
+
const mounted = React12.useRef(true);
|
|
5524
5780
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
5525
|
-
const addButtonRef =
|
|
5526
|
-
|
|
5781
|
+
const addButtonRef = React12.useRef(null);
|
|
5782
|
+
React12.useEffect(() => {
|
|
5527
5783
|
const disposeDingtalk = installDingtalkStyles();
|
|
5528
5784
|
const disposeQq = installQqStyles();
|
|
5529
5785
|
mounted.current = true;
|
|
@@ -5533,18 +5789,24 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5533
5789
|
disposeDingtalk();
|
|
5534
5790
|
};
|
|
5535
5791
|
}, []);
|
|
5536
|
-
const invoke =
|
|
5792
|
+
const invoke = React12.useCallback(async (endpoint, payload = {}, signal) => {
|
|
5537
5793
|
if (typeof rpcCall !== "function") throw new TypeError("QQ \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
5538
5794
|
return unwrapRpcResult4(await rpcCall(endpoint, payload, signal));
|
|
5539
5795
|
}, [rpcCall]);
|
|
5540
|
-
const loadStatus =
|
|
5796
|
+
const loadStatus = React12.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
5541
5797
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
5542
5798
|
if (workspaceVersion === null) return void 0;
|
|
5543
5799
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
5544
5800
|
try {
|
|
5545
5801
|
const snapshot = normalizeSnapshot3(await invoke(QQ_ENDPOINTS.status, {}, signal));
|
|
5546
5802
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
5547
|
-
setModel({
|
|
5803
|
+
setModel({
|
|
5804
|
+
phase: "ready",
|
|
5805
|
+
bots: snapshot.bots,
|
|
5806
|
+
totals: snapshot.totals,
|
|
5807
|
+
error: null,
|
|
5808
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
5809
|
+
});
|
|
5548
5810
|
if (restore && snapshot.provisioning) setProvision({
|
|
5549
5811
|
...snapshot.provisioning,
|
|
5550
5812
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -5557,12 +5819,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5557
5819
|
return void 0;
|
|
5558
5820
|
}
|
|
5559
5821
|
}, [invoke, workspaceFence]);
|
|
5560
|
-
|
|
5822
|
+
React12.useEffect(() => {
|
|
5561
5823
|
const controller = new AbortController();
|
|
5562
5824
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
5563
5825
|
return () => controller.abort();
|
|
5564
5826
|
}, [loadStatus]);
|
|
5565
|
-
|
|
5827
|
+
React12.useEffect(() => {
|
|
5566
5828
|
if (model.phase !== "ready") return void 0;
|
|
5567
5829
|
const controller = new AbortController();
|
|
5568
5830
|
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
@@ -5571,12 +5833,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5571
5833
|
window.clearInterval(timer);
|
|
5572
5834
|
};
|
|
5573
5835
|
}, [loadStatus, model.phase]);
|
|
5574
|
-
|
|
5836
|
+
React12.useEffect(() => {
|
|
5575
5837
|
if (!provision || !ACTIVE_STATES.has(provision.status)) return void 0;
|
|
5576
5838
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
5577
5839
|
return () => window.clearInterval(timer);
|
|
5578
5840
|
}, [provision?.attemptId, provision?.status]);
|
|
5579
|
-
const startProvisioning =
|
|
5841
|
+
const startProvisioning = React12.useCallback(async (replace = false) => {
|
|
5580
5842
|
setCredentialOpen(false);
|
|
5581
5843
|
setCredentialError(null);
|
|
5582
5844
|
setBusy(true);
|
|
@@ -5594,7 +5856,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5594
5856
|
if (mounted.current) setBusy(false);
|
|
5595
5857
|
}
|
|
5596
5858
|
}, [invoke, provision?.attemptId]);
|
|
5597
|
-
const bindCredentials =
|
|
5859
|
+
const bindCredentials = React12.useCallback(async ({ identity, secret }) => {
|
|
5598
5860
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
5599
5861
|
setBusy(true);
|
|
5600
5862
|
setCredentialError(null);
|
|
@@ -5605,7 +5867,13 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5605
5867
|
));
|
|
5606
5868
|
if (!mounted.current) return;
|
|
5607
5869
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5608
|
-
setModel({
|
|
5870
|
+
setModel({
|
|
5871
|
+
phase: "ready",
|
|
5872
|
+
bots: snapshot.bots,
|
|
5873
|
+
totals: snapshot.totals,
|
|
5874
|
+
error: null,
|
|
5875
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
5876
|
+
});
|
|
5609
5877
|
}
|
|
5610
5878
|
setCredentialOpen(false);
|
|
5611
5879
|
} catch (error) {
|
|
@@ -5616,7 +5884,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5616
5884
|
if (mounted.current) setBusy(false);
|
|
5617
5885
|
}
|
|
5618
5886
|
}, [invoke, loadStatus, workspaceFence]);
|
|
5619
|
-
const closeProvision =
|
|
5887
|
+
const closeProvision = React12.useCallback(async () => {
|
|
5620
5888
|
setBusy(true);
|
|
5621
5889
|
try {
|
|
5622
5890
|
if (provision?.attemptId && ACTIVE_STATES.has(provision.status)) {
|
|
@@ -5627,7 +5895,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5627
5895
|
if (mounted.current) setBusy(false);
|
|
5628
5896
|
}
|
|
5629
5897
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
5630
|
-
|
|
5898
|
+
React12.useEffect(() => {
|
|
5631
5899
|
const attemptId = provision?.attemptId;
|
|
5632
5900
|
if (!attemptId || !ACTIVE_STATES.has(provision.status)) return void 0;
|
|
5633
5901
|
const controller = new AbortController();
|
|
@@ -5657,13 +5925,19 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5657
5925
|
window.clearTimeout(timer);
|
|
5658
5926
|
};
|
|
5659
5927
|
}, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
5660
|
-
const botAction =
|
|
5928
|
+
const botAction = React12.useCallback(async (account, operation, endpoint, payload) => {
|
|
5661
5929
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
5662
5930
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
5663
5931
|
try {
|
|
5664
5932
|
const snapshot = normalizeSnapshot3(await invoke(endpoint, payload));
|
|
5665
5933
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
5666
|
-
setModel({
|
|
5934
|
+
setModel({
|
|
5935
|
+
phase: "ready",
|
|
5936
|
+
bots: snapshot.bots,
|
|
5937
|
+
totals: snapshot.totals,
|
|
5938
|
+
error: null,
|
|
5939
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
5940
|
+
});
|
|
5667
5941
|
}
|
|
5668
5942
|
return snapshot;
|
|
5669
5943
|
} finally {
|
|
@@ -5676,7 +5950,7 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5676
5950
|
});
|
|
5677
5951
|
}
|
|
5678
5952
|
}, [invoke, loadStatus, workspaceFence]);
|
|
5679
|
-
const reconnect =
|
|
5953
|
+
const reconnect = React12.useCallback(async (account) => {
|
|
5680
5954
|
setFeedbackByBot((current) => {
|
|
5681
5955
|
const next = { ...current };
|
|
5682
5956
|
delete next[account.botId];
|
|
@@ -5739,6 +6013,12 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5739
6013
|
QQ_ENDPOINTS.setWorkspace,
|
|
5740
6014
|
{ botId: account.botId, workspace }
|
|
5741
6015
|
),
|
|
6016
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
6017
|
+
account,
|
|
6018
|
+
"preset",
|
|
6019
|
+
QQ_ENDPOINTS.setAgentPreset,
|
|
6020
|
+
{ botId: account.botId, agentPreset }
|
|
6021
|
+
),
|
|
5742
6022
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
5743
6023
|
onCancelRemove: () => setRemoveTarget(null),
|
|
5744
6024
|
onConfirmRemove: async () => {
|
|
@@ -5761,7 +6041,9 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5761
6041
|
setCredentialError(null);
|
|
5762
6042
|
}
|
|
5763
6043
|
}) : null;
|
|
5764
|
-
return h2(
|
|
6044
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
6045
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
6046
|
+
}, h2(
|
|
5765
6047
|
"section",
|
|
5766
6048
|
{ className: "ddt-page dqq-page dim-channelPage", "aria-label": "QQ \u8BBE\u7F6E" },
|
|
5767
6049
|
h2(Heading3, {
|
|
@@ -5777,14 +6059,14 @@ function QqSettingsTab({ rpcCall }) {
|
|
|
5777
6059
|
addButtonRef
|
|
5778
6060
|
}),
|
|
5779
6061
|
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(
|
|
5780
|
-
|
|
6062
|
+
React12.Fragment,
|
|
5781
6063
|
null,
|
|
5782
6064
|
credentialView,
|
|
5783
6065
|
provisionView,
|
|
5784
6066
|
model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView3, { busy, onStart: () => void startProvisioning() }) : null,
|
|
5785
6067
|
botList
|
|
5786
6068
|
)
|
|
5787
|
-
);
|
|
6069
|
+
));
|
|
5788
6070
|
}
|
|
5789
6071
|
|
|
5790
6072
|
// src/channels/office/protocol.mjs
|
|
@@ -5866,7 +6148,7 @@ function normalizeOfficeStatus(value) {
|
|
|
5866
6148
|
}
|
|
5867
6149
|
|
|
5868
6150
|
// plugin-src/client/channels/office/index.js
|
|
5869
|
-
var
|
|
6151
|
+
var React13 = __toESM(require("react"), 1);
|
|
5870
6152
|
function Button9({ children, kind = "secondary", ...props }) {
|
|
5871
6153
|
return h2("button", { ...props, type: "button", className: "ddt-button", "data-kind": kind }, children);
|
|
5872
6154
|
}
|
|
@@ -5895,12 +6177,12 @@ function stateLabel(model) {
|
|
|
5895
6177
|
return "\u5DF2\u914D\u7F6E";
|
|
5896
6178
|
}
|
|
5897
6179
|
function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
5898
|
-
const [model, setModel] =
|
|
5899
|
-
const [phase, setPhase] =
|
|
5900
|
-
const [busy, setBusy] =
|
|
5901
|
-
const [error, setError] =
|
|
5902
|
-
const [notice, setNotice] =
|
|
5903
|
-
const [form, setForm] =
|
|
6180
|
+
const [model, setModel] = React13.useState(normalizeOfficeStatus(initialStatus));
|
|
6181
|
+
const [phase, setPhase] = React13.useState(initialStatus === void 0 ? "loading" : "ready");
|
|
6182
|
+
const [busy, setBusy] = React13.useState("");
|
|
6183
|
+
const [error, setError] = React13.useState("");
|
|
6184
|
+
const [notice, setNotice] = React13.useState("");
|
|
6185
|
+
const [form, setForm] = React13.useState({
|
|
5904
6186
|
baseUrl: "",
|
|
5905
6187
|
deviceId: "local-harness",
|
|
5906
6188
|
deviceToken: "",
|
|
@@ -5909,11 +6191,11 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5909
6191
|
workspaces: "",
|
|
5910
6192
|
instructionPresets: ""
|
|
5911
6193
|
});
|
|
5912
|
-
const invoke =
|
|
6194
|
+
const invoke = React13.useCallback(async (endpoint, payload = {}) => {
|
|
5913
6195
|
if (typeof rpcCall !== "function") throw new Error("AI Office \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
5914
6196
|
return unwrapOfficeRpc(await rpcCall(endpoint, payload));
|
|
5915
6197
|
}, [rpcCall]);
|
|
5916
|
-
const adopt =
|
|
6198
|
+
const adopt = React13.useCallback((value) => {
|
|
5917
6199
|
const next = normalizeOfficeStatus(value?.snapshot ?? value);
|
|
5918
6200
|
setModel(next);
|
|
5919
6201
|
if (next.config) setForm((current) => ({
|
|
@@ -5928,7 +6210,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5928
6210
|
}));
|
|
5929
6211
|
return next;
|
|
5930
6212
|
}, []);
|
|
5931
|
-
const load =
|
|
6213
|
+
const load = React13.useCallback(async () => {
|
|
5932
6214
|
try {
|
|
5933
6215
|
adopt(await invoke(OFFICE_RPC_ENDPOINTS.status));
|
|
5934
6216
|
setPhase("ready");
|
|
@@ -5938,7 +6220,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5938
6220
|
setError(caught.message);
|
|
5939
6221
|
}
|
|
5940
6222
|
}, [adopt, invoke]);
|
|
5941
|
-
|
|
6223
|
+
React13.useEffect(() => {
|
|
5942
6224
|
void load();
|
|
5943
6225
|
}, [load]);
|
|
5944
6226
|
const run = async (name2, operation) => {
|
|
@@ -5955,7 +6237,7 @@ function OfficeSettingsTab({ rpcCall, initialStatus }) {
|
|
|
5955
6237
|
setBusy("");
|
|
5956
6238
|
}
|
|
5957
6239
|
};
|
|
5958
|
-
const hooks =
|
|
6240
|
+
const hooks = React13.useMemo(() => {
|
|
5959
6241
|
try {
|
|
5960
6242
|
return officeHookUrls(form.baseUrl);
|
|
5961
6243
|
} catch {
|
|
@@ -6140,7 +6422,7 @@ var normalizeSnapshot4 = api2.normalizeSnapshot;
|
|
|
6140
6422
|
var presentError5 = api2.presentError;
|
|
6141
6423
|
|
|
6142
6424
|
// plugin-src/client/channels/slack/index.js
|
|
6143
|
-
var
|
|
6425
|
+
var React14 = __toESM(require("react"), 1);
|
|
6144
6426
|
|
|
6145
6427
|
// src/channels/slack/manifest.mjs
|
|
6146
6428
|
var SLACK_APP_MANIFEST_YAML = `_metadata:
|
|
@@ -6213,10 +6495,10 @@ function installSlackStyles() {
|
|
|
6213
6495
|
|
|
6214
6496
|
// plugin-src/client/channels/slack/index.js
|
|
6215
6497
|
function SlackCredentialPanel({ busy, error, onSubmit, onCancel }) {
|
|
6216
|
-
const [botToken, setBotToken] =
|
|
6217
|
-
const [appToken, setAppToken] =
|
|
6218
|
-
const [copied, setCopied] =
|
|
6219
|
-
const headingId =
|
|
6498
|
+
const [botToken, setBotToken] = React14.useState("");
|
|
6499
|
+
const [appToken, setAppToken] = React14.useState("");
|
|
6500
|
+
const [copied, setCopied] = React14.useState(false);
|
|
6501
|
+
const headingId = React14.useId();
|
|
6220
6502
|
const copyManifest = async () => {
|
|
6221
6503
|
try {
|
|
6222
6504
|
await navigator.clipboard.writeText(SLACK_APP_MANIFEST_YAML);
|
|
@@ -6372,7 +6654,7 @@ var normalizeSnapshot5 = api3.normalizeSnapshot;
|
|
|
6372
6654
|
var presentError6 = api3.presentError;
|
|
6373
6655
|
|
|
6374
6656
|
// plugin-src/client/channels/telegram/index.js
|
|
6375
|
-
var
|
|
6657
|
+
var React15 = __toESM(require("react"), 1);
|
|
6376
6658
|
|
|
6377
6659
|
// plugin-src/client/channels/telegram/styles.js
|
|
6378
6660
|
var TELEGRAM_STYLE_ID = "xmanrui-dsh-im-telegram-settings";
|
|
@@ -6438,11 +6720,11 @@ function allowedUsersFromText(value) {
|
|
|
6438
6720
|
function TelegramAccessSettings({ account, busy = false, onSave }) {
|
|
6439
6721
|
const policy = policyFor(account);
|
|
6440
6722
|
const sourceUsers = policy.allowedUsers.join("\n");
|
|
6441
|
-
const accessHelpId =
|
|
6442
|
-
const [accessMode, setAccessMode] =
|
|
6443
|
-
const [allowedUsers, setAllowedUsers] =
|
|
6444
|
-
const [error, setError] =
|
|
6445
|
-
|
|
6723
|
+
const accessHelpId = React15.useId();
|
|
6724
|
+
const [accessMode, setAccessMode] = React15.useState(policy.accessMode);
|
|
6725
|
+
const [allowedUsers, setAllowedUsers] = React15.useState(sourceUsers);
|
|
6726
|
+
const [error, setError] = React15.useState(null);
|
|
6727
|
+
React15.useEffect(() => {
|
|
6446
6728
|
setAccessMode(policy.accessMode);
|
|
6447
6729
|
setAllowedUsers(sourceUsers);
|
|
6448
6730
|
setError(null);
|
|
@@ -6591,7 +6873,8 @@ var WECOM_ENDPOINTS = Object.freeze({
|
|
|
6591
6873
|
bindCredentials: "bot.bind-credentials",
|
|
6592
6874
|
reconnectBot: "bot.reconnect",
|
|
6593
6875
|
deleteBot: "bot.delete",
|
|
6594
|
-
setWorkspace: "bot.workspace.set"
|
|
6876
|
+
setWorkspace: "bot.workspace.set",
|
|
6877
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
6595
6878
|
});
|
|
6596
6879
|
var PROVISION_STATES3 = /* @__PURE__ */ new Set(["starting", "pending", "refreshing", "connecting", "connected", "failed", "cancelled"]);
|
|
6597
6880
|
var ACCOUNT_STATES4 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -6661,6 +6944,7 @@ function normalizeBot4(value) {
|
|
|
6661
6944
|
connected,
|
|
6662
6945
|
state: connected ? "connected" : state,
|
|
6663
6946
|
workspace: text3(value.workspace, "", 4096),
|
|
6947
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
6664
6948
|
bot: {
|
|
6665
6949
|
name: text3(value.bot?.name, "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA", 100),
|
|
6666
6950
|
appIdMasked: text3(value.bot?.appIdMasked, "\u5E94\u7528\u6807\u8BC6\u5DF2\u5B89\u5168\u4FDD\u5B58", 140)
|
|
@@ -6684,7 +6968,8 @@ function normalizeSnapshot6(value) {
|
|
|
6684
6968
|
bots,
|
|
6685
6969
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
6686
6970
|
provisioning: source.provisioning ? normalizeProvisioning4(source.provisioning) : null,
|
|
6687
|
-
testMessage: normalizeTestMessage3(source.testMessage)
|
|
6971
|
+
testMessage: normalizeTestMessage3(source.testMessage),
|
|
6972
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
6688
6973
|
};
|
|
6689
6974
|
}
|
|
6690
6975
|
function presentError7(error) {
|
|
@@ -6699,7 +6984,7 @@ function formatRemaining4(milliseconds) {
|
|
|
6699
6984
|
}
|
|
6700
6985
|
|
|
6701
6986
|
// plugin-src/client/channels/wecom/index.js
|
|
6702
|
-
var
|
|
6987
|
+
var React16 = __toESM(require("react"), 1);
|
|
6703
6988
|
|
|
6704
6989
|
// plugin-src/client/channels/wecom/styles.js
|
|
6705
6990
|
var WECOM_STYLE_ID = "xmanrui-dsh-im-wecom-settings";
|
|
@@ -6724,7 +7009,7 @@ function installWecomStyles() {
|
|
|
6724
7009
|
|
|
6725
7010
|
// plugin-src/client/channels/wecom/index.js
|
|
6726
7011
|
var ACTIVE_STATES2 = /* @__PURE__ */ new Set(["pending", "refreshing", "connecting"]);
|
|
6727
|
-
var Button10 =
|
|
7012
|
+
var Button10 = React16.forwardRef(function Button11({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
6728
7013
|
return h2("button", {
|
|
6729
7014
|
...props,
|
|
6730
7015
|
ref,
|
|
@@ -6938,6 +7223,7 @@ function AccountCard3({
|
|
|
6938
7223
|
removing,
|
|
6939
7224
|
onReconnect,
|
|
6940
7225
|
onWorkspaceSave,
|
|
7226
|
+
onAgentPresetSave,
|
|
6941
7227
|
onRequestRemove,
|
|
6942
7228
|
onConfirmRemove,
|
|
6943
7229
|
onCancelRemove
|
|
@@ -6983,6 +7269,11 @@ function AccountCard3({
|
|
|
6983
7269
|
disabled: Boolean(busy),
|
|
6984
7270
|
onSave: onWorkspaceSave
|
|
6985
7271
|
}),
|
|
7272
|
+
h2(AgentPresetEditor, {
|
|
7273
|
+
agentPreset: account.agentPreset,
|
|
7274
|
+
disabled: Boolean(busy),
|
|
7275
|
+
onSave: onAgentPresetSave
|
|
7276
|
+
}),
|
|
6986
7277
|
h2(
|
|
6987
7278
|
"div",
|
|
6988
7279
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -7009,21 +7300,27 @@ function AccountCard3({
|
|
|
7009
7300
|
);
|
|
7010
7301
|
}
|
|
7011
7302
|
function WecomSettingsTab({ rpcCall }) {
|
|
7012
|
-
const [model, setModel] =
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
const [
|
|
7020
|
-
const [
|
|
7021
|
-
const [
|
|
7022
|
-
const
|
|
7303
|
+
const [model, setModel] = React16.useState({
|
|
7304
|
+
phase: "loading",
|
|
7305
|
+
bots: [],
|
|
7306
|
+
totals: { configured: 0, connected: 0 },
|
|
7307
|
+
error: null,
|
|
7308
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
7309
|
+
});
|
|
7310
|
+
const [provision, setProvision] = React16.useState(null);
|
|
7311
|
+
const [busy, setBusy] = React16.useState(false);
|
|
7312
|
+
const [busyByBot, setBusyByBot] = React16.useState({});
|
|
7313
|
+
const [feedbackByBot, setFeedbackByBot] = React16.useState({});
|
|
7314
|
+
const [removeTarget, setRemoveTarget] = React16.useState(null);
|
|
7315
|
+
const [credentialOpen, setCredentialOpen] = React16.useState(false);
|
|
7316
|
+
const [credentialError, setCredentialError] = React16.useState(null);
|
|
7317
|
+
const [notice, setNotice] = React16.useState("");
|
|
7318
|
+
const [now, setNow] = React16.useState(Date.now());
|
|
7319
|
+
const mounted = React16.useRef(true);
|
|
7023
7320
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
7024
|
-
const addButtonRef =
|
|
7025
|
-
const noticeFrameRef =
|
|
7026
|
-
const announce =
|
|
7321
|
+
const addButtonRef = React16.useRef(null);
|
|
7322
|
+
const noticeFrameRef = React16.useRef(null);
|
|
7323
|
+
const announce = React16.useCallback((message) => {
|
|
7027
7324
|
if (!mounted.current) return;
|
|
7028
7325
|
if (noticeFrameRef.current !== null) {
|
|
7029
7326
|
window.cancelAnimationFrame(noticeFrameRef.current);
|
|
@@ -7037,7 +7334,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7037
7334
|
});
|
|
7038
7335
|
}
|
|
7039
7336
|
}, []);
|
|
7040
|
-
|
|
7337
|
+
React16.useEffect(() => {
|
|
7041
7338
|
const disposeDingtalk = installDingtalkStyles();
|
|
7042
7339
|
const disposeWecom = installWecomStyles();
|
|
7043
7340
|
mounted.current = true;
|
|
@@ -7051,18 +7348,24 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7051
7348
|
disposeDingtalk();
|
|
7052
7349
|
};
|
|
7053
7350
|
}, []);
|
|
7054
|
-
const invoke =
|
|
7351
|
+
const invoke = React16.useCallback(async (endpoint, payload = {}, signal) => {
|
|
7055
7352
|
if (typeof rpcCall !== "function") throw new TypeError("\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
7056
7353
|
return unwrapRpcResult7(await rpcCall(endpoint, payload, signal));
|
|
7057
7354
|
}, [rpcCall]);
|
|
7058
|
-
const loadStatus =
|
|
7355
|
+
const loadStatus = React16.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
7059
7356
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
7060
7357
|
if (workspaceVersion === null) return void 0;
|
|
7061
7358
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
7062
7359
|
try {
|
|
7063
7360
|
const snapshot = normalizeSnapshot6(await invoke(WECOM_ENDPOINTS.status, {}, signal));
|
|
7064
7361
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
7065
|
-
setModel({
|
|
7362
|
+
setModel({
|
|
7363
|
+
phase: "ready",
|
|
7364
|
+
bots: snapshot.bots,
|
|
7365
|
+
totals: snapshot.totals,
|
|
7366
|
+
error: null,
|
|
7367
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7368
|
+
});
|
|
7066
7369
|
if (restore && snapshot.provisioning) setProvision({
|
|
7067
7370
|
...snapshot.provisioning,
|
|
7068
7371
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -7075,12 +7378,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7075
7378
|
return void 0;
|
|
7076
7379
|
}
|
|
7077
7380
|
}, [invoke, workspaceFence]);
|
|
7078
|
-
|
|
7381
|
+
React16.useEffect(() => {
|
|
7079
7382
|
const controller = new AbortController();
|
|
7080
7383
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
7081
7384
|
return () => controller.abort();
|
|
7082
7385
|
}, [loadStatus]);
|
|
7083
|
-
|
|
7386
|
+
React16.useEffect(() => {
|
|
7084
7387
|
if (model.phase !== "ready") return void 0;
|
|
7085
7388
|
const controller = new AbortController();
|
|
7086
7389
|
const timer = window.setInterval(() => void loadStatus({ signal: controller.signal, silent: true }), 15e3);
|
|
@@ -7089,12 +7392,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7089
7392
|
window.clearInterval(timer);
|
|
7090
7393
|
};
|
|
7091
7394
|
}, [loadStatus, model.phase]);
|
|
7092
|
-
|
|
7395
|
+
React16.useEffect(() => {
|
|
7093
7396
|
if (!provision || !ACTIVE_STATES2.has(provision.status)) return void 0;
|
|
7094
7397
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
7095
7398
|
return () => window.clearInterval(timer);
|
|
7096
7399
|
}, [provision?.attemptId, provision?.status]);
|
|
7097
|
-
const startProvisioning =
|
|
7400
|
+
const startProvisioning = React16.useCallback(async (replace = false) => {
|
|
7098
7401
|
setCredentialOpen(false);
|
|
7099
7402
|
setCredentialError(null);
|
|
7100
7403
|
setBusy(true);
|
|
@@ -7112,7 +7415,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7112
7415
|
if (mounted.current) setBusy(false);
|
|
7113
7416
|
}
|
|
7114
7417
|
}, [invoke, provision?.attemptId]);
|
|
7115
|
-
const bindCredentials =
|
|
7418
|
+
const bindCredentials = React16.useCallback(async ({ identity, secret }) => {
|
|
7116
7419
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
7117
7420
|
setBusy(true);
|
|
7118
7421
|
setCredentialError(null);
|
|
@@ -7123,7 +7426,13 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7123
7426
|
));
|
|
7124
7427
|
if (!mounted.current) return;
|
|
7125
7428
|
if (workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
7126
|
-
setModel({
|
|
7429
|
+
setModel({
|
|
7430
|
+
phase: "ready",
|
|
7431
|
+
bots: snapshot.bots,
|
|
7432
|
+
totals: snapshot.totals,
|
|
7433
|
+
error: null,
|
|
7434
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7435
|
+
});
|
|
7127
7436
|
}
|
|
7128
7437
|
setCredentialOpen(false);
|
|
7129
7438
|
} catch (error) {
|
|
@@ -7134,7 +7443,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7134
7443
|
if (mounted.current) setBusy(false);
|
|
7135
7444
|
}
|
|
7136
7445
|
}, [invoke, loadStatus, workspaceFence]);
|
|
7137
|
-
const closeProvision =
|
|
7446
|
+
const closeProvision = React16.useCallback(async () => {
|
|
7138
7447
|
setBusy(true);
|
|
7139
7448
|
try {
|
|
7140
7449
|
if (provision?.attemptId && ACTIVE_STATES2.has(provision.status)) {
|
|
@@ -7145,7 +7454,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7145
7454
|
if (mounted.current) setBusy(false);
|
|
7146
7455
|
}
|
|
7147
7456
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
7148
|
-
|
|
7457
|
+
React16.useEffect(() => {
|
|
7149
7458
|
const attemptId = provision?.attemptId;
|
|
7150
7459
|
if (!attemptId || !ACTIVE_STATES2.has(provision.status)) return void 0;
|
|
7151
7460
|
const controller = new AbortController();
|
|
@@ -7175,13 +7484,19 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7175
7484
|
window.clearTimeout(timer);
|
|
7176
7485
|
};
|
|
7177
7486
|
}, [invoke, loadStatus, provision?.attemptId, provision?.pollIntervalMs, provision?.status]);
|
|
7178
|
-
const botAction =
|
|
7487
|
+
const botAction = React16.useCallback(async (account, operation, endpoint, payload) => {
|
|
7179
7488
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
7180
7489
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
7181
7490
|
try {
|
|
7182
7491
|
const snapshot = normalizeSnapshot6(await invoke(endpoint, payload));
|
|
7183
7492
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
7184
|
-
setModel({
|
|
7493
|
+
setModel({
|
|
7494
|
+
phase: "ready",
|
|
7495
|
+
bots: snapshot.bots,
|
|
7496
|
+
totals: snapshot.totals,
|
|
7497
|
+
error: null,
|
|
7498
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7499
|
+
});
|
|
7185
7500
|
}
|
|
7186
7501
|
return snapshot;
|
|
7187
7502
|
} finally {
|
|
@@ -7194,7 +7509,7 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7194
7509
|
});
|
|
7195
7510
|
}
|
|
7196
7511
|
}, [invoke, loadStatus, workspaceFence]);
|
|
7197
|
-
const reconnect =
|
|
7512
|
+
const reconnect = React16.useCallback(async (account) => {
|
|
7198
7513
|
setFeedbackByBot((current) => {
|
|
7199
7514
|
const next = { ...current };
|
|
7200
7515
|
delete next[account.botId];
|
|
@@ -7268,6 +7583,12 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7268
7583
|
WECOM_ENDPOINTS.setWorkspace,
|
|
7269
7584
|
{ botId: account.botId, workspace }
|
|
7270
7585
|
),
|
|
7586
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
7587
|
+
account,
|
|
7588
|
+
"preset",
|
|
7589
|
+
WECOM_ENDPOINTS.setAgentPreset,
|
|
7590
|
+
{ botId: account.botId, agentPreset }
|
|
7591
|
+
),
|
|
7271
7592
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
7272
7593
|
onCancelRemove: () => setRemoveTarget(null),
|
|
7273
7594
|
onConfirmRemove: async () => {
|
|
@@ -7290,7 +7611,9 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7290
7611
|
setCredentialError(null);
|
|
7291
7612
|
}
|
|
7292
7613
|
}) : null;
|
|
7293
|
-
return h2(
|
|
7614
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
7615
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
7616
|
+
}, h2(
|
|
7294
7617
|
"section",
|
|
7295
7618
|
{ className: "ddt-page dwecom-page dim-channelPage", "aria-label": "\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
7296
7619
|
h2(Heading4, {
|
|
@@ -7307,18 +7630,18 @@ function WecomSettingsTab({ rpcCall }) {
|
|
|
7307
7630
|
}),
|
|
7308
7631
|
h2("div", { className: "ddt-visuallyHidden", role: "status", "aria-live": "polite" }, notice),
|
|
7309
7632
|
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(
|
|
7310
|
-
|
|
7633
|
+
React16.Fragment,
|
|
7311
7634
|
null,
|
|
7312
7635
|
credentialView,
|
|
7313
7636
|
provisionView,
|
|
7314
7637
|
model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView4, { busy, onStart: () => void startProvisioning() }) : null,
|
|
7315
7638
|
botList
|
|
7316
7639
|
)
|
|
7317
|
-
);
|
|
7640
|
+
));
|
|
7318
7641
|
}
|
|
7319
7642
|
|
|
7320
7643
|
// plugin-src/client/channels/weixin/index.js
|
|
7321
|
-
var
|
|
7644
|
+
var React17 = __toESM(require("react"), 1);
|
|
7322
7645
|
|
|
7323
7646
|
// plugin-src/client/channels/weixin/api.js
|
|
7324
7647
|
var WEIXIN_RPC_CHANNEL = "/weixin";
|
|
@@ -7330,7 +7653,8 @@ var WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
7330
7653
|
cancelProvisioning: "provision.cancel",
|
|
7331
7654
|
reconnectBot: "bot.reconnect",
|
|
7332
7655
|
deleteBot: "bot.delete",
|
|
7333
|
-
setWorkspace: "bot.workspace.set"
|
|
7656
|
+
setWorkspace: "bot.workspace.set",
|
|
7657
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
7334
7658
|
});
|
|
7335
7659
|
var ACCOUNT_STATES5 = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
7336
7660
|
var PROVISION_STATES4 = /* @__PURE__ */ new Set([
|
|
@@ -7360,6 +7684,14 @@ function normalizeTestMessage4(value) {
|
|
|
7360
7684
|
const code = value.code === "test-target-unavailable" ? "test-target-unavailable" : "test-message-failed";
|
|
7361
7685
|
return { sent: false, code };
|
|
7362
7686
|
}
|
|
7687
|
+
function normalizeMessageError(value) {
|
|
7688
|
+
if (!isRecord6(value)) return null;
|
|
7689
|
+
const code = string(value.code).slice(0, 64);
|
|
7690
|
+
const reason = string(value.reason).slice(0, 128);
|
|
7691
|
+
const message = string(value.message).slice(0, 500);
|
|
7692
|
+
const at = timestamp5(value.at);
|
|
7693
|
+
return code && reason && message && at !== null ? { code, reason, message, at } : null;
|
|
7694
|
+
}
|
|
7363
7695
|
function unwrapRpcResult8(result) {
|
|
7364
7696
|
if (!isRecord6(result) || typeof result.ok !== "boolean") {
|
|
7365
7697
|
throw new Error("\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
@@ -7420,6 +7752,7 @@ function normalizeBot5(value) {
|
|
|
7420
7752
|
connected,
|
|
7421
7753
|
configured: value.configured === true,
|
|
7422
7754
|
workspace: string(value.workspace).slice(0, 4096),
|
|
7755
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
7423
7756
|
bot: {
|
|
7424
7757
|
name: string(value.bot.name, "\u5FAE\u4FE1\u673A\u5668\u4EBA"),
|
|
7425
7758
|
accountIdMasked: string(value.bot.accountIdMasked, "\u5DF2\u5B89\u5168\u4FDD\u5B58")
|
|
@@ -7433,6 +7766,7 @@ function normalizeBot5(value) {
|
|
|
7433
7766
|
messagesReceived: Math.max(0, Number(value.stats?.messagesReceived) || 0),
|
|
7434
7767
|
messagesReplied: Math.max(0, Number(value.stats?.messagesReplied) || 0)
|
|
7435
7768
|
},
|
|
7769
|
+
lastMessageError: normalizeMessageError(value.lastMessageError),
|
|
7436
7770
|
error: isRecord6(value.error) ? {
|
|
7437
7771
|
code: string(value.error.code, "WEIXIN_ACCOUNT_ERROR"),
|
|
7438
7772
|
message: string(value.error.message, "\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA")
|
|
@@ -7454,7 +7788,8 @@ function normalizeSnapshot7(value) {
|
|
|
7454
7788
|
connected: bots.filter((bot) => bot.connected).length
|
|
7455
7789
|
},
|
|
7456
7790
|
provisioning: value.provisioning ? normalizeProvisioning5(value.provisioning) : null,
|
|
7457
|
-
testMessage: normalizeTestMessage4(value.testMessage)
|
|
7791
|
+
testMessage: normalizeTestMessage4(value.testMessage),
|
|
7792
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog)
|
|
7458
7793
|
};
|
|
7459
7794
|
}
|
|
7460
7795
|
function presentError8(error) {
|
|
@@ -7591,7 +7926,7 @@ function installWeixinStyles() {
|
|
|
7591
7926
|
}
|
|
7592
7927
|
|
|
7593
7928
|
// plugin-src/client/channels/weixin/index.js
|
|
7594
|
-
var Button12 =
|
|
7929
|
+
var Button12 = React17.forwardRef(function Button13({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
7595
7930
|
return h2("button", {
|
|
7596
7931
|
...props,
|
|
7597
7932
|
ref,
|
|
@@ -7664,14 +7999,14 @@ function EmptyView5({ onStart, busy }) {
|
|
|
7664
7999
|
);
|
|
7665
8000
|
}
|
|
7666
8001
|
function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
7667
|
-
const [imageFailed, setImageFailed] =
|
|
8002
|
+
const [imageFailed, setImageFailed] = React17.useState(false);
|
|
7668
8003
|
const source = safeQrSource5(provision.qrCodeDataUrl);
|
|
7669
8004
|
const href = safeVerificationUrl(provision.verificationUrl);
|
|
7670
8005
|
const remaining = Math.max(0, provision.expiresAt - now);
|
|
7671
8006
|
const expired = remaining === 0 || provision.status === "expired";
|
|
7672
8007
|
const duration = Math.max(1, provision.durationMs ?? 5 * 6e4);
|
|
7673
8008
|
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
7674
|
-
|
|
8009
|
+
React17.useEffect(() => setImageFailed(false), [source]);
|
|
7675
8010
|
return h2(
|
|
7676
8011
|
"div",
|
|
7677
8012
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -7738,9 +8073,9 @@ function QrPanel4({ provision, now, busy, onRefresh, onCancel }) {
|
|
|
7738
8073
|
);
|
|
7739
8074
|
}
|
|
7740
8075
|
function VerificationPanel({ provision, busy, onSubmit, onCancel }) {
|
|
7741
|
-
const [code, setCode] =
|
|
8076
|
+
const [code, setCode] = React17.useState("");
|
|
7742
8077
|
const valid = /^\d{4,8}$/.test(code);
|
|
7743
|
-
|
|
8078
|
+
React17.useEffect(() => setCode(""), [provision.attemptId]);
|
|
7744
8079
|
return h2(
|
|
7745
8080
|
"div",
|
|
7746
8081
|
{ className: "dxw-card dim-surfaceCard" },
|
|
@@ -7838,6 +8173,7 @@ function AccountCard4({
|
|
|
7838
8173
|
removing,
|
|
7839
8174
|
onReconnect,
|
|
7840
8175
|
onWorkspaceSave,
|
|
8176
|
+
onAgentPresetSave,
|
|
7841
8177
|
onRequestRemove,
|
|
7842
8178
|
onConfirmRemove,
|
|
7843
8179
|
onCancelRemove
|
|
@@ -7888,10 +8224,19 @@ function AccountCard4({
|
|
|
7888
8224
|
disabled: Boolean(busy),
|
|
7889
8225
|
onSave: onWorkspaceSave
|
|
7890
8226
|
}),
|
|
8227
|
+
h2(AgentPresetEditor, {
|
|
8228
|
+
agentPreset: account.agentPreset,
|
|
8229
|
+
disabled: Boolean(busy),
|
|
8230
|
+
onSave: onAgentPresetSave
|
|
8231
|
+
}),
|
|
7891
8232
|
h2(
|
|
7892
8233
|
"div",
|
|
7893
8234
|
{ className: "dxw-accountFooter dim-cardFooter" },
|
|
7894
8235
|
summary ? h2("div", { className: "dxw-summary dim-cardSummary" }, summary) : null,
|
|
8236
|
+
account.lastMessageError ? h2("div", {
|
|
8237
|
+
className: "dxw-summary dim-cardSummary",
|
|
8238
|
+
role: "status"
|
|
8239
|
+
}, `\u6700\u8FD1\u4E00\u6761\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF1A${account.lastMessageError.message}`) : null,
|
|
7895
8240
|
feedback ? h2("div", {
|
|
7896
8241
|
className: "dxw-summary dim-cardSummary",
|
|
7897
8242
|
role: "status",
|
|
@@ -7942,6 +8287,7 @@ function AccountList2(props) {
|
|
|
7942
8287
|
removing: props.removeTarget === account.botId,
|
|
7943
8288
|
onReconnect: () => props.onReconnect(account),
|
|
7944
8289
|
onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
|
|
8290
|
+
onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
|
|
7945
8291
|
onRequestRemove: () => props.onRequestRemove(account),
|
|
7946
8292
|
onConfirmRemove: () => props.onConfirmRemove(account),
|
|
7947
8293
|
onCancelRemove: props.onCancelRemove
|
|
@@ -7960,40 +8306,41 @@ function mergeWeixinProvisioningSnapshot(current, incoming, { restoreProvisionin
|
|
|
7960
8306
|
};
|
|
7961
8307
|
}
|
|
7962
8308
|
function WeixinSettingsTab({ rpcCall }) {
|
|
7963
|
-
const [model, setModel] =
|
|
8309
|
+
const [model, setModel] = React17.useState({
|
|
7964
8310
|
phase: "loading",
|
|
7965
8311
|
bots: [],
|
|
7966
8312
|
totals: EMPTY_TOTALS3,
|
|
7967
8313
|
revision: 0,
|
|
7968
|
-
error: null
|
|
8314
|
+
error: null,
|
|
8315
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
7969
8316
|
});
|
|
7970
|
-
const [provision, setProvision] =
|
|
7971
|
-
const [busy, setBusy] =
|
|
7972
|
-
const [busyByBot, setBusyByBot] =
|
|
7973
|
-
const [feedbackByBot, setFeedbackByBot] =
|
|
7974
|
-
const [removeTarget, setRemoveTarget] =
|
|
7975
|
-
const [notice, setNotice] =
|
|
7976
|
-
const [now, setNow] =
|
|
7977
|
-
const addButtonRef =
|
|
7978
|
-
const mountedRef =
|
|
8317
|
+
const [provision, setProvision] = React17.useState(null);
|
|
8318
|
+
const [busy, setBusy] = React17.useState(false);
|
|
8319
|
+
const [busyByBot, setBusyByBot] = React17.useState({});
|
|
8320
|
+
const [feedbackByBot, setFeedbackByBot] = React17.useState({});
|
|
8321
|
+
const [removeTarget, setRemoveTarget] = React17.useState(null);
|
|
8322
|
+
const [notice, setNotice] = React17.useState("");
|
|
8323
|
+
const [now, setNow] = React17.useState(() => Date.now());
|
|
8324
|
+
const addButtonRef = React17.useRef(null);
|
|
8325
|
+
const mountedRef = React17.useRef(true);
|
|
7979
8326
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
7980
8327
|
const scheduleAnimationFrame = useAnimationFrameScheduler();
|
|
7981
|
-
|
|
8328
|
+
React17.useEffect(() => {
|
|
7982
8329
|
mountedRef.current = true;
|
|
7983
8330
|
return () => {
|
|
7984
8331
|
mountedRef.current = false;
|
|
7985
8332
|
};
|
|
7986
8333
|
}, []);
|
|
7987
|
-
const announce =
|
|
8334
|
+
const announce = React17.useCallback((value) => {
|
|
7988
8335
|
setNotice("");
|
|
7989
8336
|
scheduleAnimationFrame(() => {
|
|
7990
8337
|
if (value) setNotice(value);
|
|
7991
8338
|
}, "announcement");
|
|
7992
8339
|
}, [scheduleAnimationFrame]);
|
|
7993
|
-
const invoke =
|
|
8340
|
+
const invoke = React17.useCallback(async (endpoint, payload = {}, signal) => {
|
|
7994
8341
|
return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
|
|
7995
8342
|
}, [rpcCall]);
|
|
7996
|
-
const loadStatus =
|
|
8343
|
+
const loadStatus = React17.useCallback(async ({
|
|
7997
8344
|
signal,
|
|
7998
8345
|
silent = false,
|
|
7999
8346
|
restoreProvisioning = false
|
|
@@ -8009,7 +8356,8 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8009
8356
|
bots: snapshot.bots,
|
|
8010
8357
|
totals: snapshot.totals,
|
|
8011
8358
|
revision: snapshot.revision,
|
|
8012
|
-
error: null
|
|
8359
|
+
error: null,
|
|
8360
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8013
8361
|
});
|
|
8014
8362
|
if (snapshot.provisioning) {
|
|
8015
8363
|
setProvision((current) => mergeWeixinProvisioningSnapshot(
|
|
@@ -8029,12 +8377,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8029
8377
|
return void 0;
|
|
8030
8378
|
}
|
|
8031
8379
|
}, [invoke, workspaceFence]);
|
|
8032
|
-
|
|
8380
|
+
React17.useEffect(() => {
|
|
8033
8381
|
const controller = new AbortController();
|
|
8034
8382
|
void loadStatus({ signal: controller.signal, restoreProvisioning: true });
|
|
8035
8383
|
return () => controller.abort();
|
|
8036
8384
|
}, [loadStatus]);
|
|
8037
|
-
|
|
8385
|
+
React17.useEffect(() => {
|
|
8038
8386
|
if (model.phase !== "ready") return void 0;
|
|
8039
8387
|
const controller = new AbortController();
|
|
8040
8388
|
let running = false;
|
|
@@ -8053,12 +8401,12 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8053
8401
|
window.clearInterval(timer);
|
|
8054
8402
|
};
|
|
8055
8403
|
}, [loadStatus, model.phase]);
|
|
8056
|
-
|
|
8404
|
+
React17.useEffect(() => {
|
|
8057
8405
|
if (!provision || !["pending", "scanned"].includes(provision.status)) return void 0;
|
|
8058
8406
|
const timer = window.setInterval(() => setNow(Date.now()), 1e3);
|
|
8059
8407
|
return () => window.clearInterval(timer);
|
|
8060
8408
|
}, [provision?.attemptId, provision?.status]);
|
|
8061
|
-
const startProvisioning =
|
|
8409
|
+
const startProvisioning = React17.useCallback(async ({ replace = false } = {}) => {
|
|
8062
8410
|
setBusy(true);
|
|
8063
8411
|
try {
|
|
8064
8412
|
if (replace && provision?.attemptId) {
|
|
@@ -8079,7 +8427,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8079
8427
|
setBusy(false);
|
|
8080
8428
|
}
|
|
8081
8429
|
}, [announce, invoke, provision?.attemptId]);
|
|
8082
|
-
const cancelProvisioning =
|
|
8430
|
+
const cancelProvisioning = React17.useCallback(async () => {
|
|
8083
8431
|
setBusy(true);
|
|
8084
8432
|
try {
|
|
8085
8433
|
if (provision?.attemptId && !["failed", "expired", "cancelled"].includes(provision.status)) {
|
|
@@ -8094,7 +8442,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8094
8442
|
setBusy(false);
|
|
8095
8443
|
}
|
|
8096
8444
|
}, [announce, invoke, provision?.attemptId, provision?.status, scheduleAnimationFrame]);
|
|
8097
|
-
const submitVerification =
|
|
8445
|
+
const submitVerification = React17.useCallback(async (verifyCode) => {
|
|
8098
8446
|
if (!provision?.attemptId) return;
|
|
8099
8447
|
setBusy(true);
|
|
8100
8448
|
try {
|
|
@@ -8110,7 +8458,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8110
8458
|
setBusy(false);
|
|
8111
8459
|
}
|
|
8112
8460
|
}, [announce, invoke, provision?.attemptId]);
|
|
8113
|
-
|
|
8461
|
+
React17.useEffect(() => {
|
|
8114
8462
|
const attemptId = provision?.attemptId;
|
|
8115
8463
|
if (!attemptId || !["pending", "scanned", "connecting"].includes(provision.status)) return void 0;
|
|
8116
8464
|
const controller = new AbortController();
|
|
@@ -8158,7 +8506,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8158
8506
|
controller.abort();
|
|
8159
8507
|
};
|
|
8160
8508
|
}, [announce, invoke, loadStatus, provision?.attemptId, provision?.status, provision?.pollIntervalMs]);
|
|
8161
|
-
const setBotBusy =
|
|
8509
|
+
const setBotBusy = React17.useCallback((botId, value) => {
|
|
8162
8510
|
setBusyByBot((current) => {
|
|
8163
8511
|
const next = { ...current };
|
|
8164
8512
|
if (value) next[botId] = value;
|
|
@@ -8166,7 +8514,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8166
8514
|
return next;
|
|
8167
8515
|
});
|
|
8168
8516
|
}, []);
|
|
8169
|
-
const reconnect =
|
|
8517
|
+
const reconnect = React17.useCallback(async (account) => {
|
|
8170
8518
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8171
8519
|
setBotBusy(account.botId, "reconnect");
|
|
8172
8520
|
setFeedbackByBot((current) => {
|
|
@@ -8180,7 +8528,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8180
8528
|
{ botId: account.botId, sendTest: true }
|
|
8181
8529
|
));
|
|
8182
8530
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8183
|
-
setModel((current) => ({
|
|
8531
|
+
setModel((current) => ({
|
|
8532
|
+
...current,
|
|
8533
|
+
bots: snapshot.bots,
|
|
8534
|
+
totals: snapshot.totals,
|
|
8535
|
+
revision: snapshot.revision,
|
|
8536
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
8537
|
+
}));
|
|
8184
8538
|
}
|
|
8185
8539
|
const refreshed = snapshot.bots.find((bot) => bot.botId === account.botId);
|
|
8186
8540
|
let feedback;
|
|
@@ -8211,7 +8565,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8211
8565
|
setBotBusy(account.botId, null);
|
|
8212
8566
|
}
|
|
8213
8567
|
}, [announce, invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8214
|
-
const saveWorkspace =
|
|
8568
|
+
const saveWorkspace = React17.useCallback(async (account, workspace) => {
|
|
8215
8569
|
const workspaceVersion = workspaceFence.beginMutation();
|
|
8216
8570
|
setBotBusy(account.botId, "workspace");
|
|
8217
8571
|
try {
|
|
@@ -8225,7 +8579,32 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8225
8579
|
bots: snapshot.bots,
|
|
8226
8580
|
totals: snapshot.totals,
|
|
8227
8581
|
revision: snapshot.revision,
|
|
8228
|
-
error: null
|
|
8582
|
+
error: null,
|
|
8583
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8584
|
+
});
|
|
8585
|
+
}
|
|
8586
|
+
} finally {
|
|
8587
|
+
const shouldRefresh = workspaceFence.endMutation();
|
|
8588
|
+
if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
|
|
8589
|
+
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
8590
|
+
}
|
|
8591
|
+
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8592
|
+
const saveAgentPreset = React17.useCallback(async (account, agentPreset) => {
|
|
8593
|
+
const snapshotVersion = workspaceFence.beginMutation();
|
|
8594
|
+
setBotBusy(account.botId, "preset");
|
|
8595
|
+
try {
|
|
8596
|
+
const snapshot = normalizeSnapshot7(await invoke(
|
|
8597
|
+
WEIXIN_ENDPOINTS.setAgentPreset,
|
|
8598
|
+
{ botId: account.botId, agentPreset }
|
|
8599
|
+
));
|
|
8600
|
+
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8601
|
+
setModel({
|
|
8602
|
+
phase: "ready",
|
|
8603
|
+
bots: snapshot.bots,
|
|
8604
|
+
totals: snapshot.totals,
|
|
8605
|
+
revision: snapshot.revision,
|
|
8606
|
+
error: null,
|
|
8607
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8229
8608
|
});
|
|
8230
8609
|
}
|
|
8231
8610
|
} finally {
|
|
@@ -8234,7 +8613,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8234
8613
|
if (mountedRef.current) setBotBusy(account.botId, null);
|
|
8235
8614
|
}
|
|
8236
8615
|
}, [invoke, loadStatus, setBotBusy, workspaceFence]);
|
|
8237
|
-
const remove =
|
|
8616
|
+
const remove = React17.useCallback(async (account) => {
|
|
8238
8617
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8239
8618
|
setBotBusy(account.botId, "delete");
|
|
8240
8619
|
try {
|
|
@@ -8243,7 +8622,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8243
8622
|
confirm: true
|
|
8244
8623
|
}));
|
|
8245
8624
|
if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8246
|
-
setModel((current) => ({
|
|
8625
|
+
setModel((current) => ({
|
|
8626
|
+
...current,
|
|
8627
|
+
bots: snapshot.bots,
|
|
8628
|
+
totals: snapshot.totals,
|
|
8629
|
+
revision: snapshot.revision,
|
|
8630
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? current.agentPresetCatalog
|
|
8631
|
+
}));
|
|
8247
8632
|
}
|
|
8248
8633
|
setRemoveTarget(null);
|
|
8249
8634
|
announce("\u5FAE\u4FE1\u8D26\u53F7\u53CA\u672C\u673A\u51ED\u636E\u5DF2\u79FB\u9664\u3002");
|
|
@@ -8287,7 +8672,9 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8287
8672
|
onClose: () => void cancelProvisioning()
|
|
8288
8673
|
});
|
|
8289
8674
|
}
|
|
8290
|
-
return h2(
|
|
8675
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
8676
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
8677
|
+
}, h2(
|
|
8291
8678
|
"section",
|
|
8292
8679
|
{ className: "dxw-page dim-channelPage", "aria-label": "\u5FAE\u4FE1\u8BBE\u7F6E" },
|
|
8293
8680
|
h2(Heading5, {
|
|
@@ -8310,7 +8697,7 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8310
8697
|
h2(Button12, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
8311
8698
|
)
|
|
8312
8699
|
) : h2(
|
|
8313
|
-
|
|
8700
|
+
React17.Fragment,
|
|
8314
8701
|
null,
|
|
8315
8702
|
provisionView,
|
|
8316
8703
|
model.bots.length === 0 && !provision ? h2(EmptyView5, { onStart: () => void startProvisioning(), busy }) : null,
|
|
@@ -8321,12 +8708,13 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
8321
8708
|
removeTarget,
|
|
8322
8709
|
onReconnect: (account) => void reconnect(account),
|
|
8323
8710
|
onWorkspaceSave: saveWorkspace,
|
|
8711
|
+
onAgentPresetSave: saveAgentPreset,
|
|
8324
8712
|
onRequestRemove: (account) => setRemoveTarget(account.botId),
|
|
8325
8713
|
onConfirmRemove: (account) => void remove(account),
|
|
8326
8714
|
onCancelRemove: () => setRemoveTarget(null)
|
|
8327
8715
|
}) : null
|
|
8328
8716
|
)
|
|
8329
|
-
);
|
|
8717
|
+
));
|
|
8330
8718
|
}
|
|
8331
8719
|
|
|
8332
8720
|
// plugin-src/client/channels/whatsapp/api.js
|
|
@@ -8338,7 +8726,8 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
8338
8726
|
cancelProvisioning: "provision.cancel",
|
|
8339
8727
|
reconnectBot: "bot.reconnect",
|
|
8340
8728
|
deleteBot: "bot.delete",
|
|
8341
|
-
setWorkspace: "bot.workspace.set"
|
|
8729
|
+
setWorkspace: "bot.workspace.set",
|
|
8730
|
+
setAgentPreset: SET_AGENT_PRESET_ENDPOINT
|
|
8342
8731
|
});
|
|
8343
8732
|
var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
|
|
8344
8733
|
var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
@@ -8403,6 +8792,7 @@ function normalizeBot6(value) {
|
|
|
8403
8792
|
connected,
|
|
8404
8793
|
state: connected ? "connected" : state,
|
|
8405
8794
|
workspace: text4(value.workspace, "", 4096),
|
|
8795
|
+
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
|
8406
8796
|
bot: {
|
|
8407
8797
|
name: text4(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
|
|
8408
8798
|
idMasked: text4(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
|
|
@@ -8427,7 +8817,8 @@ function normalizeSnapshot8(value) {
|
|
|
8427
8817
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
8428
8818
|
bots,
|
|
8429
8819
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
8430
|
-
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null
|
|
8820
|
+
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null,
|
|
8821
|
+
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
|
8431
8822
|
};
|
|
8432
8823
|
}
|
|
8433
8824
|
function presentError9(error) {
|
|
@@ -8442,7 +8833,7 @@ function formatRemaining6(milliseconds) {
|
|
|
8442
8833
|
}
|
|
8443
8834
|
|
|
8444
8835
|
// plugin-src/client/channels/whatsapp/index.js
|
|
8445
|
-
var
|
|
8836
|
+
var React18 = __toESM(require("react"), 1);
|
|
8446
8837
|
|
|
8447
8838
|
// plugin-src/client/channels/whatsapp/styles.js
|
|
8448
8839
|
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
|
@@ -8467,7 +8858,7 @@ function installWhatsappStyles() {
|
|
|
8467
8858
|
|
|
8468
8859
|
// plugin-src/client/channels/whatsapp/index.js
|
|
8469
8860
|
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
|
8470
|
-
var Button14 =
|
|
8861
|
+
var Button14 = React18.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
8471
8862
|
return h2("button", {
|
|
8472
8863
|
...props,
|
|
8473
8864
|
ref,
|
|
@@ -8689,6 +9080,7 @@ function WhatsappAccountCard({
|
|
|
8689
9080
|
removing,
|
|
8690
9081
|
onReconnect,
|
|
8691
9082
|
onWorkspaceSave,
|
|
9083
|
+
onAgentPresetSave,
|
|
8692
9084
|
onRequestRemove,
|
|
8693
9085
|
onConfirmRemove,
|
|
8694
9086
|
onCancelRemove
|
|
@@ -8748,6 +9140,11 @@ function WhatsappAccountCard({
|
|
|
8748
9140
|
disabled: Boolean(busy),
|
|
8749
9141
|
onSave: onWorkspaceSave
|
|
8750
9142
|
}),
|
|
9143
|
+
h2(AgentPresetEditor, {
|
|
9144
|
+
agentPreset: account.agentPreset,
|
|
9145
|
+
disabled: Boolean(busy),
|
|
9146
|
+
onSave: onAgentPresetSave
|
|
9147
|
+
}),
|
|
8751
9148
|
h2(
|
|
8752
9149
|
"div",
|
|
8753
9150
|
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
@@ -8782,22 +9179,23 @@ function WhatsappAccountCard({
|
|
|
8782
9179
|
);
|
|
8783
9180
|
}
|
|
8784
9181
|
function WhatsappSettingsTab({ rpcCall }) {
|
|
8785
|
-
const [model, setModel] =
|
|
9182
|
+
const [model, setModel] = React18.useState({
|
|
8786
9183
|
phase: "loading",
|
|
8787
9184
|
bots: [],
|
|
8788
9185
|
totals: { configured: 0, connected: 0 },
|
|
8789
|
-
error: null
|
|
9186
|
+
error: null,
|
|
9187
|
+
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
|
8790
9188
|
});
|
|
8791
|
-
const [provision, setProvision] =
|
|
8792
|
-
const [busy, setBusy] =
|
|
8793
|
-
const [busyByBot, setBusyByBot] =
|
|
8794
|
-
const [testNoticeByBot, setTestNoticeByBot] =
|
|
8795
|
-
const [removeTarget, setRemoveTarget] =
|
|
8796
|
-
const [now, setNow] =
|
|
8797
|
-
const mounted =
|
|
9189
|
+
const [provision, setProvision] = React18.useState(null);
|
|
9190
|
+
const [busy, setBusy] = React18.useState(false);
|
|
9191
|
+
const [busyByBot, setBusyByBot] = React18.useState({});
|
|
9192
|
+
const [testNoticeByBot, setTestNoticeByBot] = React18.useState({});
|
|
9193
|
+
const [removeTarget, setRemoveTarget] = React18.useState(null);
|
|
9194
|
+
const [now, setNow] = React18.useState(Date.now());
|
|
9195
|
+
const mounted = React18.useRef(true);
|
|
8798
9196
|
const workspaceFence = useWorkspaceSnapshotFence();
|
|
8799
|
-
const addButtonRef =
|
|
8800
|
-
|
|
9197
|
+
const addButtonRef = React18.useRef(null);
|
|
9198
|
+
React18.useEffect(() => {
|
|
8801
9199
|
const disposeDingtalk = installDingtalkStyles();
|
|
8802
9200
|
const disposeWhatsapp = installWhatsappStyles();
|
|
8803
9201
|
mounted.current = true;
|
|
@@ -8807,18 +9205,24 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8807
9205
|
disposeDingtalk();
|
|
8808
9206
|
};
|
|
8809
9207
|
}, []);
|
|
8810
|
-
const invoke =
|
|
9208
|
+
const invoke = React18.useCallback(async (endpoint, payload = {}, signal) => {
|
|
8811
9209
|
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
8812
9210
|
return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
|
|
8813
9211
|
}, [rpcCall]);
|
|
8814
|
-
const loadStatus =
|
|
9212
|
+
const loadStatus = React18.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
8815
9213
|
const workspaceVersion = workspaceFence.beginStatus();
|
|
8816
9214
|
if (workspaceVersion === null) return void 0;
|
|
8817
9215
|
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
8818
9216
|
try {
|
|
8819
9217
|
const snapshot = normalizeSnapshot8(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
8820
9218
|
if (!mounted.current || signal?.aborted || !workspaceFence.canCommitStatus(workspaceVersion)) return void 0;
|
|
8821
|
-
setModel({
|
|
9219
|
+
setModel({
|
|
9220
|
+
phase: "ready",
|
|
9221
|
+
bots: snapshot.bots,
|
|
9222
|
+
totals: snapshot.totals,
|
|
9223
|
+
error: null,
|
|
9224
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9225
|
+
});
|
|
8822
9226
|
if (restore && snapshot.provisioning) setProvision({
|
|
8823
9227
|
...snapshot.provisioning,
|
|
8824
9228
|
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
@@ -8835,12 +9239,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8835
9239
|
return void 0;
|
|
8836
9240
|
}
|
|
8837
9241
|
}, [invoke, workspaceFence]);
|
|
8838
|
-
|
|
9242
|
+
React18.useEffect(() => {
|
|
8839
9243
|
const controller = new AbortController();
|
|
8840
9244
|
void loadStatus({ signal: controller.signal, restore: true });
|
|
8841
9245
|
return () => controller.abort();
|
|
8842
9246
|
}, [loadStatus]);
|
|
8843
|
-
|
|
9247
|
+
React18.useEffect(() => {
|
|
8844
9248
|
if (model.phase !== "ready") return void 0;
|
|
8845
9249
|
const controller = new AbortController();
|
|
8846
9250
|
const timer = window.setInterval(
|
|
@@ -8852,12 +9256,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8852
9256
|
window.clearInterval(timer);
|
|
8853
9257
|
};
|
|
8854
9258
|
}, [loadStatus, model.phase]);
|
|
8855
|
-
|
|
9259
|
+
React18.useEffect(() => {
|
|
8856
9260
|
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
8857
9261
|
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
8858
9262
|
return () => window.clearInterval(timer);
|
|
8859
9263
|
}, [provision?.attemptId, provision?.status]);
|
|
8860
|
-
const startProvisioning =
|
|
9264
|
+
const startProvisioning = React18.useCallback(async (replace = false) => {
|
|
8861
9265
|
setBusy(true);
|
|
8862
9266
|
try {
|
|
8863
9267
|
if (replace && provision?.attemptId) {
|
|
@@ -8875,7 +9279,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8875
9279
|
if (mounted.current) setBusy(false);
|
|
8876
9280
|
}
|
|
8877
9281
|
}, [invoke, provision?.attemptId]);
|
|
8878
|
-
const closeProvision =
|
|
9282
|
+
const closeProvision = React18.useCallback(async () => {
|
|
8879
9283
|
setBusy(true);
|
|
8880
9284
|
try {
|
|
8881
9285
|
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
|
@@ -8886,7 +9290,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8886
9290
|
if (mounted.current) setBusy(false);
|
|
8887
9291
|
}
|
|
8888
9292
|
}, [invoke, provision?.attemptId, provision?.status]);
|
|
8889
|
-
|
|
9293
|
+
React18.useEffect(() => {
|
|
8890
9294
|
const attemptId = provision?.attemptId;
|
|
8891
9295
|
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
8892
9296
|
const controller = new AbortController();
|
|
@@ -8927,7 +9331,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8927
9331
|
if (timer) window.clearTimeout(timer);
|
|
8928
9332
|
};
|
|
8929
9333
|
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
|
8930
|
-
const botAction =
|
|
9334
|
+
const botAction = React18.useCallback(async (account, operation, endpoint, payload) => {
|
|
8931
9335
|
const snapshotVersion = workspaceFence.beginMutation();
|
|
8932
9336
|
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
8933
9337
|
if (operation === "reconnect") {
|
|
@@ -8941,7 +9345,13 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8941
9345
|
const value = await invoke(endpoint, payload);
|
|
8942
9346
|
const snapshot = normalizeSnapshot8(value);
|
|
8943
9347
|
if (mounted.current && workspaceFence.canCommitMutation(snapshotVersion)) {
|
|
8944
|
-
setModel({
|
|
9348
|
+
setModel({
|
|
9349
|
+
phase: "ready",
|
|
9350
|
+
bots: snapshot.bots,
|
|
9351
|
+
totals: snapshot.totals,
|
|
9352
|
+
error: null,
|
|
9353
|
+
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9354
|
+
});
|
|
8945
9355
|
if (operation === "reconnect") {
|
|
8946
9356
|
setTestNoticeByBot((current) => ({
|
|
8947
9357
|
...current,
|
|
@@ -8992,6 +9402,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
8992
9402
|
WHATSAPP_ENDPOINTS.setWorkspace,
|
|
8993
9403
|
{ botId: account.botId, workspace }
|
|
8994
9404
|
),
|
|
9405
|
+
onAgentPresetSave: (agentPreset) => botAction(
|
|
9406
|
+
account,
|
|
9407
|
+
"preset",
|
|
9408
|
+
WHATSAPP_ENDPOINTS.setAgentPreset,
|
|
9409
|
+
{ botId: account.botId, agentPreset }
|
|
9410
|
+
),
|
|
8995
9411
|
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
8996
9412
|
onCancelRemove: () => setRemoveTarget(null),
|
|
8997
9413
|
onConfirmRemove: async () => {
|
|
@@ -9003,7 +9419,9 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9003
9419
|
}
|
|
9004
9420
|
}))))
|
|
9005
9421
|
) : null;
|
|
9006
|
-
return h2(
|
|
9422
|
+
return h2(AgentPresetCatalogContext.Provider, {
|
|
9423
|
+
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
|
9424
|
+
}, h2(
|
|
9007
9425
|
"section",
|
|
9008
9426
|
{
|
|
9009
9427
|
className: "ddt-page dwa-page dim-channelPage",
|
|
@@ -9026,7 +9444,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9026
9444
|
h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
9027
9445
|
)
|
|
9028
9446
|
) : h2(
|
|
9029
|
-
|
|
9447
|
+
React18.Fragment,
|
|
9030
9448
|
null,
|
|
9031
9449
|
provision?.status === "pending" ? h2(QrPanel5, {
|
|
9032
9450
|
provision,
|
|
@@ -9042,7 +9460,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|
|
9042
9460
|
}) : model.bots.length === 0 ? h2(EmptyView6, { busy, onStart: () => void startProvisioning(false) }) : null,
|
|
9043
9461
|
botList
|
|
9044
9462
|
)
|
|
9045
|
-
);
|
|
9463
|
+
));
|
|
9046
9464
|
}
|
|
9047
9465
|
|
|
9048
9466
|
// plugin-src/client/styles.js
|
|
@@ -9189,6 +9607,14 @@ var CSS11 = String.raw`
|
|
|
9189
9607
|
.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; }
|
|
9190
9608
|
.dim-panel .dim-workspaceEdit:disabled { cursor: not-allowed; opacity: .55; }
|
|
9191
9609
|
.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; }
|
|
9610
|
+
.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); }
|
|
9611
|
+
.dim-panel .dim-presetHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
|
|
9612
|
+
.dim-panel .dim-presetHeader > span { grid-column: 1; grid-row: 1; white-space: nowrap; }
|
|
9613
|
+
.dim-panel .dim-presetStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
|
|
9614
|
+
.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; }
|
|
9615
|
+
.dim-panel .dim-presetSelect:disabled { cursor: not-allowed; opacity: .55; }
|
|
9616
|
+
.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; }
|
|
9617
|
+
.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; }
|
|
9192
9618
|
.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); }
|
|
9193
9619
|
.dim-directoryPickerBackdrop, .dim-directoryPickerBackdrop *, .dim-directoryPickerBackdrop *::before, .dim-directoryPickerBackdrop *::after { box-sizing: border-box; }
|
|
9194
9620
|
.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%); }
|
|
@@ -9419,8 +9845,8 @@ function IMSettingsTab({
|
|
|
9419
9845
|
officeRpcCall,
|
|
9420
9846
|
workspaceDirectoryPicker
|
|
9421
9847
|
}) {
|
|
9422
|
-
const [selected, setSelected] =
|
|
9423
|
-
const githubTooltipId =
|
|
9848
|
+
const [selected, setSelected] = React19.useState("weixin");
|
|
9849
|
+
const githubTooltipId = React19.useId();
|
|
9424
9850
|
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
|
9425
9851
|
return h2(
|
|
9426
9852
|
WorkspaceDirectoryPickerContext.Provider,
|