@niubitli/plugin-feishu-connector 0.3.1-connector-feishu

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.
@@ -0,0 +1,4047 @@
1
+ // src/ui/index.tsx
2
+ import { Children, Fragment, useEffect, useMemo, useState } from "react";
3
+ import {
4
+ usePluginAction,
5
+ usePluginData
6
+ } from "@paperclipai/plugin-sdk/ui";
7
+
8
+ // src/constants.ts
9
+ var PLUGIN_ID = "paperclipai.feishu-connector";
10
+ var DATA_KEYS = {
11
+ status: "status",
12
+ catalog: "catalog",
13
+ profiles: "profiles",
14
+ directory: "directory",
15
+ issueSource: "issue-source",
16
+ capabilities: "capabilities"
17
+ };
18
+ var ACTION_KEYS = {
19
+ simulateInboundMessage: "simulate-inbound-message",
20
+ sendMessage: "send-message",
21
+ writeBaseRecord: "write-base-record",
22
+ bindProfile: "bind-profile",
23
+ startGuidedBind: "start-guided-bind",
24
+ finishGuidedBind: "finish-guided-bind",
25
+ startUserAuth: "start-user-auth",
26
+ finishUserAuth: "finish-user-auth",
27
+ testRoute: "test-route",
28
+ checkPermissions: "check-permissions",
29
+ retryFailedDeliveries: "retry-failed-deliveries",
30
+ replyIssueSourceThread: "reply-issue-source-thread",
31
+ downloadIssueAttachments: "download-issue-attachments",
32
+ writeIssueBaseRecord: "write-issue-base-record",
33
+ lookupIssueRequester: "lookup-issue-requester",
34
+ replyIssueCommentToFeishu: "reply-issue-comment-to-feishu"
35
+ };
36
+ var DEFAULT_ACK_TEMPLATE = "\u5DF2\u6536\u5230\uFF0C\u4EA4\u7ED9 {{agent_name}} \u5904\u7406\u3002\n\u4EFB\u52A1\uFF1A{{issue_ref}}";
37
+ var DEFAULT_COMPLETION_TEMPLATE = "\u5904\u7406\u5B8C\u6210\uFF1A{{issue_title}}";
38
+ var DEFAULT_QUICK_REPLY_REGEX = "^(\u53EA\u56DE\u590D\\s*ok|\u56DE\u590D\\s*ok|ping)$";
39
+ var DEFAULT_QUICK_REPLY_TEXT = "ok";
40
+
41
+ // src/config.ts
42
+ var DEFAULT_CONFIG = {
43
+ larkCliBin: "lark-cli",
44
+ dryRunCli: true,
45
+ capabilityDefaultPolicy: "authorized",
46
+ paperclipBaseUrl: "",
47
+ enableEventSubscriber: false,
48
+ eventTypes: "im.message.receive_v1",
49
+ eventRequireSignature: false,
50
+ ackOnInbound: false,
51
+ ackMessageTemplate: DEFAULT_ACK_TEMPLATE,
52
+ completionMessageTemplate: DEFAULT_COMPLETION_TEMPLATE,
53
+ enableQuickReply: true,
54
+ quickReplyRegex: DEFAULT_QUICK_REPLY_REGEX,
55
+ quickReplyText: DEFAULT_QUICK_REPLY_TEXT
56
+ };
57
+
58
+ // src/routing.ts
59
+ function describeRouteTrigger(route) {
60
+ if (route.matchType === "chat") {
61
+ return route.chatName ? `\u6307\u5B9A\u98DE\u4E66\u4F1A\u8BDD\u300C${route.chatName}\u300D` : "\u6307\u5B9A\u98DE\u4E66\u4F1A\u8BDD";
62
+ }
63
+ if (route.matchType === "user") {
64
+ return route.userName ? `\u6307\u5B9A\u63D0\u51FA\u4EBA\u300C${route.userName}\u300D` : "\u6307\u5B9A\u63D0\u51FA\u4EBA";
65
+ }
66
+ if (route.matchType === "keyword") {
67
+ return route.keyword ? `\u5305\u542B\u300C${route.keyword}\u300D\u7684\u98DE\u4E66\u6D88\u606F` : "\u5305\u542B\u5173\u952E\u8BCD\u7684\u98DE\u4E66\u6D88\u606F";
68
+ }
69
+ if (route.matchType === "regex") {
70
+ return "\u5339\u914D\u9AD8\u7EA7\u89C4\u5219\u7684\u98DE\u4E66\u6D88\u606F";
71
+ }
72
+ return "\u9ED8\u8BA4\u5165\u53E3";
73
+ }
74
+ function isLikelyInternalRouteName(value) {
75
+ const normalized = (value ?? "").trim().toLocaleLowerCase();
76
+ if (!normalized) return false;
77
+ if (/[\u4e00-\u9fff\s]/.test(normalized)) return false;
78
+ if (/^(chat|team|keyword|regex|default|route|entry|inbound)[_-]/.test(normalized)) return true;
79
+ if (/[_-](to|agent|bot|team|chat|keyword|regex|route|entry|inbound)([_-]|$)/.test(normalized)) return true;
80
+ return /^[a-z0-9]+([_-][a-z0-9]+){2,}$/.test(normalized);
81
+ }
82
+ function describeRouteEntry(route) {
83
+ const explicitName = route.name?.trim();
84
+ if (explicitName && !isLikelyInternalRouteName(explicitName)) return explicitName;
85
+ const trigger = describeRouteTrigger(route);
86
+ const agentName = route.targetAgentName?.trim();
87
+ return agentName ? `${trigger} \u2192 ${agentName}` : trigger;
88
+ }
89
+ function describeRouteForHumans(route) {
90
+ return describeRouteEntry(route);
91
+ }
92
+
93
+ // src/ui/index.tsx
94
+ import { jsx, jsxs } from "react/jsx-runtime";
95
+ function pluginInstanceIdFromProps(props) {
96
+ const slotPluginId = props?.slot?.pluginId?.trim();
97
+ if (slotPluginId) return slotPluginId;
98
+ if (typeof window !== "undefined") {
99
+ const match = window.location.pathname.match(/\/instance\/settings\/plugins\/([^/?#]+)/);
100
+ if (match?.[1]) return decodeURIComponent(match[1]);
101
+ }
102
+ return PLUGIN_ID;
103
+ }
104
+ function pluginSettingsHref(props) {
105
+ return `/instance/settings/plugins/${encodeURIComponent(pluginInstanceIdFromProps(props))}`;
106
+ }
107
+ var mainTabs = [
108
+ { key: "overview", label: "\u603B\u89C8", detail: "\u4E0B\u4E00\u6B65", hash: "feishu-overview" },
109
+ { key: "entries", label: "\u5165\u53E3", detail: "\u4E1A\u52A1\u89C4\u5219", hash: "feishu-entries" },
110
+ { key: "robots", label: "\u673A\u5668\u4EBA", detail: "\u8D26\u53F7\u6C60", hash: "feishu-robots" },
111
+ { key: "test", label: "\u6D4B\u8BD5", detail: "\u771F\u5B9E\u786E\u8BA4", hash: "feishu-test" },
112
+ { key: "advanced", label: "\u9AD8\u7EA7", detail: "\u5DE5\u7A0B\u914D\u7F6E", hash: "feishu-advanced" }
113
+ ];
114
+ function mainTabFromHash(hash) {
115
+ const match = mainTabs.find((tab) => `#${tab.hash}` === hash);
116
+ return match?.key ?? "overview";
117
+ }
118
+ function initialMainTab() {
119
+ if (typeof window === "undefined") return "overview";
120
+ return mainTabFromHash(window.location.hash);
121
+ }
122
+ var pageStyle = {
123
+ display: "grid",
124
+ gap: "18px",
125
+ fontSize: "14px"
126
+ };
127
+ var sectionHeaderStyle = {
128
+ display: "flex",
129
+ justifyContent: "space-between",
130
+ gap: "12px",
131
+ alignItems: "flex-start"
132
+ };
133
+ var actionBarStyle = {
134
+ display: "flex",
135
+ flexWrap: "wrap",
136
+ gap: "10px",
137
+ alignItems: "center",
138
+ justifyContent: "space-between"
139
+ };
140
+ var gridTwoStyle = {
141
+ display: "grid",
142
+ gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))",
143
+ gap: "12px"
144
+ };
145
+ var stepGridStyle = {
146
+ display: "grid",
147
+ gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
148
+ gap: "12px"
149
+ };
150
+ var fieldStyle = {
151
+ display: "grid",
152
+ gap: "6px"
153
+ };
154
+ var labelStyle = {
155
+ fontSize: "13px",
156
+ fontWeight: 600
157
+ };
158
+ var helpStyle = {
159
+ fontSize: "12px",
160
+ color: "var(--muted-foreground)",
161
+ lineHeight: 1.5
162
+ };
163
+ var inputStyle = {
164
+ width: "100%",
165
+ height: "38px",
166
+ border: "1px solid var(--border)",
167
+ borderRadius: "8px",
168
+ padding: "0 12px",
169
+ background: "var(--background)",
170
+ color: "var(--foreground)",
171
+ fontSize: "14px"
172
+ };
173
+ var selectStyle = {
174
+ ...inputStyle
175
+ };
176
+ var buttonStyle = {
177
+ height: "36px",
178
+ border: "1px solid var(--border)",
179
+ borderRadius: "8px",
180
+ padding: "0 12px",
181
+ background: "var(--background)",
182
+ color: "var(--foreground)",
183
+ fontSize: "14px",
184
+ cursor: "pointer"
185
+ };
186
+ var primaryButtonStyle = {
187
+ ...buttonStyle,
188
+ border: "1px solid var(--primary)",
189
+ background: "var(--primary)",
190
+ color: "var(--primary-foreground)",
191
+ fontWeight: 600
192
+ };
193
+ var subtleBoxStyle = {
194
+ border: "1px solid var(--border)",
195
+ borderRadius: "8px",
196
+ padding: "12px",
197
+ background: "var(--muted)"
198
+ };
199
+ var successBoxStyle = {
200
+ ...subtleBoxStyle,
201
+ border: "1px solid color-mix(in oklab, var(--primary) 40%, var(--border))",
202
+ background: "color-mix(in oklab, var(--primary) 8%, var(--background))"
203
+ };
204
+ var recommendedBoxStyle = {
205
+ ...subtleBoxStyle,
206
+ border: "1px solid color-mix(in oklab, var(--primary) 55%, var(--border))",
207
+ background: "color-mix(in oklab, var(--primary) 10%, var(--background))"
208
+ };
209
+ var heroStyle = {
210
+ border: "1px solid color-mix(in oklab, var(--primary) 35%, var(--border))",
211
+ borderRadius: "12px",
212
+ padding: "16px",
213
+ display: "grid",
214
+ gap: "14px",
215
+ background: "var(--background)",
216
+ boxShadow: "0 18px 40px color-mix(in oklab, var(--foreground) 5%, transparent)"
217
+ };
218
+ var tabNavStyle = {
219
+ display: "flex",
220
+ flexWrap: "wrap",
221
+ gap: "8px",
222
+ padding: "0",
223
+ borderBottom: "1px solid var(--border)",
224
+ alignItems: "flex-end"
225
+ };
226
+ var tabLinkStyle = {
227
+ appearance: "none",
228
+ border: "0",
229
+ background: "transparent",
230
+ padding: "0 12px 10px",
231
+ color: "var(--muted-foreground)",
232
+ textDecoration: "none",
233
+ fontSize: "14px",
234
+ fontWeight: 700,
235
+ borderBottom: "2px solid transparent",
236
+ display: "grid",
237
+ gap: "2px",
238
+ textAlign: "left",
239
+ cursor: "pointer"
240
+ };
241
+ var activeTabLinkStyle = {
242
+ ...tabLinkStyle,
243
+ color: "var(--foreground)",
244
+ borderBottom: "2px solid var(--foreground)"
245
+ };
246
+ var tabDetailStyle = {
247
+ fontSize: "11px",
248
+ fontWeight: 500,
249
+ color: "var(--muted-foreground)"
250
+ };
251
+ var metricGridStyle = {
252
+ display: "grid",
253
+ gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
254
+ gap: "10px"
255
+ };
256
+ var metricCardStyle = {
257
+ borderRight: "1px solid var(--border)",
258
+ padding: "12px 18px",
259
+ background: "transparent",
260
+ display: "grid",
261
+ gap: "6px"
262
+ };
263
+ var metricHeaderStyle = {
264
+ display: "flex",
265
+ alignItems: "center",
266
+ gap: "8px",
267
+ color: "var(--muted-foreground)",
268
+ fontSize: "12px"
269
+ };
270
+ var metricIconStyle = {
271
+ width: "28px",
272
+ height: "28px",
273
+ borderRadius: "999px",
274
+ display: "inline-grid",
275
+ placeItems: "center",
276
+ fontSize: "13px",
277
+ fontWeight: 800
278
+ };
279
+ var productSectionStyle = {
280
+ border: "1px solid var(--border)",
281
+ borderRadius: "14px",
282
+ padding: "16px",
283
+ display: "grid",
284
+ gap: "14px",
285
+ background: "var(--background)"
286
+ };
287
+ var productEntryStyle = {
288
+ border: "1px solid var(--border)",
289
+ borderRadius: "12px",
290
+ padding: "14px",
291
+ display: "grid",
292
+ gap: "10px",
293
+ background: "var(--background)"
294
+ };
295
+ var productEntryEditorStyle = {
296
+ border: "1px solid color-mix(in oklab, var(--primary) 34%, var(--border))",
297
+ borderRadius: "12px",
298
+ padding: "14px",
299
+ display: "grid",
300
+ gap: "12px",
301
+ background: "color-mix(in oklab, var(--primary) 5%, var(--background))"
302
+ };
303
+ var compactPillStyle = {
304
+ border: "1px solid var(--border)",
305
+ borderRadius: "999px",
306
+ padding: "3px 8px",
307
+ background: "var(--muted)",
308
+ color: "var(--muted-foreground)",
309
+ fontSize: "12px"
310
+ };
311
+ var botIconStyle = {
312
+ width: "52px",
313
+ height: "52px",
314
+ borderRadius: "999px",
315
+ display: "grid",
316
+ placeItems: "center",
317
+ background: "var(--primary)",
318
+ color: "var(--primary-foreground)",
319
+ fontWeight: 900,
320
+ fontSize: "20px",
321
+ flex: "0 0 auto"
322
+ };
323
+ var wizardStepperStyle = {
324
+ display: "grid",
325
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
326
+ gap: "10px"
327
+ };
328
+ var checklistGridStyle = {
329
+ display: "grid",
330
+ gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
331
+ gap: "10px"
332
+ };
333
+ var flowGridStyle = {
334
+ display: "grid",
335
+ gridTemplateColumns: "repeat(auto-fit, minmax(190px, 1fr))",
336
+ gap: "10px"
337
+ };
338
+ var flowStepStyle = {
339
+ border: "1px solid var(--border)",
340
+ borderRadius: "8px",
341
+ padding: "10px",
342
+ background: "var(--background)",
343
+ minHeight: "74px"
344
+ };
345
+ var settingsListStyle = {
346
+ border: "1px solid var(--border)",
347
+ borderRadius: "12px",
348
+ overflow: "hidden",
349
+ background: "var(--background)"
350
+ };
351
+ var guideCardStyle = {
352
+ border: "1px solid var(--border)",
353
+ borderRadius: "8px",
354
+ padding: "12px",
355
+ display: "grid",
356
+ gap: "8px",
357
+ background: "var(--background)"
358
+ };
359
+ var codeStyle = {
360
+ display: "block",
361
+ border: "1px solid var(--border)",
362
+ borderRadius: "8px",
363
+ padding: "10px",
364
+ background: "var(--muted)",
365
+ color: "var(--foreground)",
366
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
367
+ fontSize: "12px",
368
+ whiteSpace: "pre-wrap",
369
+ overflowWrap: "anywhere"
370
+ };
371
+ var linkButtonStyle = {
372
+ ...buttonStyle,
373
+ display: "inline-flex",
374
+ alignItems: "center",
375
+ width: "fit-content",
376
+ textDecoration: "none"
377
+ };
378
+ var modalBackdropStyle = {
379
+ position: "fixed",
380
+ inset: 0,
381
+ zIndex: 1e3,
382
+ background: "rgba(0, 0, 0, 0.28)",
383
+ display: "grid",
384
+ placeItems: "center",
385
+ padding: "24px"
386
+ };
387
+ var modalPanelStyle = {
388
+ width: "min(720px, 100%)",
389
+ maxHeight: "min(760px, calc(100vh - 48px))",
390
+ overflow: "auto",
391
+ border: "1px solid var(--border)",
392
+ borderRadius: "14px",
393
+ background: "var(--background)",
394
+ boxShadow: "0 24px 80px rgba(0,0,0,0.24)",
395
+ padding: "18px",
396
+ display: "grid",
397
+ gap: "14px"
398
+ };
399
+ var floatingToastStyle = {
400
+ position: "fixed",
401
+ right: "24px",
402
+ bottom: "24px",
403
+ zIndex: 1100,
404
+ width: "min(420px, calc(100vw - 48px))",
405
+ border: "1px solid color-mix(in oklab, var(--primary) 45%, var(--border))",
406
+ borderRadius: "12px",
407
+ padding: "12px 14px",
408
+ background: "var(--background)",
409
+ boxShadow: "0 18px 44px rgba(0,0,0,0.18)"
410
+ };
411
+ var nextStepStyle = {
412
+ border: "1px solid color-mix(in oklab, var(--primary) 38%, var(--border))",
413
+ borderRadius: "12px",
414
+ padding: "14px",
415
+ background: "color-mix(in oklab, var(--primary) 5%, var(--background))",
416
+ display: "grid",
417
+ gap: "10px"
418
+ };
419
+ var heroCommandStyle = {
420
+ border: "1px solid var(--border)",
421
+ borderRadius: "14px",
422
+ padding: "16px",
423
+ display: "grid",
424
+ gap: "14px",
425
+ background: "var(--background)"
426
+ };
427
+ var setupStepStyle = {
428
+ border: "1px solid var(--border)",
429
+ borderRadius: "12px",
430
+ padding: "12px",
431
+ display: "grid",
432
+ gap: "8px",
433
+ minHeight: "118px",
434
+ background: "var(--background)"
435
+ };
436
+ var pipelineStyle = {
437
+ display: "grid",
438
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
439
+ gap: "8px"
440
+ };
441
+ var pipelineStepStyle = {
442
+ border: "1px solid var(--border)",
443
+ borderRadius: "12px",
444
+ padding: "12px",
445
+ display: "grid",
446
+ gap: "6px",
447
+ background: "var(--background)"
448
+ };
449
+ var settingsShellStyle = {
450
+ ...settingsListStyle,
451
+ display: "grid"
452
+ };
453
+ var cardStyle = {
454
+ display: "grid",
455
+ gap: "8px",
456
+ fontSize: "12px"
457
+ };
458
+ var rowStyle = {
459
+ display: "flex",
460
+ flexWrap: "wrap",
461
+ gap: "8px",
462
+ alignItems: "center"
463
+ };
464
+ var mutedRowStyle = {
465
+ ...rowStyle,
466
+ color: "var(--muted-foreground)",
467
+ fontSize: "12px"
468
+ };
469
+ var matchTypeLabels = {
470
+ chat: "\u53EA\u63A5\u67D0\u4E2A\u7FA4\u6216\u5355\u804A",
471
+ user: "\u53EA\u63A5\u67D0\u4E2A\u4EBA",
472
+ keyword: "\u6D88\u606F\u91CC\u6709\u5173\u952E\u8BCD",
473
+ regex: "\u9AD8\u7EA7\u89C4\u5219",
474
+ default: "\u5176\u4ED6\u6D88\u606F\u90FD\u63A5\u6536"
475
+ };
476
+ var replyModeLabels = {
477
+ none: "\u4E0D\u81EA\u52A8\u56DE\u590D",
478
+ message: "\u53D1\u4E00\u6761\u65B0\u6D88\u606F",
479
+ thread: "\u5728\u539F\u6D88\u606F\u7EBF\u7A0B\u91CC\u56DE\u590D"
480
+ };
481
+ function isLikelyFeishuInternalId(value) {
482
+ const trimmed = (value ?? "").trim();
483
+ return /^(oc|ou|om|on|od|of|cli)_[a-z0-9][a-z0-9_-]{5,}$/i.test(trimmed);
484
+ }
485
+ function issueSourceDisplayName(value) {
486
+ const trimmed = value?.trim();
487
+ if (!trimmed || isLikelyFeishuInternalId(trimmed)) return null;
488
+ return trimmed;
489
+ }
490
+ function issueSourceValue(value, fallback = "\u672A\u8BB0\u5F55") {
491
+ const trimmed = value?.trim();
492
+ return trimmed ? trimmed : fallback;
493
+ }
494
+ function issueReplyModeLabel(mode) {
495
+ if (mode === "none" || mode === "message" || mode === "thread") {
496
+ return replyModeLabels[mode];
497
+ }
498
+ return issueSourceValue(typeof mode === "string" ? mode : null);
499
+ }
500
+ function Badge({ children }) {
501
+ return /* @__PURE__ */ jsx("span", { style: {
502
+ border: "1px solid var(--border)",
503
+ borderRadius: "999px",
504
+ padding: "2px 8px",
505
+ opacity: 0.82
506
+ }, children });
507
+ }
508
+ function StatusBadge({ tone = "neutral", children }) {
509
+ const background = tone === "success" ? "color-mix(in oklab, var(--primary) 12%, var(--background))" : tone === "warning" ? "color-mix(in oklab, #f59e0b 14%, var(--background))" : "var(--muted)";
510
+ return /* @__PURE__ */ jsx("span", { style: {
511
+ border: "1px solid var(--border)",
512
+ borderRadius: "999px",
513
+ padding: "4px 10px",
514
+ fontSize: "12px",
515
+ fontWeight: 600,
516
+ background
517
+ }, children });
518
+ }
519
+ function CheckReport({ items, title = "\u8FDE\u63A5\u4F53\u68C0\u62A5\u544A" }) {
520
+ return /* @__PURE__ */ jsxs(
521
+ "div",
522
+ {
523
+ style: {
524
+ border: "1px solid var(--border)",
525
+ borderRadius: "12px",
526
+ padding: "12px",
527
+ display: "grid",
528
+ gap: "10px",
529
+ background: "var(--background)"
530
+ },
531
+ children: [
532
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: title }, "title"),
533
+ /* @__PURE__ */ jsx("div", { style: checklistGridStyle, children: items.map((item, index) => {
534
+ const marker = item.tone === "success" ? "\u2713" : item.tone === "warning" ? "!" : "\xD7";
535
+ const border = item.tone === "error" ? "1px solid var(--destructive)" : item.tone === "warning" ? "1px solid color-mix(in oklab, #f59e0b 55%, var(--border))" : "1px solid color-mix(in oklab, var(--primary) 35%, var(--border))";
536
+ return /* @__PURE__ */ jsxs(
537
+ "div",
538
+ {
539
+ style: {
540
+ border,
541
+ borderRadius: "8px",
542
+ padding: "10px",
543
+ display: "grid",
544
+ gap: "6px",
545
+ background: "var(--muted)"
546
+ },
547
+ children: [
548
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, gap: "6px" }, children: [
549
+ /* @__PURE__ */ jsx(
550
+ "strong",
551
+ {
552
+ style: {
553
+ width: "20px",
554
+ height: "20px",
555
+ borderRadius: "999px",
556
+ display: "inline-grid",
557
+ placeItems: "center",
558
+ border: "1px solid var(--border)",
559
+ fontSize: "12px"
560
+ },
561
+ children: marker
562
+ },
563
+ "marker"
564
+ ),
565
+ /* @__PURE__ */ jsx("strong", { children: item.title }, "title")
566
+ ] }, "head"),
567
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: item.detail }, "detail")
568
+ ]
569
+ },
570
+ `${item.title}-${index}`
571
+ );
572
+ }) }, "items")
573
+ ]
574
+ }
575
+ );
576
+ }
577
+ function dataString(data, key) {
578
+ const value = data?.[key];
579
+ return typeof value === "string" && value.trim() ? value.trim() : null;
580
+ }
581
+ function routeDiagnosticReasons(data) {
582
+ const diagnostics = data?.routeDiagnostics;
583
+ if (!Array.isArray(diagnostics)) return [];
584
+ return diagnostics.map((item) => {
585
+ if (typeof item !== "object" || item === null) return null;
586
+ const record = item;
587
+ const name = typeof record.routeName === "string" ? record.routeName : "\u5165\u53E3";
588
+ const reason = typeof record.reason === "string" ? record.reason : "";
589
+ return reason ? `${name}\uFF1A${reason}` : null;
590
+ }).filter((item) => Boolean(item)).slice(0, 3);
591
+ }
592
+ function recentRecordDetails(record) {
593
+ const data = record.data;
594
+ const details = [];
595
+ const connection = dataString(data, "connectionName") ?? (dataString(data, "connectionId") ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null);
596
+ const chat = dataString(data, "chatName") ?? (dataString(data, "chatId") ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null);
597
+ const sender = dataString(data, "senderName") ?? (dataString(data, "senderOpenId") ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null);
598
+ const route = dataString(data, "routeName") ?? (dataString(data, "routeId") ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null);
599
+ const agent = dataString(data, "targetAgentName");
600
+ const preview = dataString(data, "textPreview");
601
+ if (connection) details.push(`\u673A\u5668\u4EBA\uFF1A${connection}`);
602
+ if (route) details.push(`\u5165\u53E3\uFF1A${route}${agent ? ` \u2192 ${agent}` : ""}`);
603
+ if (chat) details.push(`\u4F1A\u8BDD\uFF1A${chat}`);
604
+ if (sender) details.push(`\u63D0\u51FA\u4EBA\uFF1A${sender}`);
605
+ if (preview) details.push(`\u6D88\u606F\uFF1A${preview}`);
606
+ details.push(...routeDiagnosticReasons(data));
607
+ return details;
608
+ }
609
+ function isInboundMessageRecord(record) {
610
+ if (dataString(record.data, "messageId")) return true;
611
+ return record.message.includes("\u98DE\u4E66\u5165\u53E3\u6D4B\u8BD5") || record.message.includes("\u5FEB\u6377\u6D4B\u8BD5\u56DE\u590D");
612
+ }
613
+ function friendlyMonitorMessage(message) {
614
+ const text = message?.trim();
615
+ if (!text) return "\u98DE\u4E66\u8FDE\u63A5\u5668\u8FD0\u884C\u6B63\u5E38";
616
+ if (text.includes("\u751F\u4EA7\u76D1\u63A7\u53D1\u73B0\u9700\u8981\u786E\u8BA4\u7684\u98CE\u9669\u9879")) return "\u9700\u8981\u786E\u8BA4\uFF1A\u6700\u8FD1\u6709\u98DE\u4E66\u6D88\u606F\u672A\u547D\u4E2D\u5165\u53E3";
617
+ if (text.includes("\u98DE\u4E66\u6D88\u606F\u76D1\u542C\u51FA\u73B0\u63D0\u9192")) return "\u6700\u8FD1\u6709\u98DE\u4E66\u6D88\u606F\u672A\u547D\u4E2D\u5165\u53E3";
618
+ return text.replace(/^生产监控[::]\s*/, "");
619
+ }
620
+ function connectorHealthLabel(data) {
621
+ if (!data?.connectionCount) return "\u5F85\u7ED1\u5B9A\u673A\u5668\u4EBA";
622
+ if (!data.eventSubscriberEnabled) return "\u5DF2\u914D\u7F6E\uFF0C\u672A\u76D1\u542C";
623
+ if (data.dryRunCli) return "\u76D1\u542C\u4E2D\uFF0C\u6D4B\u8BD5\u6A21\u5F0F";
624
+ return data.monitor?.health === "error" ? "\u9700\u8981\u5904\u7406" : data.monitor?.health === "warning" ? "\u53EF\u7528\uFF0C\u6709\u63D0\u9192" : "\u8FD0\u884C\u4E2D";
625
+ }
626
+ function RecentEventList({ records, emptyText = "\u8FD8\u6CA1\u6709\u6536\u5230\u98DE\u4E66\u6D88\u606F\u4E8B\u4EF6\u3002" }) {
627
+ if (records.length === 0) {
628
+ return /* @__PURE__ */ jsx("div", { style: helpStyle, children: emptyText });
629
+ }
630
+ return /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "8px" }, children: records.map((record, index) => {
631
+ const color = record.level === "error" ? "var(--destructive)" : record.level === "warning" ? "#b45309" : "var(--foreground)";
632
+ const details = recentRecordDetails(record);
633
+ return /* @__PURE__ */ jsxs(
634
+ "div",
635
+ {
636
+ style: {
637
+ border: "1px solid var(--border)",
638
+ borderRadius: "8px",
639
+ padding: "10px 12px",
640
+ display: "grid",
641
+ gap: "6px",
642
+ background: "var(--background)"
643
+ },
644
+ children: [
645
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, justifyContent: "space-between", gap: "12px" }, children: [
646
+ /* @__PURE__ */ jsx("strong", { style: { color }, children: record.message }, "message"),
647
+ /* @__PURE__ */ jsx("span", { style: helpStyle, children: record.createdAt }, "time")
648
+ ] }, "head"),
649
+ details.length ? /* @__PURE__ */ jsx("div", { style: { ...helpStyle, display: "grid", gap: "3px" }, children: details.map((detail, detailIndex) => /* @__PURE__ */ jsx("span", { children: detail }, `${detail}-${detailIndex}`)) }, "details") : null
650
+ ]
651
+ },
652
+ `${record.createdAt}-${index}`
653
+ );
654
+ }) });
655
+ }
656
+ function InlineCheckReport({ items, checkedAt }) {
657
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "8px", marginTop: "4px" }, children: [
658
+ checkedAt ? /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
659
+ "\u68C0\u67E5\u65F6\u95F4\uFF1A",
660
+ checkedAt
661
+ ] }, "checked-at") : null,
662
+ items.map((item, index) => {
663
+ const mark = item.tone === "success" ? "\u2713" : item.tone === "warning" ? "!" : "\xD7";
664
+ const color = item.tone === "error" ? "var(--destructive)" : item.tone === "warning" ? "#b45309" : "var(--foreground)";
665
+ return /* @__PURE__ */ jsxs(
666
+ "div",
667
+ {
668
+ style: {
669
+ display: "grid",
670
+ gridTemplateColumns: "22px minmax(0, 1fr)",
671
+ gap: "8px",
672
+ alignItems: "start",
673
+ padding: "8px 10px",
674
+ border: "1px solid var(--border)",
675
+ borderRadius: "8px",
676
+ background: "var(--muted)"
677
+ },
678
+ children: [
679
+ /* @__PURE__ */ jsx("strong", { style: { color }, children: mark }, "mark"),
680
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "2px" }, children: [
681
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: "13px", color }, children: item.title }, "title"),
682
+ /* @__PURE__ */ jsx("span", { style: helpStyle, children: item.detail }, "detail")
683
+ ] }, "copy")
684
+ ]
685
+ },
686
+ `${item.title}-${index}`
687
+ );
688
+ })
689
+ ] });
690
+ }
691
+ function ChatSearchControl(props) {
692
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "8px" }, children: [
693
+ /* @__PURE__ */ jsx(
694
+ "input",
695
+ {
696
+ style: inputStyle,
697
+ placeholder: "\u8F93\u5165\u7FA4\u540D\u6216\u5355\u804A\u540D\u79F0\uFF0C\u4F8B\u5982\u201C\u8001\u677F\u7FA4\u201D\u201C\u667A\u80FD\u4F53\u56E2\u961F\u201D",
698
+ value: props.query,
699
+ onChange: (event) => props.onQueryChange(event.target.value)
700
+ }
701
+ ),
702
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
703
+ "\u7528 ",
704
+ props.profileName || "\u5F53\u524D\u98DE\u4E66\u8D26\u53F7",
705
+ " \u641C\u7D22\u53EF\u89C1\u4F1A\u8BDD\u3002\u9009\u4E2D\u540E\u81EA\u52A8\u7ED1\u5B9A\u5230\u8FD9\u6761\u5165\u53E3\u3002"
706
+ ] }),
707
+ props.currentChatId ? /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
708
+ "\u5F53\u524D\u9009\u62E9\uFF1A",
709
+ props.currentChatName || "\u5DF2\u9009\u62E9\u4E00\u4E2A\u4F1A\u8BDD\uFF0C\u540D\u79F0\u5F85\u540C\u6B65"
710
+ ] }) : null,
711
+ props.loading ? /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6B63\u5728\u641C\u7D22\u98DE\u4E66\u4F1A\u8BDD..." }) : null,
712
+ props.error ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, color: "var(--destructive)" }, children: [
713
+ "\u641C\u7D22\u5931\u8D25\uFF1A",
714
+ props.error
715
+ ] }) : null,
716
+ !props.loading && !props.error && props.query && props.chats.length === 0 ? /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6CA1\u6709\u641C\u5230\u3002\u786E\u8BA4\u4F60\u6709\u6743\u9650\u770B\u5230\u8FD9\u4E2A\u7FA4\uFF0C\u6216\u5148\u628A\u98DE\u4E66\u673A\u5668\u4EBA\u52A0\u8FDB\u7FA4\u91CC\u3002" }) : null,
717
+ /* @__PURE__ */ jsx("div", { style: stepGridStyle, children: props.chats.map((chat) => /* @__PURE__ */ jsxs(
718
+ "button",
719
+ {
720
+ type: "button",
721
+ style: {
722
+ ...buttonStyle,
723
+ height: "auto",
724
+ minHeight: "54px",
725
+ padding: "10px 12px",
726
+ textAlign: "left",
727
+ justifyContent: "flex-start",
728
+ border: chat.chatId === props.currentChatId ? "1px solid var(--primary)" : buttonStyle.border
729
+ },
730
+ onClick: () => props.onSelect(chat),
731
+ children: [
732
+ /* @__PURE__ */ jsx("strong", { style: { display: "block" }, children: chat.name }),
733
+ /* @__PURE__ */ jsx("span", { style: { ...helpStyle, display: "block" }, children: chat.description || (chat.external ? "\u5916\u90E8\u7FA4" : "\u5185\u90E8\u4F1A\u8BDD") })
734
+ ]
735
+ },
736
+ chat.chatId
737
+ )) })
738
+ ] });
739
+ }
740
+ function UserSearchControl(props) {
741
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "8px" }, children: [
742
+ /* @__PURE__ */ jsx(
743
+ "input",
744
+ {
745
+ style: inputStyle,
746
+ placeholder: "\u8F93\u5165\u59D3\u540D\u3001\u90AE\u7BB1\u6216\u5DE5\u53F7\uFF0C\u4F8B\u5982\u201C\u5F20\u6D2A\u4E39\u201D",
747
+ value: props.query,
748
+ onChange: (event) => props.onQueryChange(event.target.value)
749
+ }
750
+ ),
751
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
752
+ "\u7528 ",
753
+ props.profileName || "\u5F53\u524D\u98DE\u4E66\u8D26\u53F7",
754
+ " \u641C\u7D22\u901A\u8BAF\u5F55\u3002\u9009\u4E2D\u540E\u81EA\u52A8\u7ED1\u5B9A\u5230\u8FD9\u6761\u5165\u53E3\u3002"
755
+ ] }),
756
+ props.currentUserOpenId ? /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
757
+ "\u5F53\u524D\u9009\u62E9\uFF1A",
758
+ props.currentUserName || "\u5DF2\u9009\u62E9\u4E00\u4E2A\u8054\u7CFB\u4EBA\uFF0C\u540D\u79F0\u5F85\u540C\u6B65"
759
+ ] }) : null,
760
+ props.loading ? /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6B63\u5728\u641C\u7D22\u98DE\u4E66\u8054\u7CFB\u4EBA..." }) : null,
761
+ props.error ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, color: "var(--destructive)" }, children: [
762
+ "\u641C\u7D22\u5931\u8D25\uFF1A",
763
+ props.error
764
+ ] }) : null,
765
+ !props.loading && !props.error && props.query && props.users.length === 0 ? /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6CA1\u6709\u641C\u5230\u3002\u786E\u8BA4\u98DE\u4E66\u5E94\u7528\u53EF\u89C1\u8303\u56F4\u548C\u901A\u8BAF\u5F55\u6743\u9650\u3002" }) : null,
766
+ /* @__PURE__ */ jsx("div", { style: stepGridStyle, children: props.users.map((user) => /* @__PURE__ */ jsxs(
767
+ "button",
768
+ {
769
+ type: "button",
770
+ style: {
771
+ ...buttonStyle,
772
+ height: "auto",
773
+ minHeight: "54px",
774
+ padding: "10px 12px",
775
+ textAlign: "left",
776
+ justifyContent: "flex-start",
777
+ border: user.openId === props.currentUserOpenId ? "1px solid var(--primary)" : buttonStyle.border
778
+ },
779
+ onClick: () => props.onSelect(user),
780
+ children: [
781
+ /* @__PURE__ */ jsx("strong", { style: { display: "block" }, children: user.name }),
782
+ /* @__PURE__ */ jsx("span", { style: { ...helpStyle, display: "block" }, children: user.userId ? `\u5DE5\u53F7\uFF1A${user.userId}` : user.departmentIds?.length ? "\u5DF2\u5339\u914D\u901A\u8BAF\u5F55\u90E8\u95E8" : "\u901A\u8BAF\u5F55\u7528\u6237" })
783
+ ]
784
+ },
785
+ user.openId
786
+ )) })
787
+ ] });
788
+ }
789
+ function StatusDot({ done }) {
790
+ return /* @__PURE__ */ jsx(
791
+ "span",
792
+ {
793
+ "aria-hidden": "true",
794
+ style: {
795
+ width: "18px",
796
+ height: "18px",
797
+ borderRadius: "999px",
798
+ display: "inline-flex",
799
+ alignItems: "center",
800
+ justifyContent: "center",
801
+ flex: "0 0 auto",
802
+ border: "1px solid var(--border)",
803
+ background: done ? "var(--primary)" : "var(--background)",
804
+ color: done ? "var(--primary-foreground)" : "var(--muted-foreground)",
805
+ fontSize: "12px",
806
+ lineHeight: 1
807
+ },
808
+ children: done ? "\u2713" : "\u2022"
809
+ }
810
+ );
811
+ }
812
+ function ChecklistItem({ done, title, detail }) {
813
+ return /* @__PURE__ */ jsxs(
814
+ "div",
815
+ {
816
+ style: {
817
+ border: "1px solid var(--border)",
818
+ borderRadius: "8px",
819
+ padding: "10px",
820
+ display: "flex",
821
+ alignItems: "flex-start",
822
+ gap: "8px",
823
+ background: done ? "color-mix(in oklab, var(--primary) 6%, var(--background))" : "var(--background)"
824
+ },
825
+ children: [
826
+ /* @__PURE__ */ jsx(StatusDot, { done }, "dot"),
827
+ /* @__PURE__ */ jsxs("div", { children: [
828
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700, fontSize: "13px" }, children: title }, "title"),
829
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: detail }, "detail")
830
+ ] }, "body")
831
+ ]
832
+ }
833
+ );
834
+ }
835
+ function FlowStep({ title, value, detail }) {
836
+ return /* @__PURE__ */ jsxs("div", { style: flowStepStyle, children: [
837
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginBottom: "6px" }, children: title }, "title"),
838
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700, lineHeight: 1.35 }, children: value }, "value"),
839
+ detail ? /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: detail }, "detail") : null
840
+ ] });
841
+ }
842
+ function SetupStep({
843
+ index,
844
+ done,
845
+ title,
846
+ detail,
847
+ action
848
+ }) {
849
+ return /* @__PURE__ */ jsxs(
850
+ "div",
851
+ {
852
+ style: {
853
+ ...setupStepStyle,
854
+ border: done ? "1px solid color-mix(in oklab, var(--primary) 34%, var(--border))" : setupStepStyle.border,
855
+ background: done ? "color-mix(in oklab, var(--primary) 5%, var(--background))" : setupStepStyle.background
856
+ },
857
+ children: [
858
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, justifyContent: "space-between" }, children: [
859
+ /* @__PURE__ */ jsx("span", { style: { ...compactPillStyle, color: done ? "var(--foreground)" : "var(--muted-foreground)" }, children: done ? "\u5B8C\u6210" : `\u7B2C ${index} \u6B65` }, "number"),
860
+ /* @__PURE__ */ jsx(StatusDot, { done }, "dot")
861
+ ] }, "head"),
862
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "15px" }, children: title }, "title"),
863
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: detail }, "detail"),
864
+ action ? /* @__PURE__ */ jsx("div", { style: { marginTop: "auto" }, children: action }, "action") : null
865
+ ]
866
+ }
867
+ );
868
+ }
869
+ function PipelineStep({
870
+ done,
871
+ label,
872
+ detail
873
+ }) {
874
+ return /* @__PURE__ */ jsxs(
875
+ "div",
876
+ {
877
+ style: {
878
+ ...pipelineStepStyle,
879
+ border: done ? "1px solid color-mix(in oklab, var(--primary) 36%, var(--border))" : pipelineStepStyle.border
880
+ },
881
+ children: [
882
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
883
+ /* @__PURE__ */ jsx(StatusDot, { done }, "dot"),
884
+ /* @__PURE__ */ jsx("strong", { children: label }, "label")
885
+ ] }, "head"),
886
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: detail }, "detail")
887
+ ]
888
+ }
889
+ );
890
+ }
891
+ function Field({ label, help, children }) {
892
+ return /* @__PURE__ */ jsxs("div", { style: fieldStyle, children: [
893
+ /* @__PURE__ */ jsx("span", { style: labelStyle, children: label }, "label"),
894
+ /* @__PURE__ */ jsx("span", { style: { display: "contents" }, children: Children.toArray(children) }, "control"),
895
+ help ? /* @__PURE__ */ jsx("span", { style: helpStyle, children: help }, "help") : null
896
+ ] });
897
+ }
898
+ function ToggleField({
899
+ label,
900
+ help,
901
+ checked,
902
+ onChange
903
+ }) {
904
+ return /* @__PURE__ */ jsxs("div", { style: fieldStyle, children: [
905
+ /* @__PURE__ */ jsxs("div", { style: actionBarStyle, children: [
906
+ /* @__PURE__ */ jsx("span", { style: labelStyle, children: label }, "label"),
907
+ /* @__PURE__ */ jsx(
908
+ "button",
909
+ {
910
+ type: "button",
911
+ "aria-pressed": checked,
912
+ onClick: () => onChange(!checked),
913
+ style: {
914
+ width: "44px",
915
+ height: "24px",
916
+ borderRadius: "999px",
917
+ border: "1px solid var(--border)",
918
+ padding: "2px",
919
+ background: checked ? "var(--primary)" : "var(--muted)",
920
+ cursor: "pointer",
921
+ display: "flex",
922
+ justifyContent: checked ? "flex-end" : "flex-start",
923
+ alignItems: "center"
924
+ },
925
+ children: /* @__PURE__ */ jsx("span", { style: {
926
+ width: "18px",
927
+ height: "18px",
928
+ borderRadius: "999px",
929
+ background: checked ? "var(--primary-foreground)" : "var(--background)",
930
+ boxShadow: "0 1px 2px rgba(0,0,0,0.16)"
931
+ } }, "knob")
932
+ },
933
+ "switch"
934
+ )
935
+ ] }, "row"),
936
+ help ? /* @__PURE__ */ jsx("span", { style: helpStyle, children: help }, "help") : null
937
+ ] });
938
+ }
939
+ function NoticeBanner({ notice, meta }) {
940
+ const border = notice.tone === "error" ? "1px solid var(--destructive)" : notice.tone === "success" ? "1px solid color-mix(in oklab, var(--primary) 45%, var(--border))" : "1px solid var(--border)";
941
+ const background = notice.tone === "error" ? "color-mix(in oklab, var(--destructive) 8%, var(--background))" : notice.tone === "success" ? "color-mix(in oklab, var(--primary) 8%, var(--background))" : "var(--background)";
942
+ return /* @__PURE__ */ jsxs(
943
+ "div",
944
+ {
945
+ role: "status",
946
+ "aria-live": "polite",
947
+ style: {
948
+ border,
949
+ borderRadius: "8px",
950
+ padding: "10px 12px",
951
+ background,
952
+ display: "grid",
953
+ gap: "4px"
954
+ },
955
+ children: [
956
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700 }, children: notice.text }, "text"),
957
+ meta ? /* @__PURE__ */ jsx("div", { style: helpStyle, children: meta }, "meta") : null
958
+ ]
959
+ }
960
+ );
961
+ }
962
+ function normalizeText(value) {
963
+ return (value ?? "").trim().toLowerCase();
964
+ }
965
+ function normalizeMentionLabel(value) {
966
+ return normalizeText(value).replace(/^@+/, "").replace(/\s+/g, "");
967
+ }
968
+ function splitBotAliases(value) {
969
+ const values = Array.isArray(value) ? value : typeof value === "string" ? value.split(/[,,、\n]/g) : [];
970
+ return [...new Set(values.filter((item) => typeof item === "string").map((item) => item.trim().replace(/^@+/, "")).filter(Boolean))];
971
+ }
972
+ function isPlaceholderBotName(value) {
973
+ const normalized = normalizeText(value);
974
+ return !normalized || normalized === "\u98DE\u4E66\u673A\u5668\u4EBA" || normalized === "\u98DE\u4E66\u5E94\u7528" || normalized.startsWith("cli_") || normalized.includes("\u98DE\u4E66\u5E94\u7528") || /^[0-9a-f-]{12,}$/.test(normalized);
975
+ }
976
+ function connectionAliasList(connection) {
977
+ return splitBotAliases(connection?.botAliases);
978
+ }
979
+ function formatBotAliases(connection) {
980
+ return connectionAliasList(connection).join("\u3001");
981
+ }
982
+ function normalizeUiConfig(input) {
983
+ const source = input ?? {};
984
+ return {
985
+ ...DEFAULT_CONFIG,
986
+ ...source,
987
+ connections: Array.isArray(source.connections) ? source.connections.map((connection) => ({
988
+ ...connection,
989
+ botAliases: splitBotAliases(connection.botAliases)
990
+ })) : [],
991
+ routes: Array.isArray(source.routes) ? source.routes : [],
992
+ baseSinks: Array.isArray(source.baseSinks) ? source.baseSinks : []
993
+ };
994
+ }
995
+ function portableConfig(input) {
996
+ const secretKeys = /* @__PURE__ */ new Set([
997
+ "appSecret",
998
+ "app_secret",
999
+ "clientSecret",
1000
+ "client_secret",
1001
+ "tenantAccessToken",
1002
+ "userAccessToken",
1003
+ "accessToken",
1004
+ "refreshToken",
1005
+ "verificationToken",
1006
+ "encryptKey"
1007
+ ]);
1008
+ function sanitize(value) {
1009
+ if (Array.isArray(value)) return value.map((item) => sanitize(item));
1010
+ if (!value || typeof value !== "object") return value;
1011
+ const next = {};
1012
+ Object.entries(value).forEach(([key, nested]) => {
1013
+ if (secretKeys.has(key)) return;
1014
+ next[key] = sanitize(nested);
1015
+ });
1016
+ return next;
1017
+ }
1018
+ return normalizeUiConfig(sanitize(input));
1019
+ }
1020
+ function readableError(error) {
1021
+ if (error instanceof Error) return readableError(error.message);
1022
+ if (typeof error === "string") {
1023
+ const trimmed = error.trim();
1024
+ if (trimmed.startsWith("{")) {
1025
+ try {
1026
+ const parsed = JSON.parse(trimmed);
1027
+ const errorRecord = typeof parsed.error === "object" && parsed.error !== null ? parsed.error : null;
1028
+ const message = typeof errorRecord?.message === "string" ? errorRecord.message : typeof parsed.error === "string" ? parsed.error : typeof parsed.message === "string" ? parsed.message : trimmed;
1029
+ const hint = typeof errorRecord?.hint === "string" ? errorRecord.hint : "";
1030
+ return hint ? `${message}\u3002${hint}` : message;
1031
+ } catch {
1032
+ return trimmed;
1033
+ }
1034
+ }
1035
+ return trimmed;
1036
+ }
1037
+ if (typeof error === "object" && error !== null) {
1038
+ const record = error;
1039
+ const errorRecord = typeof record.error === "object" && record.error !== null ? record.error : null;
1040
+ if (typeof errorRecord?.message === "string") {
1041
+ const hint = typeof errorRecord.hint === "string" ? errorRecord.hint : "";
1042
+ return hint ? `${errorRecord.message}\u3002${hint}` : errorRecord.message;
1043
+ }
1044
+ if (typeof record.error === "string") {
1045
+ return record.error;
1046
+ }
1047
+ if (typeof record.message === "string") return readableError(record.message);
1048
+ }
1049
+ return "\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002";
1050
+ }
1051
+ function companyLabel(company) {
1052
+ return company.issuePrefix ? `${company.name}\uFF08${company.issuePrefix}\uFF09` : company.name;
1053
+ }
1054
+ function agentLabel(agent) {
1055
+ return agent.title ? `${agent.name} - ${agent.title}` : agent.name;
1056
+ }
1057
+ function profileLabel(profile) {
1058
+ const parts = [profileDisplayName(profile)];
1059
+ parts.push(profileAuthLabel(profile));
1060
+ if (profile.appId) parts.push(`App ID\uFF1A${maskTechnicalId(profile.appId)}`);
1061
+ if (profile.name && profile.name !== profile.appId) parts.push(`\u914D\u7F6E\uFF1A${profile.name}`);
1062
+ if (profile.active) parts.push("\u5F53\u524D\u9ED8\u8BA4");
1063
+ return parts.join(" \xB7 ");
1064
+ }
1065
+ function maskTechnicalId(value) {
1066
+ const trimmed = value?.trim();
1067
+ if (!trimmed) return "\u672A\u8FD4\u56DE";
1068
+ if (trimmed.length <= 14) return trimmed;
1069
+ return `${trimmed.slice(0, 8)}\u2026${trimmed.slice(-4)}`;
1070
+ }
1071
+ function profileAuthLabel(profile) {
1072
+ if (profile?.user) return `\u4E2A\u4EBA\u6388\u6743\uFF1A${profile.user}`;
1073
+ return "\u673A\u5668\u4EBA\u8EAB\u4EFD\uFF1A\u5DF2\u7528\u4E8E\u6536\u53D1\u6D88\u606F";
1074
+ }
1075
+ function profileAuthDetail(profile) {
1076
+ if (profile?.user) return "\u5DF2\u7ECF\u5B8C\u6210\u7528\u6237\u6388\u6743\uFF0C\u53EF\u6309\u6388\u6743\u8303\u56F4\u8BBF\u95EE\u4E2A\u4EBA\u98DE\u4E66\u8D44\u6E90\u3002";
1077
+ return "\u8FD9\u662F\u6B63\u5E38\u72B6\u6001\uFF1A\u6536\u6D88\u606F\u3001\u56DE\u6D88\u606F\u3001\u5199\u591A\u7EF4\u8868\u683C\u8D70\u673A\u5668\u4EBA\u8EAB\u4EFD\uFF0C\u4E0D\u9700\u8981\u4E2A\u4EBA\u6388\u6743\u3002\u53EA\u6709\u8BBF\u95EE\u4E2A\u4EBA\u6587\u6863\u3001\u65E5\u5386\u3001\u90AE\u7BB1\u65F6\u624D\u5355\u72EC\u6388\u6743\u3002";
1078
+ }
1079
+ function missingProfileHelp(connection) {
1080
+ const label = connection?.name || connection?.profileName || "\u8FD9\u4E2A\u673A\u5668\u4EBA";
1081
+ return `\u5F53\u524D\u9875\u9762\u8FD8\u4FDD\u7559\u201C${label}\u201D\uFF0C\u4F46\u8FD9\u53F0\u673A\u5668/\u670D\u52A1\u5668\u6CA1\u6709\u8BFB\u5230\u5BF9\u5E94\u7684 lark-cli \u6388\u6743\u3002\u5148\u70B9\u201C\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868\u201D\uFF1B\u5982\u679C\u8FD8\u6CA1\u6709\uFF0C\u5C31\u70B9\u201C\u91CD\u65B0\u7ED1\u5B9A\u201D\u91CD\u65B0\u8D70\u4E00\u6B21\u98DE\u4E66\u6388\u6743\u3002\u4E91\u670D\u52A1\u5668\u90E8\u7F72\u65F6\uFF0C\u672C\u5730\u7ED1\u5B9A\u4E0D\u4F1A\u81EA\u52A8\u5E26\u8FC7\u53BB\uFF0C\u670D\u52A1\u5668\u4E0A\u4E5F\u8981\u7ED1\u5B9A\u6216\u6CE8\u5165\u540C\u4E00\u5957\u5BC6\u94A5\u3002`;
1082
+ }
1083
+ function missingBotNameHelp(connection) {
1084
+ const aliases = formatBotAliases(connection);
1085
+ if (aliases) return `\u98DE\u4E66\u6CA1\u6709\u8FD4\u56DE\u5B98\u65B9\u673A\u5668\u4EBA\u540D\uFF0C\u5F53\u524D\u4F1A\u7528\u4F60\u586B\u5199\u7684 @ \u540D\u79F0\u201C${aliases}\u201D\u5224\u65AD\u6D88\u606F\u662F\u4E0D\u662F\u53D1\u7ED9\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002`;
1086
+ return "\u6CA1\u6709\u4ECE\u98DE\u4E66\u8BFB\u53D6\u5230\u673A\u5668\u4EBA\u663E\u793A\u540D\u3002\u8BF7\u586B\u5199\u98DE\u4E66\u91CC @ \u5B83\u65F6\u770B\u5230\u7684\u540D\u5B57\uFF0C\u4F8B\u5982\u201C\u5C0F\u9510\u201D\u3002\u5426\u5219\u591A\u4E2A\u673A\u5668\u4EBA\u5728\u540C\u4E00\u4E2A\u7FA4\u91CC\u65F6\uFF0C@\u5C0F\u9510/@\u9510\u601D \u53EF\u80FD\u88AB\u9519\u8BEF\u63A5\u8D70\u3002";
1087
+ }
1088
+ function profileDisplayName(profile) {
1089
+ if (!profile) return "\u98DE\u4E66\u5E94\u7528";
1090
+ return profile.botName || (profile.user ? `\u98DE\u4E66\u5E94\u7528\uFF08${profile.user}\uFF09` : profile.name || "\u98DE\u4E66\u5E94\u7528");
1091
+ }
1092
+ function primaryMentionName(connection, profile) {
1093
+ const realBotName = profile?.botName?.trim();
1094
+ if (realBotName) return realBotName;
1095
+ const alias = connectionAliasList(connection)[0];
1096
+ if (alias) return alias;
1097
+ const connectionName = connection?.name?.trim();
1098
+ if (connectionName && !isPlaceholderBotName(connectionName)) return connectionName;
1099
+ return "\u673A\u5668\u4EBA";
1100
+ }
1101
+ function appLabel(connection, profile) {
1102
+ const realBotName = profile?.botName ?? null;
1103
+ const alias = connectionAliasList(connection)[0];
1104
+ const connectionName = connection?.name?.trim();
1105
+ if (realBotName) return realBotName;
1106
+ if (alias) return alias;
1107
+ if (connectionName) return connectionName;
1108
+ if (profile?.user) return `\u98DE\u4E66\u5E94\u7528\uFF08${profile.user}\uFF09`;
1109
+ if (profile?.name) return profile.name;
1110
+ return "\u98DE\u4E66\u5E94\u7528";
1111
+ }
1112
+ function routeTitle(route, index) {
1113
+ const explicitName = route.name?.trim();
1114
+ if (explicitName && !isLikelyInternalRouteName(explicitName)) return explicitName;
1115
+ const described = describeRouteForHumans(route);
1116
+ if (described && described !== "\u9ED8\u8BA4\u5165\u53E3") return described;
1117
+ if (route.matchType === "regex") {
1118
+ if (route.regex?.includes("\u9510\u601D") && route.regex?.includes("paperclip")) {
1119
+ return route.targetAgentName?.trim() ? `\u9AD8\u7EA7\u5165\u53E3\uFF1A\u5173\u952E\u8BCD\u201C\u9510\u601D / paperclip\u201D \u2192 ${route.targetAgentName.trim()}` : "\u9AD8\u7EA7\u5165\u53E3\uFF1A\u5173\u952E\u8BCD\u201C\u9510\u601D / paperclip\u201D";
1120
+ }
1121
+ }
1122
+ if (route.matchType === "default") return "\u5176\u4ED6\u672A\u5339\u914D\u6D88\u606F";
1123
+ return `\u63A5\u6536\u89C4\u5219 ${index + 1}`;
1124
+ }
1125
+ function routeSourceLabel(route) {
1126
+ if (route.matchType === "chat") return route.chatName ? `\u98DE\u4E66\u4F1A\u8BDD\u201C${route.chatName}\u201D` : route.chatId ? "\u6307\u5B9A\u4F1A\u8BDD\uFF08\u540D\u79F0\u5F85\u540C\u6B65\uFF09" : "\u6307\u5B9A\u7FA4\u6216\u5355\u804A";
1127
+ if (route.matchType === "user") return route.userName ? `\u6307\u5B9A\u4EBA\u5458\u201C${route.userName}\u201D` : route.userOpenId ? "\u6307\u5B9A\u4EBA\u5458\uFF08\u540D\u79F0\u5F85\u540C\u6B65\uFF09" : "\u6307\u5B9A\u53D1\u6D88\u606F\u4EBA";
1128
+ if (route.matchType === "keyword") return route.keyword ? `\u6D88\u606F\u5305\u542B\u201C${route.keyword}\u201D` : "\u6D88\u606F\u5305\u542B\u5173\u952E\u8BCD";
1129
+ if (route.matchType === "regex") return route.regex ? "\u6309\u9AD8\u7EA7\u89C4\u5219\u5339\u914D" : "\u9AD8\u7EA7\u89C4\u5219";
1130
+ return "\u672A\u88AB\u5176\u4ED6\u89C4\u5219\u63A5\u8D70\u7684\u6D88\u606F";
1131
+ }
1132
+ function routeTargetLabel(company, agent) {
1133
+ if (!company && !agent) return "\u8FD8\u6CA1\u9009\u62E9";
1134
+ if (company && agent) return `${agentLabel(agent)}\uFF08${companyLabel(company)}\uFF09`;
1135
+ if (company) return `${companyLabel(company)}\u91CC\u7684\u667A\u80FD\u4F53`;
1136
+ return agent ? agentLabel(agent) : "\u8FD8\u6CA1\u9009\u62E9";
1137
+ }
1138
+ function feishuTriggerText(route, connection, profile) {
1139
+ const botName = primaryMentionName(connection, profile);
1140
+ const mention = `@${botName}`;
1141
+ if (!route) return `${mention} paperclip`;
1142
+ if (route.matchType === "keyword") {
1143
+ const keyword = route.keyword?.trim() || "paperclip";
1144
+ return normalizeMentionLabel(keyword) === normalizeMentionLabel(botName) ? mention : `${mention} ${keyword}`;
1145
+ }
1146
+ if (route.matchType === "regex" && route.regex?.includes("paperclip")) return `${mention} paperclip`;
1147
+ return mention;
1148
+ }
1149
+ function feishuSmokeText(route, connection, profile) {
1150
+ return `${feishuTriggerText(route, connection, profile)} \u53EA\u56DE\u590D ok`;
1151
+ }
1152
+ function feishuTaskTestText(route, connection, profile) {
1153
+ const trigger = feishuTriggerText(route, connection, profile);
1154
+ return `${trigger} \u8BF7\u521B\u5EFA\u4E00\u4E2A paperclip \u6D4B\u8BD5\u4EFB\u52A1\uFF0C\u5B8C\u6210\u540E\u56DE\u590D\u6211\uFF1B\u5982\u679C\u6211\u5E26\u4E86\u56FE\u7247\u6216\u6587\u4EF6\uFF0C\u4E5F\u8BF7\u4E00\u8D77\u5904\u7406\u3002`;
1155
+ }
1156
+ function deploymentHint() {
1157
+ const host = typeof window !== "undefined" ? window.location.hostname : "";
1158
+ if (host === "localhost" || host === "127.0.0.1") {
1159
+ return "\u5F53\u524D\u662F\u672C\u5730\u6D4B\u8BD5\uFF1A\u8FD9\u4E2A\u98DE\u4E66\u5E94\u7528\u7ED1\u5728\u8FD9\u53F0 Mac \u4E0A\u3002\u672A\u6765\u90E8\u7F72\u5230\u4E91\u670D\u52A1\u5668\u540E\uFF0C\u8981\u628A\u540C\u4E00\u4E2A\u98DE\u4E66\u5E94\u7528\u7ED1\u5B9A\u5230\u670D\u52A1\u5668\u4E0A\u3002";
1160
+ }
1161
+ return "\u5F53\u524D\u662F\u670D\u52A1\u5668\u73AF\u5883\uFF1A\u98DE\u4E66\u5E94\u7528\u914D\u7F6E\u6765\u81EA Paperclip \u670D\u52A1\u5668\uFF0C\u4E0D\u4F1A\u8BFB\u53D6\u7528\u6237\u7535\u8111\u3002";
1162
+ }
1163
+ function isLocalRuntime() {
1164
+ const host = typeof window !== "undefined" ? window.location.hostname : "";
1165
+ return host === "localhost" || host === "127.0.0.1";
1166
+ }
1167
+ function shellQuote(value) {
1168
+ return `'${value.replace(/'/g, "'\\''")}'`;
1169
+ }
1170
+ function serverProfileName(connection) {
1171
+ return connection?.profileName?.trim() || "paperclip-feishu-bot";
1172
+ }
1173
+ function buildServerDeployCommands(connection) {
1174
+ const profileName = serverProfileName(connection);
1175
+ const appId = connection?.appId?.trim() || "<App ID>";
1176
+ return [
1177
+ "# 1. \u5728 Paperclip \u670D\u52A1\u5668\u4E0A\u786E\u8BA4 lark-cli \u53EF\u7528\uFF08\u63D2\u4EF6\u5305\u4F1A\u81EA\u5E26 CLI\uFF1B\u8FD9\u91CC\u7528\u4E8E\u4EBA\u5DE5\u4F53\u68C0\uFF09",
1178
+ "lark-cli --version",
1179
+ "lark-cli doctor",
1180
+ "",
1181
+ "# 2. \u5728\u670D\u52A1\u5668\u4E0A\u7ED1\u5B9A\u540C\u4E00\u4E2A\u98DE\u4E66\u5E94\u7528\u3002App Secret \u4E0D\u8981\u53D1\u5230\u804A\u5929\u6216\u622A\u56FE\u91CC\u3002",
1182
+ `lark-cli config init --new --name ${shellQuote(profileName)} --brand feishu --lang zh`,
1183
+ `printf '<App Secret>' | lark-cli profile add --name ${shellQuote(profileName)} --app-id ${shellQuote(appId)} --brand feishu --app-secret-stdin --use`,
1184
+ "",
1185
+ "# 3. \u56DE\u5230 Paperclip \u98DE\u4E66\u8FDE\u63A5\u5668\u9875\u9762\uFF0C\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868\uFF0C\u786E\u8BA4\u540C\u540D profile \u51FA\u73B0\u540E\u518D\u4FDD\u5B58\u914D\u7F6E\u3002"
1186
+ ].join("\n");
1187
+ }
1188
+ function connectionOptionNodes(connections, prefix, defaultLabel = "\u9ED8\u8BA4\u7B2C\u4E00\u4E2A\u53EF\u7528\u673A\u5668\u4EBA", profiles = []) {
1189
+ return Children.toArray([
1190
+ /* @__PURE__ */ jsx("option", { value: "", children: defaultLabel }, `${prefix}-default`),
1191
+ ...connections.map((connection, optionIndex) => {
1192
+ const profile = profiles.find((item) => item.name === connection.profileName) ?? null;
1193
+ return /* @__PURE__ */ jsx("option", { value: connection.id, children: appLabel(connection, profile) }, `${prefix}-connection-${optionIndex}-${connection.id}`);
1194
+ })
1195
+ ]);
1196
+ }
1197
+ function companyOptionNodes(companies, prefix) {
1198
+ return Children.toArray([
1199
+ /* @__PURE__ */ jsx("option", { value: "", children: "\u8BF7\u9009\u62E9\u516C\u53F8" }, `${prefix}-empty-company`),
1200
+ ...companies.map((item, optionIndex) => /* @__PURE__ */ jsx("option", { value: item.id, children: companyLabel(item) }, `${prefix}-company-${optionIndex}-${item.id}`))
1201
+ ]);
1202
+ }
1203
+ function agentOptionNodes(agents, prefix) {
1204
+ return Children.toArray([
1205
+ /* @__PURE__ */ jsx("option", { value: "", children: "\u8BF7\u9009\u62E9\u667A\u80FD\u4F53" }, `${prefix}-empty-agent`),
1206
+ ...agents.map((item, optionIndex) => /* @__PURE__ */ jsx("option", { value: item.id, children: agentLabel(item) }, `${prefix}-agent-${optionIndex}-${item.id}`))
1207
+ ]);
1208
+ }
1209
+ function resolveCompany(route, companies) {
1210
+ const id = normalizeText(route.companyId);
1211
+ if (id) {
1212
+ const byId = companies.find((company) => normalizeText(company.id) === id);
1213
+ if (byId) return byId;
1214
+ }
1215
+ const ref = normalizeText(route.companyRef);
1216
+ if (!ref) return null;
1217
+ return companies.find(
1218
+ (company) => normalizeText(company.id) === ref || normalizeText(company.name) === ref || normalizeText(company.issuePrefix) === ref
1219
+ ) ?? null;
1220
+ }
1221
+ function resolveAgent(route, company) {
1222
+ if (!company) return null;
1223
+ const id = normalizeText(route.targetAgentId);
1224
+ if (id) {
1225
+ const byId = company.agents.find((agent) => normalizeText(agent.id) === id);
1226
+ if (byId) return byId;
1227
+ }
1228
+ const ref = normalizeText(route.targetAgentRef ?? route.targetAgentName);
1229
+ if (!ref) return null;
1230
+ return company.agents.find(
1231
+ (agent) => normalizeText(agent.id) === ref || normalizeText(agent.name) === ref || normalizeText(agent.title) === ref || normalizeText(agent.urlKey) === ref
1232
+ ) ?? null;
1233
+ }
1234
+ async function hostFetchJson(path, init) {
1235
+ const response = await fetch(path, {
1236
+ credentials: "include",
1237
+ headers: {
1238
+ "content-type": "application/json",
1239
+ ...init?.headers ?? {}
1240
+ },
1241
+ ...init
1242
+ });
1243
+ if (!response.ok) {
1244
+ const text = await response.text();
1245
+ throw new Error(readableError(text || `Request failed: ${response.status}`));
1246
+ }
1247
+ return await response.json();
1248
+ }
1249
+ function useSettingsConfig(pluginApiId) {
1250
+ const [configJson, setConfigJson] = useState(() => normalizeUiConfig({}));
1251
+ const [loading, setLoading] = useState(true);
1252
+ const [saving, setSaving] = useState(false);
1253
+ const [error, setError] = useState(null);
1254
+ useEffect(() => {
1255
+ let cancelled = false;
1256
+ setLoading(true);
1257
+ hostFetchJson(`/api/plugins/${encodeURIComponent(pluginApiId)}/config`).then((result) => {
1258
+ if (cancelled) return;
1259
+ setConfigJson(normalizeUiConfig(result?.configJson ?? {}));
1260
+ setError(null);
1261
+ }).catch((nextError) => {
1262
+ if (cancelled) return;
1263
+ setError(readableError(nextError));
1264
+ }).finally(() => {
1265
+ if (!cancelled) setLoading(false);
1266
+ });
1267
+ return () => {
1268
+ cancelled = true;
1269
+ };
1270
+ }, [pluginApiId]);
1271
+ async function save(nextConfig) {
1272
+ setSaving(true);
1273
+ try {
1274
+ await hostFetchJson(`/api/plugins/${encodeURIComponent(pluginApiId)}/config`, {
1275
+ method: "POST",
1276
+ body: JSON.stringify({ configJson: nextConfig })
1277
+ });
1278
+ setConfigJson(normalizeUiConfig(nextConfig));
1279
+ setError(null);
1280
+ } catch (nextError) {
1281
+ setError(readableError(nextError));
1282
+ throw nextError;
1283
+ } finally {
1284
+ setSaving(false);
1285
+ }
1286
+ }
1287
+ async function test(nextConfig) {
1288
+ return await hostFetchJson(`/api/plugins/${encodeURIComponent(pluginApiId)}/config/test`, {
1289
+ method: "POST",
1290
+ body: JSON.stringify({ configJson: nextConfig })
1291
+ });
1292
+ }
1293
+ return { configJson, setConfigJson, loading, saving, error, save, test };
1294
+ }
1295
+ function connectionFromProfile(input) {
1296
+ const baseId = input.profileName.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 42) || "feishu-bot";
1297
+ return {
1298
+ id: input.index === 0 ? baseId : `${baseId}-${input.index + 1}`,
1299
+ name: input.displayName?.trim() || `\u98DE\u4E66\u673A\u5668\u4EBA ${input.index + 1}`,
1300
+ botAliases: input.displayName && !isPlaceholderBotName(input.displayName) ? [input.displayName.trim()] : [],
1301
+ profileName: input.profileName,
1302
+ appId: input.appId,
1303
+ enabled: true
1304
+ };
1305
+ }
1306
+ function suggestedBindProfileName(profiles) {
1307
+ const existing = new Set(profiles.map((profile) => profile.name));
1308
+ if (!existing.has("paperclip-feishu-bot")) return "paperclip-feishu-bot";
1309
+ for (let index = 2; index < 100; index += 1) {
1310
+ const candidate = `paperclip-feishu-bot-${index}`;
1311
+ if (!existing.has(candidate)) return candidate;
1312
+ }
1313
+ return `paperclip-feishu-bot-${Date.now()}`;
1314
+ }
1315
+ function FeishuSettingsPage(props) {
1316
+ const pluginApiId = pluginInstanceIdFromProps(props);
1317
+ const catalog = usePluginData(DATA_KEYS.catalog);
1318
+ const profileCatalog = usePluginData(DATA_KEYS.profiles);
1319
+ const connectorStatus = usePluginData(DATA_KEYS.status);
1320
+ const capabilityCenter = usePluginData(DATA_KEYS.capabilities);
1321
+ const bindProfile = usePluginAction(ACTION_KEYS.bindProfile);
1322
+ const startGuidedBind = usePluginAction(ACTION_KEYS.startGuidedBind);
1323
+ const finishGuidedBind = usePluginAction(ACTION_KEYS.finishGuidedBind);
1324
+ const startUserAuth = usePluginAction(ACTION_KEYS.startUserAuth);
1325
+ const finishUserAuth = usePluginAction(ACTION_KEYS.finishUserAuth);
1326
+ const testRoute = usePluginAction(ACTION_KEYS.testRoute);
1327
+ const checkPermissions = usePluginAction(ACTION_KEYS.checkPermissions);
1328
+ const retryFailedDeliveries = usePluginAction(ACTION_KEYS.retryFailedDeliveries);
1329
+ const {
1330
+ configJson,
1331
+ setConfigJson,
1332
+ loading,
1333
+ saving,
1334
+ error,
1335
+ save,
1336
+ test
1337
+ } = useSettingsConfig(pluginApiId);
1338
+ const [notice, setNotice] = useState(null);
1339
+ const [toast, setToast] = useState(null);
1340
+ const [showBindPanel, setShowBindPanel] = useState(false);
1341
+ const [bindPanelTitle, setBindPanelTitle] = useState("\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA");
1342
+ const [bindMethod, setBindMethod] = useState("guided");
1343
+ const [binding, setBinding] = useState(false);
1344
+ const [checking, setChecking] = useState(false);
1345
+ const [lastCheckAt, setLastCheckAt] = useState(null);
1346
+ const [checkReportItems, setCheckReportItems] = useState([]);
1347
+ const [startingGuidedBind, setStartingGuidedBind] = useState(false);
1348
+ const [finishingGuidedBind, setFinishingGuidedBind] = useState(false);
1349
+ const [startingUserAuthProfileName, setStartingUserAuthProfileName] = useState(null);
1350
+ const [finishingUserAuthProfileName, setFinishingUserAuthProfileName] = useState(null);
1351
+ const [userAuthResults, setUserAuthResults] = useState({});
1352
+ const [guidedBindResult, setGuidedBindResult] = useState(null);
1353
+ const [testingRouteId, setTestingRouteId] = useState(null);
1354
+ const [checkingPermissions, setCheckingPermissions] = useState(false);
1355
+ const [permissionCheck, setPermissionCheck] = useState(null);
1356
+ const [retryingQueue, setRetryingQueue] = useState(false);
1357
+ const [importConfigText, setImportConfigText] = useState("");
1358
+ const [importConfigError, setImportConfigError] = useState(null);
1359
+ const [fixingRouteId, setFixingRouteId] = useState(null);
1360
+ const [routeTestResults, setRouteTestResults] = useState({});
1361
+ const [checkingConnectionId, setCheckingConnectionId] = useState(null);
1362
+ const [connectionCheckResults, setConnectionCheckResults] = useState({});
1363
+ const [showFeishuTestGuide, setShowFeishuTestGuide] = useState(false);
1364
+ const [bindForm, setBindForm] = useState({
1365
+ displayName: "\u98DE\u4E66\u673A\u5668\u4EBA",
1366
+ botAliases: "",
1367
+ profileName: "",
1368
+ appId: "",
1369
+ appSecret: "",
1370
+ appSecretRef: ""
1371
+ });
1372
+ const [showEntryWizard, setShowEntryWizard] = useState(false);
1373
+ const [savedEntry, setSavedEntry] = useState(null);
1374
+ const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
1375
+ const [activeAdvancedPanel, setActiveAdvancedPanel] = useState("auth");
1376
+ const [activeMainTab, setActiveMainTab] = useState(() => initialMainTab());
1377
+ const [expandedEntryRouteId, setExpandedEntryRouteId] = useState(null);
1378
+ const [chatSearchQuery, setChatSearchQuery] = useState("\u667A\u80FD\u4F53");
1379
+ const [userSearchQuery, setUserSearchQuery] = useState("\u5F20");
1380
+ const [wizardDraft, setWizardDraft] = useState({
1381
+ matchType: "keyword",
1382
+ keyword: "paperclip",
1383
+ replyMode: "thread"
1384
+ });
1385
+ useEffect(() => {
1386
+ if (!toast) return void 0;
1387
+ const timer = window.setTimeout(() => setToast(null), 4200);
1388
+ return () => window.clearTimeout(timer);
1389
+ }, [toast]);
1390
+ useEffect(() => {
1391
+ const syncFromHash = () => setActiveMainTab(mainTabFromHash(window.location.hash));
1392
+ syncFromHash();
1393
+ window.addEventListener("hashchange", syncFromHash);
1394
+ return () => window.removeEventListener("hashchange", syncFromHash);
1395
+ }, []);
1396
+ const companies = catalog.data?.companies ?? [];
1397
+ const allAgentOptions = companies.flatMap(
1398
+ (company) => company.agents.map((agent) => ({ company, agent }))
1399
+ );
1400
+ const connections = configJson.connections ?? [];
1401
+ const routes = configJson.routes ?? [];
1402
+ const baseSinks = configJson.baseSinks ?? [];
1403
+ const capabilityOverrides = configJson.capabilities ?? [];
1404
+ const capabilityGroups = capabilityCenter.data?.groups ?? [];
1405
+ const enabledCapabilityCount = capabilityGroups.flatMap((group) => group.capabilities).filter((capability) => capability.enabled).length;
1406
+ const profiles = profileCatalog.data?.profiles ?? [];
1407
+ const profileError = profileCatalog.data?.error ?? profileCatalog.error?.message;
1408
+ const suggestedNewProfileName = suggestedBindProfileName(profiles);
1409
+ const activeConnections = connections.filter((connection) => connection.enabled !== false);
1410
+ const availableProfileNames = new Set(profiles.map((profile) => profile.name));
1411
+ const usableConnections = activeConnections.filter((connection) => availableProfileNames.has(connection.profileName));
1412
+ const missingProfileConnections = activeConnections.filter((connection) => !availableProfileNames.has(connection.profileName));
1413
+ const firstEnabledConnection = activeConnections[0] ?? connections[0];
1414
+ const preferredConnection = usableConnections[0] ?? firstEnabledConnection;
1415
+ const suggestedProfileName = firstEnabledConnection?.profileName || "paperclip-feishu-bot";
1416
+ const runtimeHint = deploymentHint();
1417
+ const connectedProfile = profiles.find((profile) => profile.name === firstEnabledConnection?.profileName);
1418
+ const directoryProfileName = profiles.find((profile) => profile.user)?.name ?? connectedProfile?.name ?? firstEnabledConnection?.profileName ?? "";
1419
+ const directoryParams = useMemo(() => ({
1420
+ profileName: directoryProfileName,
1421
+ chatQuery: chatSearchQuery,
1422
+ userQuery: userSearchQuery
1423
+ }), [directoryProfileName, chatSearchQuery, userSearchQuery]);
1424
+ const directoryCatalog = usePluginData(DATA_KEYS.directory, directoryParams);
1425
+ const hasConnection = activeConnections.some((connection) => connection.profileName);
1426
+ const hasUsableConnection = usableConnections.length > 0;
1427
+ const enabledRouteCount = routes.filter((route) => route.enabled !== false).length;
1428
+ const isSendingRealMessages = configJson.dryRunCli !== true;
1429
+ const isListening = configJson.enableEventSubscriber === true;
1430
+ const runningOnLocalhost = isLocalRuntime();
1431
+ const routeSummaries = useMemo(() => routes.map((route) => {
1432
+ const company = resolveCompany(route, companies);
1433
+ const agent = resolveAgent(route, company);
1434
+ return { route, company, agent };
1435
+ }), [companies, routes]);
1436
+ const enabledRouteSummaries = routeSummaries.filter(({ route }) => route.enabled !== false);
1437
+ const firstEnabledRouteSummary = routeSummaries.find(({ route }) => route.enabled !== false) ?? routeSummaries[0] ?? null;
1438
+ const firstRouteConnection = firstEnabledRouteSummary?.route.connectionId ? connections.find((connection) => connection.id === firstEnabledRouteSummary.route.connectionId) ?? preferredConnection : preferredConnection;
1439
+ const firstRouteProfile = profiles.find((profile) => profile.name === firstRouteConnection?.profileName);
1440
+ const firstRouteConnectionReady = Boolean(firstRouteConnection?.profileName && availableProfileNames.has(firstRouteConnection.profileName));
1441
+ const enabledRoutesWithMissingConnection = enabledRouteSummaries.filter(({ route }) => {
1442
+ const connection = route.connectionId ? connections.find((candidate) => candidate.id === route.connectionId) : preferredConnection;
1443
+ return !connection?.profileName || !availableProfileNames.has(connection.profileName);
1444
+ }).length;
1445
+ const firstMissingRouteSummary = enabledRouteSummaries.find(({ route }) => {
1446
+ const connection = route.connectionId ? connections.find((candidate) => candidate.id === route.connectionId) : preferredConnection;
1447
+ return !connection?.profileName || !availableProfileNames.has(connection.profileName);
1448
+ }) ?? null;
1449
+ const connectionToFix = firstMissingRouteSummary?.route.connectionId ? connections.find((connection) => connection.id === firstMissingRouteSummary.route.connectionId) : missingProfileConnections[0] ?? null;
1450
+ const quickSmokeText = feishuSmokeText(firstEnabledRouteSummary?.route, firstRouteConnection, firstRouteProfile);
1451
+ const smokeText = feishuTaskTestText(firstEnabledRouteSummary?.route, firstRouteConnection, firstRouteProfile);
1452
+ const currentBotName = primaryMentionName(firstRouteConnection, firstRouteProfile ?? connectedProfile);
1453
+ const routeUsesOldBotKeyword = Boolean(
1454
+ firstEnabledRouteSummary?.route.matchType === "regex" && firstEnabledRouteSummary.route.regex?.includes("\u9510\u601D") && currentBotName && !firstEnabledRouteSummary.route.regex.includes(currentBotName)
1455
+ );
1456
+ const canTryFeishuSmokeTest = firstRouteConnectionReady && enabledRouteCount > 0 && isListening && isSendingRealMessages;
1457
+ const connectionUsageCounts = useMemo(() => {
1458
+ const counts = /* @__PURE__ */ new Map();
1459
+ const fallbackConnectionId = preferredConnection?.id;
1460
+ for (const route of routes) {
1461
+ if (route.enabled === false) continue;
1462
+ const connectionId = route.connectionId || fallbackConnectionId;
1463
+ if (!connectionId) continue;
1464
+ counts.set(connectionId, (counts.get(connectionId) ?? 0) + 1);
1465
+ }
1466
+ return counts;
1467
+ }, [routes, preferredConnection?.id]);
1468
+ const activeConnectionLabels = activeConnections.map((connection) => {
1469
+ const label = appLabel(connection, profiles.find((profile) => profile.name === connection.profileName));
1470
+ const routeCount = connectionUsageCounts.get(connection.id) ?? 0;
1471
+ const profileReady = availableProfileNames.has(connection.profileName);
1472
+ return `${label}\uFF08${profileReady ? `${routeCount} \u6761\u5165\u53E3` : "profile \u7F3A\u5931"}\uFF09`;
1473
+ }).filter(Boolean);
1474
+ const runtimeStatusLabel = isListening && isSendingRealMessages ? "\u76D1\u542C\u4E2D" : isListening ? "\u76D1\u542C\u4E2D\uFF0C\u6A21\u62DF\u56DE\u590D" : "\u672A\u76D1\u542C";
1475
+ const runtimeStatusDetail = isListening && isSendingRealMessages ? "\u771F\u5B9E\u56DE\u590D\u5DF2\u5F00\u542F" : `${isListening ? "\u5DF2\u63A5\u6536\u4E8B\u4EF6" : "\u4E0D\u4F1A\u81EA\u52A8\u63A5\u6536\u98DE\u4E66\u6D88\u606F"} \xB7 ${isSendingRealMessages ? "\u771F\u5B9E\u56DE\u590D" : "\u6D4B\u8BD5\u6A21\u5F0F"}`;
1476
+ const feishuEventRecords = useMemo(() => {
1477
+ const records = connectorStatus.data?.recentRecords ?? [];
1478
+ return records.filter(isInboundMessageRecord);
1479
+ }, [connectorStatus.data?.recentRecords]);
1480
+ const latestFeishuEvent = feishuEventRecords[0] ?? null;
1481
+ const latestOperationalRecord = (connectorStatus.data?.recentRecords ?? []).find((record) => !isInboundMessageRecord(record)) ?? null;
1482
+ const feishuEventEmptyText = connectorStatus.data?.lastInboundEventAt ? `\u8FD8\u6CA1\u6709\u65B0\u7684\u98DE\u4E66\u6D88\u606F\u4E8B\u4EF6\u3002\u4E0A\u6B21\u8FDB\u5165\u63D2\u4EF6\u7684\u98DE\u4E66\u6D88\u606F\u662F ${connectorStatus.data.lastInboundEventAt}\uFF1B\u5982\u679C\u521A\u53D1\u8FC7\u6D4B\u8BD5\u6D88\u606F\uFF0C\u8BF7\u5148\u786E\u8BA4\u6D88\u606F\u53D1\u7ED9\u4E86\u5F53\u524D\u5165\u53E3\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u3002` : "\u8FD8\u6CA1\u6709\u6536\u5230\u98DE\u4E66\u6D88\u606F\u4E8B\u4EF6\u3002\u8BF7\u786E\u8BA4\u4F60 @ \u7684\u673A\u5668\u4EBA\u5C31\u662F\u4E0B\u65B9\u5165\u53E3\u9009\u62E9\u7684\u673A\u5668\u4EBA\u3002";
1483
+ const statusTitle = !hasConnection ? "\u5F85\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA" : !hasUsableConnection ? "\u5DF2\u914D\u7F6E\u673A\u5668\u4EBA\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u7F3A\u5C11\u6388\u6743" : enabledRouteCount === 0 ? "\u5DF2\u6DFB\u52A0\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u5F85\u914D\u7F6E\u6D88\u606F\u5165\u53E3" : enabledRoutesWithMissingConnection > 0 ? "\u6709\u5165\u53E3\u4F7F\u7528\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u4E0D\u53EF\u8FD0\u884C\uFF0C\u9700\u8981\u91CD\u65B0\u7ED1\u5B9A\u6216\u6362\u673A\u5668\u4EBA" : !isListening ? "\u5DF2\u914D\u7F6E\u5165\u53E3\uFF0C\u5F85\u5F00\u542F\u98DE\u4E66\u6D88\u606F\u76D1\u542C" : !isSendingRealMessages ? "\u5F53\u524D\u4E3A\u6D4B\u8BD5\u6A21\u5F0F\uFF0C\u6682\u4E0D\u4F1A\u771F\u5B9E\u56DE\u590D\u98DE\u4E66" : "\u673A\u5668\u4EBA\u3001\u5165\u53E3\u548C\u76D1\u542C\u90FD\u5DF2\u5C31\u7EEA\uFF0C\u5EFA\u8BAE\u5B8C\u6210\u4E00\u6B21\u98DE\u4E66\u771F\u5B9E\u6D4B\u8BD5";
1484
+ const overviewTitle = !hasConnection ? "\u5148\u63A5\u5165\u4E00\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA" : enabledRoutesWithMissingConnection > 0 ? "\u98DE\u4E66\u5165\u53E3\u9700\u8981\u4FEE\u590D" : hasUsableConnection ? "\u98DE\u4E66\u5DF2\u7ECF\u8FDE\u63A5\u5230 Paperclip" : "\u98DE\u4E66\u673A\u5668\u4EBA\u8FD8\u6CA1\u6709\u6388\u6743\u5230\u5F53\u524D\u73AF\u5883";
1485
+ const nextStepKind = !hasConnection ? "bind" : !hasUsableConnection ? "rebind" : enabledRouteCount === 0 ? "entry" : enabledRoutesWithMissingConnection > 0 ? "edit-entry" : !isListening ? "enable-listen" : !isSendingRealMessages ? "enable-real" : "test";
1486
+ const nextStepCopy = (() => {
1487
+ if (nextStepKind === "bind") {
1488
+ return {
1489
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u5148\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA",
1490
+ detail: "\u8FD9\u662F\u552F\u4E00\u5FC5\u987B\u5148\u505A\u7684\u4E8B\u3002\u63A5\u5165\u540E\u518D\u9009\u62E9\u201C\u54EA\u4E9B\u6D88\u606F\u8FDB\u6765\u3001\u4EA4\u7ED9\u54EA\u4E2A\u667A\u80FD\u4F53\u201D\u3002"
1491
+ };
1492
+ }
1493
+ if (nextStepKind === "rebind") {
1494
+ const label = appLabel(connectionToFix ?? firstEnabledConnection, profiles.find((profile) => profile.name === connectionToFix?.profileName));
1495
+ return {
1496
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u4FEE\u590D\u673A\u5668\u4EBA\u6388\u6743",
1497
+ detail: `\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u6CA1\u6709\u8BFB\u5230\u201C${label}\u201D\u3002\u5148\u5237\u65B0\u5217\u8868\uFF1B\u5982\u679C\u4ECD\u7136\u6CA1\u6709\uFF0C\u5C31\u5728\u5F39\u7A97\u91CC\u91CD\u65B0\u7ED1\u5B9A\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002`
1498
+ };
1499
+ }
1500
+ if (nextStepKind === "entry") {
1501
+ return {
1502
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u65B0\u589E\u4E00\u6761\u4E1A\u52A1\u5165\u53E3",
1503
+ detail: "\u5165\u53E3\u51B3\u5B9A\u201C\u54EA\u4E2A\u98DE\u4E66\u7FA4\u6216\u5173\u952E\u8BCD\u8FDB\u6765\u3001\u7528\u54EA\u4E2A\u673A\u5668\u4EBA\u6536\u3001\u4EA4\u7ED9\u54EA\u4E2A Paperclip \u667A\u80FD\u4F53\u201D\u3002"
1504
+ };
1505
+ }
1506
+ if (nextStepKind === "edit-entry") {
1507
+ return {
1508
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u4FEE\u590D\u5165\u53E3\u4F7F\u7528\u7684\u673A\u5668\u4EBA",
1509
+ detail: "\u6709\u5165\u53E3\u8FD8\u6307\u5411\u4E0D\u53EF\u8FD0\u884C\u7684\u673A\u5668\u4EBA\u3002\u7F16\u8F91\u8FD9\u6761\u5165\u53E3\uFF0C\u6362\u6210\u53EF\u8FD0\u884C\u673A\u5668\u4EBA\uFF0C\u6216\u91CD\u65B0\u7ED1\u5B9A\u539F\u673A\u5668\u4EBA\u3002"
1510
+ };
1511
+ }
1512
+ if (nextStepKind === "enable-listen") {
1513
+ return {
1514
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u5F00\u542F\u81EA\u52A8\u76D1\u542C",
1515
+ detail: "\u4E0D\u5F00\u76D1\u542C\u65F6\uFF0C\u98DE\u4E66\u91CC\u53D1\u6D88\u606F\u4E0D\u4F1A\u81EA\u52A8\u8FDB\u5165 Paperclip\u3002\u5F00\u542F\u540E\u518D\u53BB\u98DE\u4E66\u5B9E\u6D4B\u3002"
1516
+ };
1517
+ }
1518
+ if (nextStepKind === "enable-real") {
1519
+ return {
1520
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u5F00\u542F\u771F\u5B9E\u56DE\u590D",
1521
+ detail: "\u5F53\u524D\u53EA\u662F\u6A21\u62DF\u6A21\u5F0F\u3002\u8981\u770B\u5230\u98DE\u4E66\u91CC\u771F\u5B9E\u56DE\u590D\uFF0C\u9700\u8981\u5F00\u542F\u771F\u5B9E\u53D1\u9001\u3002"
1522
+ };
1523
+ }
1524
+ return {
1525
+ title: "\u4E0B\u4E00\u6B65\uFF1A\u53BB\u98DE\u4E66\u91CC\u53D1\u4E00\u53E5\u771F\u5B9E\u6D4B\u8BD5",
1526
+ detail: `\u628A\u6D4B\u8BD5\u8BDD\u672F\u53D1\u5230\u76EE\u6807\u4F1A\u8BDD\uFF1A${smokeText}`
1527
+ };
1528
+ })();
1529
+ const serverDeployConnection = firstRouteConnection ?? preferredConnection ?? firstEnabledConnection;
1530
+ const serverDeployCommands = buildServerDeployCommands(serverDeployConnection);
1531
+ const activeSubscriberCount = connectorStatus.data?.subscribers?.filter((subscriber) => activeConnections.some((connection) => connection.id === subscriber.connectionId)).length ?? 0;
1532
+ const capabilityChecks = [
1533
+ {
1534
+ tone: hasUsableConnection && !profileError && missingProfileConnections.length === 0 ? "success" : hasConnection ? "warning" : "error",
1535
+ title: "\u98DE\u4E66\u5E94\u7528\u6388\u6743",
1536
+ detail: hasUsableConnection && !profileError ? missingProfileConnections.length > 0 ? `\u5DF2\u53D1\u73B0 ${profiles.length} \u4E2A lark-cli profile\uFF1B${usableConnections.length} \u4E2A\u673A\u5668\u4EBA\u53EF\u8FD0\u884C\uFF0C${missingProfileConnections.length} \u4E2A\u673A\u5668\u4EBA\u7F3A\u5C11\u5F53\u524D\u73AF\u5883\u6388\u6743\u3002` : `\u5DF2\u53D1\u73B0 ${profiles.length} \u4E2A lark-cli profile\uFF0C\u673A\u5668\u4EBA\u6C60 ${usableConnections.length} \u4E2A\u53EF\u8FD0\u884C\u3002` : hasConnection ? `\u5DF2\u914D\u7F6E\u673A\u5668\u4EBA\uFF0C\u4F46\u8BFB\u53D6 lark-cli profile \u5F02\u5E38\uFF1A${profileError ?? "\u5F53\u524D\u73AF\u5883\u672A\u8FD4\u56DE\u6388\u6743\u5217\u8868"}` : "\u8FD8\u6CA1\u6709\u628A\u98DE\u4E66\u673A\u5668\u4EBA\u52A0\u5165\u673A\u5668\u4EBA\u6C60\u3002"
1537
+ },
1538
+ {
1539
+ tone: isListening && activeSubscriberCount > 0 ? "success" : isListening ? "warning" : "warning",
1540
+ title: "\u63A5\u6536\u98DE\u4E66\u6D88\u606F",
1541
+ detail: isListening ? activeSubscriberCount > 0 ? `\u5DF2\u770B\u5230 ${activeSubscriberCount} \u4E2A\u76D1\u542C\u8FDB\u7A0B\u3002` : "\u76D1\u542C\u5F00\u5173\u5DF2\u5F00\uFF0C\u4F46\u6682\u65F6\u6CA1\u770B\u5230\u76D1\u542C\u8FDB\u7A0B\uFF1B\u4FDD\u5B58\u914D\u7F6E\u6216\u91CD\u542F\u670D\u52A1\u540E\u518D\u68C0\u67E5\u3002" : "\u76D1\u542C\u5F00\u5173\u672A\u5F00\u542F\uFF0C\u98DE\u4E66\u6D88\u606F\u4E0D\u4F1A\u81EA\u52A8\u8FDB\u5165 Paperclip\u3002"
1542
+ },
1543
+ {
1544
+ tone: isSendingRealMessages ? "success" : "warning",
1545
+ title: "\u56DE\u590D\u98DE\u4E66\u6D88\u606F",
1546
+ detail: isSendingRealMessages ? "\u771F\u5B9E\u56DE\u590D\u5DF2\u5F00\u542F\u3002" : "\u5F53\u524D\u662F\u6A21\u62DF\u6A21\u5F0F\uFF0C\u53EA\u9A8C\u8BC1\u6D41\u7A0B\u4E0D\u771F\u6B63\u53D1\u56DE\u98DE\u4E66\u3002"
1547
+ },
1548
+ {
1549
+ tone: isSendingRealMessages ? "success" : "warning",
1550
+ title: "\u4E0B\u8F7D\u98DE\u4E66\u9644\u4EF6",
1551
+ detail: isSendingRealMessages ? "\u771F\u5B9E\u4EFB\u52A1\u91CC\u4F1A\u628A\u98DE\u4E66\u56FE\u7247\u3001\u6587\u4EF6\u3001\u97F3\u9891\u548C\u89C6\u9891\u4E0A\u4F20\u6210 Paperclip \u9644\u4EF6\u3002" : "\u6A21\u62DF\u6A21\u5F0F\u53EA\u8BB0\u5F55\u9644\u4EF6\u540D\u79F0\uFF0C\u4E0D\u4F1A\u4E0B\u8F7D\u4E0A\u4F20\u3002"
1552
+ },
1553
+ {
1554
+ tone: directoryCatalog.error || directoryCatalog.data?.chatError || directoryCatalog.data?.userError ? "warning" : "success",
1555
+ title: "\u641C\u7D22\u7FA4\u548C\u8054\u7CFB\u4EBA",
1556
+ detail: directoryCatalog.error || directoryCatalog.data?.chatError || directoryCatalog.data?.userError ? "\u5F53\u524D\u641C\u7D22\u76EE\u5F55\u6709\u62A5\u9519\uFF0C\u53EF\u80FD\u5F71\u54CD\u9009\u62E9\u7FA4/\u8054\u7CFB\u4EBA\u3002\u5DF2\u5EFA\u597D\u7684\u5165\u53E3\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u53EF\u4EE5\u8BFB\u53D6\u5F53\u524D profile \u53EF\u89C1\u7684\u7FA4\u548C\u8054\u7CFB\u4EBA\uFF0C\u7528\u4E8E\u65B0\u589E\u5165\u53E3\u3002"
1557
+ },
1558
+ {
1559
+ tone: baseSinks.length > 0 ? "success" : "warning",
1560
+ title: "\u5199\u5165\u591A\u7EF4\u8868\u683C",
1561
+ detail: baseSinks.length > 0 ? `\u5DF2\u914D\u7F6E ${baseSinks.length} \u6761\u591A\u7EF4\u8868\u683C\u5199\u5165\u89C4\u5219\u3002` : "\u672A\u914D\u7F6E\u3002\u6CA1\u6709\u9700\u6C42\u6C89\u6DC0\u5230 Base \u7684\u573A\u666F\u65F6\u53EF\u4EE5\u7559\u7A7A\u3002"
1562
+ }
1563
+ ];
1564
+ const productionMonitor = connectorStatus.data?.monitor;
1565
+ const productionMonitorChecks = productionMonitor?.checks ?? [];
1566
+ const retryQueue = connectorStatus.data?.retryQueue;
1567
+ const primaryRouteSummary = firstEnabledRouteSummary;
1568
+ const primaryRouteConnectionLabel = appLabel(firstRouteConnection, firstRouteProfile ?? connectedProfile);
1569
+ const setupProgressSteps = [
1570
+ {
1571
+ done: hasUsableConnection,
1572
+ title: "\u9009\u62E9\u98DE\u4E66\u673A\u5668\u4EBA",
1573
+ detail: hasUsableConnection ? `${primaryRouteConnectionLabel} \u53EF\u7528\u4E8E\u6536\u53D1\u98DE\u4E66\u6D88\u606F\u3002` : "\u5148\u7ED1\u5B9A\u4E00\u4E2A\u516C\u53F8\u901A\u7528\u673A\u5668\u4EBA\u6216\u4E1A\u52A1\u4E13\u7528\u673A\u5668\u4EBA\u3002",
1574
+ action: hasUsableConnection ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => selectMainTab("robots"), children: "\u67E5\u770B\u673A\u5668\u4EBA" }, "view-bots") : /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openBindPanel(void 0, "guided"), children: "\u7ED1\u5B9A\u673A\u5668\u4EBA" }, "bind-bot")
1575
+ },
1576
+ {
1577
+ done: enabledRouteCount > 0,
1578
+ title: "\u5EFA\u7ACB\u4E1A\u52A1\u5165\u53E3",
1579
+ detail: enabledRouteCount > 0 ? `${enabledRouteCount} \u6761\u5165\u53E3\u6B63\u5728\u628A\u98DE\u4E66\u6D88\u606F\u4EA4\u7ED9 Paperclip\u3002` : "\u51B3\u5B9A\u54EA\u4E2A\u7FA4\u3001\u5173\u952E\u8BCD\u6216\u8054\u7CFB\u4EBA\u8FDB\u5165\u54EA\u4E2A\u667A\u80FD\u4F53\u3002",
1580
+ action: /* @__PURE__ */ jsx("button", { type: "button", style: enabledRouteCount > 0 ? buttonStyle : primaryButtonStyle, onClick: () => openEntryWizard(), children: enabledRouteCount > 0 ? "\u7BA1\u7406\u5165\u53E3" : "\u65B0\u589E\u5165\u53E3" }, "manage-entry")
1581
+ },
1582
+ {
1583
+ done: canTryFeishuSmokeTest,
1584
+ title: "\u98DE\u4E66\u91CC\u771F\u5B9E\u6D4B\u8BD5",
1585
+ detail: canTryFeishuSmokeTest ? "\u76D1\u542C\u548C\u771F\u5B9E\u56DE\u590D\u5DF2\u5F00\u542F\uFF0C\u53EF\u4EE5\u53BB\u98DE\u4E66\u53D1\u6D4B\u8BD5\u8BDD\u672F\u3002" : "\u786E\u8BA4\u76D1\u542C\u3001\u771F\u5B9E\u56DE\u590D\u548C\u5165\u53E3\u673A\u5668\u4EBA\u90FD\u5C31\u7EEA\u540E\u518D\u5B9E\u6D4B\u3002",
1586
+ action: /* @__PURE__ */ jsx("button", { type: "button", style: canTryFeishuSmokeTest ? primaryButtonStyle : buttonStyle, onClick: () => selectMainTab("test"), children: "\u53BB\u6D4B\u8BD5" }, "go-test")
1587
+ }
1588
+ ];
1589
+ const realTestPipeline = [
1590
+ {
1591
+ done: firstRouteConnectionReady,
1592
+ label: "\u673A\u5668\u4EBA\u53EF\u7528",
1593
+ detail: firstRouteConnectionReady ? primaryRouteConnectionLabel : "\u5F53\u524D\u5165\u53E3\u673A\u5668\u4EBA\u672A\u5728\u8FD0\u884C\u73AF\u5883\u4E2D\u8BFB\u5230\u3002"
1594
+ },
1595
+ {
1596
+ done: enabledRouteCount > 0,
1597
+ label: "\u5165\u53E3\u5DF2\u5EFA",
1598
+ detail: primaryRouteSummary ? routeTitle(primaryRouteSummary.route, 0) : "\u8FD8\u6CA1\u6709\u98DE\u4E66\u6D88\u606F\u5165\u53E3\u3002"
1599
+ },
1600
+ {
1601
+ done: isListening,
1602
+ label: "\u6B63\u5728\u76D1\u542C",
1603
+ detail: isListening ? runtimeStatusLabel : "\u672A\u5F00\u542F\u76D1\u542C\uFF0C\u98DE\u4E66\u6D88\u606F\u4E0D\u4F1A\u81EA\u52A8\u8FDB\u5165\u3002"
1604
+ },
1605
+ {
1606
+ done: isSendingRealMessages,
1607
+ label: "\u771F\u5B9E\u56DE\u590D",
1608
+ detail: isSendingRealMessages ? "\u667A\u80FD\u4F53\u5B8C\u6210\u540E\u4F1A\u56DE\u590D\u98DE\u4E66\u3002" : "\u5F53\u524D\u662F\u6A21\u62DF\u6A21\u5F0F\u3002"
1609
+ },
1610
+ {
1611
+ done: isSendingRealMessages,
1612
+ label: "\u9644\u4EF6\u5165\u5E93",
1613
+ detail: isSendingRealMessages ? "\u56FE\u7247\u548C\u6587\u4EF6\u4F1A\u4F5C\u4E3A\u4EFB\u52A1\u9644\u4EF6\u3002" : "\u6A21\u62DF\u6A21\u5F0F\u4E0D\u4E0B\u8F7D\u9644\u4EF6\u3002"
1614
+ }
1615
+ ];
1616
+ function patchWizardDraft(patch) {
1617
+ setWizardDraft((prev) => ({ ...prev, ...patch }));
1618
+ setNotice(null);
1619
+ }
1620
+ function selectChatForWizard(chat) {
1621
+ patchWizardDraft({
1622
+ matchType: "chat",
1623
+ chatId: chat.chatId,
1624
+ chatName: chat.name
1625
+ });
1626
+ setNotice({ tone: "success", text: `\u5DF2\u9009\u62E9\u98DE\u4E66\u4F1A\u8BDD\uFF1A${chat.name}` });
1627
+ }
1628
+ function selectUserForWizard(user) {
1629
+ patchWizardDraft({
1630
+ matchType: "user",
1631
+ userOpenId: user.openId,
1632
+ userName: user.name
1633
+ });
1634
+ setNotice({ tone: "success", text: `\u5DF2\u9009\u62E9\u53D1\u6D88\u606F\u4EBA\uFF1A${user.name}` });
1635
+ }
1636
+ function patchConfig(patch) {
1637
+ setConfigJson((prev) => normalizeUiConfig({ ...prev, ...patch }));
1638
+ setNotice(null);
1639
+ setCheckReportItems([]);
1640
+ }
1641
+ function selectMainTab(tab) {
1642
+ setActiveMainTab(tab);
1643
+ if (tab !== "advanced") {
1644
+ setShowAdvancedSettings(false);
1645
+ }
1646
+ const hash = mainTabs.find((item) => item.key === tab)?.hash;
1647
+ if (hash) {
1648
+ window.history.replaceState(null, "", `${window.location.pathname}${window.location.search}#${hash}`);
1649
+ }
1650
+ }
1651
+ function patchRoute(index, patch) {
1652
+ const next = [...routes];
1653
+ next[index] = { ...next[index], ...patch };
1654
+ patchConfig({ routes: next });
1655
+ }
1656
+ function patchConnectionById(connectionId, patch) {
1657
+ patchConfig({
1658
+ connections: connections.map(
1659
+ (connection) => connection.id === connectionId ? { ...connection, ...patch } : connection
1660
+ )
1661
+ });
1662
+ }
1663
+ function patchBaseSink(index, patch) {
1664
+ const next = [...baseSinks];
1665
+ next[index] = { ...next[index], ...patch };
1666
+ patchConfig({ baseSinks: next });
1667
+ }
1668
+ function patchCapability(key, patch) {
1669
+ const current = capabilityOverrides.find((capability) => capability.key === key);
1670
+ const nextCapability = { ...current, key, ...patch };
1671
+ const nextCapabilities = current ? capabilityOverrides.map((capability) => capability.key === key ? nextCapability : capability) : [...capabilityOverrides, nextCapability];
1672
+ patchConfig({ capabilities: nextCapabilities });
1673
+ }
1674
+ function patchCapabilityScope(key, scope) {
1675
+ patchCapability(key, {
1676
+ scope,
1677
+ connectionId: scope === "bot" ? preferredConnection?.id ?? activeConnections[0]?.id : void 0,
1678
+ routeId: scope === "entry" ? firstEnabledRouteSummary?.route.id ?? routes[0]?.id : void 0,
1679
+ agentId: scope === "agent" ? firstEnabledRouteSummary?.agent?.id ?? allAgentOptions[0]?.agent.id : void 0
1680
+ });
1681
+ }
1682
+ async function addProfileToPool(profile, options = {}) {
1683
+ const existing = connections.find((connection) => connection.profileName === profile.name);
1684
+ const displayName = profileDisplayName(profile);
1685
+ const inferredAliases = splitBotAliases(profile.botName ?? displayName).filter((alias) => !isPlaceholderBotName(alias));
1686
+ const selected = existing ? {
1687
+ ...existing,
1688
+ enabled: true,
1689
+ appId: profile.appId ?? existing.appId,
1690
+ name: existing.name && existing.name !== existing.profileName ? existing.name : displayName,
1691
+ botAliases: connectionAliasList(existing).length > 0 ? connectionAliasList(existing) : inferredAliases
1692
+ } : connectionFromProfile({
1693
+ index: connections.length,
1694
+ profileName: profile.name,
1695
+ appId: profile.appId ?? void 0,
1696
+ displayName
1697
+ });
1698
+ const firstRouteId = firstEnabledRouteSummary?.route.id;
1699
+ const updatedConnections = existing ? connections.map((connection) => connection.profileName === profile.name ? selected : connection) : [...connections, selected];
1700
+ const nextConnections = !firstEnabledConnection || options.useForCurrentEntry && !firstRouteId ? [
1701
+ selected,
1702
+ ...updatedConnections.filter((connection) => connection.profileName !== profile.name)
1703
+ ] : updatedConnections;
1704
+ const nextRoutes = firstRouteId ? routes.map((route) => options.useForCurrentEntry && route.id === firstRouteId ? { ...route, connectionId: selected.id } : route) : routes;
1705
+ const nextConfig = normalizeUiConfig({
1706
+ ...configJson,
1707
+ connections: nextConnections,
1708
+ routes: nextRoutes
1709
+ });
1710
+ setNotice({
1711
+ tone: "info",
1712
+ text: options.useForCurrentEntry ? `\u6B63\u5728\u628A\u6307\u5B9A\u5165\u53E3\u6539\u7528\u201C${appLabel(selected, profile)}\u201D...` : `\u6B63\u5728\u628A\u201C${appLabel(selected, profile)}\u201D\u52A0\u5165\u673A\u5668\u4EBA\u6C60...`
1713
+ });
1714
+ try {
1715
+ await save(nextConfig);
1716
+ setConfigJson(nextConfig);
1717
+ profileCatalog.refresh();
1718
+ setNotice({
1719
+ tone: "success",
1720
+ text: options.useForCurrentEntry && firstRouteId ? `\u5DF2\u4FDD\u5B58\uFF1A\u6307\u5B9A\u5165\u53E3\u5DF2\u6539\u7528\u201C${appLabel(selected, profile)}\u201D\u3002\u5176\u4ED6\u98DE\u4E66\u673A\u5668\u4EBA\u4ECD\u7136\u4FDD\u7559\uFF0C\u53EF\u7ED9\u5176\u4ED6\u5165\u53E3\u4F7F\u7528\u3002` : `\u5DF2\u4FDD\u5B58\uFF1A\u5DF2\u6DFB\u52A0\u201C${appLabel(selected, profile)}\u201D\u3002\u540E\u7EED\u6BCF\u6761\u98DE\u4E66\u5165\u53E3\u90FD\u53EF\u4EE5\u5355\u72EC\u9009\u62E9\u673A\u5668\u4EBA\u3002`
1721
+ });
1722
+ } catch (nextError) {
1723
+ setNotice({ tone: "error", text: readableError(nextError) });
1724
+ }
1725
+ }
1726
+ function addConnectionFromProfile(profile) {
1727
+ void addProfileToPool(profile);
1728
+ }
1729
+ function openBindPanel(connection, method = "guided") {
1730
+ const title = connection ? `\u91CD\u65B0\u7ED1\u5B9A\uFF1A${connection.name || connection.profileName}` : "\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA";
1731
+ setBindForm((prev) => ({
1732
+ ...prev,
1733
+ displayName: connection?.name || prev.displayName || "\u98DE\u4E66\u673A\u5668\u4EBA",
1734
+ botAliases: connection ? formatBotAliases(connection) : prev.botAliases,
1735
+ profileName: connection?.profileName || prev.profileName || suggestedNewProfileName,
1736
+ appId: connection?.appId || prev.appId,
1737
+ appSecret: "",
1738
+ appSecretRef: ""
1739
+ }));
1740
+ setGuidedBindResult(null);
1741
+ setBindMethod(method);
1742
+ setBindPanelTitle(title);
1743
+ setShowBindPanel(true);
1744
+ setNotice(null);
1745
+ }
1746
+ function openEntryWizard(connectionId) {
1747
+ if (!hasConnection) {
1748
+ openBindPanel();
1749
+ setNotice({ tone: "info", text: "\u5148\u9009\u62E9\u6216\u7ED1\u5B9A\u4E00\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA\uFF0C\u7136\u540E\u518D\u65B0\u589E\u98DE\u4E66\u5165\u53E3\u3002" });
1750
+ return;
1751
+ }
1752
+ selectMainTab("entries");
1753
+ const existingSummary = routeSummaries.find((summary) => summary.company && summary.agent) ?? null;
1754
+ const company = existingSummary?.company ?? companies[0];
1755
+ const agent = existingSummary?.agent ?? company?.agents[0];
1756
+ const existingConnection = existingSummary?.route.connectionId ? connections.find((connection) => connection.id === existingSummary.route.connectionId) : null;
1757
+ setWizardDraft({
1758
+ connectionId: connectionId ?? existingConnection?.id ?? preferredConnection?.id,
1759
+ matchType: "keyword",
1760
+ keyword: "paperclip",
1761
+ replyMode: "thread",
1762
+ companyId: company?.id,
1763
+ targetAgentId: agent?.id
1764
+ });
1765
+ setShowEntryWizard(true);
1766
+ setNotice(null);
1767
+ }
1768
+ function openEntryEditor(routeId) {
1769
+ const route = routeId ? routes.find((item) => item.id === routeId) : firstEnabledRouteSummary?.route;
1770
+ if (!route) {
1771
+ openEntryWizard();
1772
+ return;
1773
+ }
1774
+ selectMainTab("entries");
1775
+ setShowEntryWizard(false);
1776
+ setExpandedEntryRouteId(route.id);
1777
+ setNotice({ tone: "info", text: "\u5DF2\u6253\u5F00\u5165\u53E3\u7F16\u8F91\u533A\uFF0C\u53EF\u4EE5\u6539\u5173\u952E\u8BCD\u3001\u5904\u7406\u4EBA\u6216\u56DE\u590D\u65B9\u5F0F\u3002" });
1778
+ window.setTimeout(() => {
1779
+ document.getElementById(`product-entry-${route.id}`)?.scrollIntoView({ behavior: "smooth", block: "start" });
1780
+ }, 30);
1781
+ }
1782
+ function refreshProfilesWithNotice() {
1783
+ profileCatalog.refresh();
1784
+ setToast({ tone: "info", text: "\u6B63\u5728\u5237\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5217\u8868\u3002" });
1785
+ setNotice({ tone: "info", text: "\u6B63\u5728\u5237\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5217\u8868\u3002\u6388\u6743\u5B8C\u6210\u540E\uFF0C\u5982\u679C\u8FD9\u91CC\u8FD8\u6CA1\u51FA\u73B0\uFF0C\u901A\u5E38\u662F\u5F53\u524D\u673A\u5668/\u670D\u52A1\u5668\u8FD8\u6CA1\u6709\u5B8C\u6210 lark-cli \u6388\u6743\u3002" });
1786
+ }
1787
+ function openFeishuTestGuide() {
1788
+ selectMainTab("test");
1789
+ setShowFeishuTestGuide((value) => !value);
1790
+ window.setTimeout(() => {
1791
+ document.getElementById("feishu-test-guide")?.scrollIntoView({ behavior: "smooth", block: "nearest" });
1792
+ }, 30);
1793
+ }
1794
+ async function copySmokeText() {
1795
+ try {
1796
+ await navigator.clipboard.writeText(smokeText);
1797
+ setNotice({ tone: "success", text: `\u5DF2\u590D\u5236\u6D4B\u8BD5\u8BDD\u672F\uFF1A${smokeText}` });
1798
+ } catch {
1799
+ setNotice({ tone: "info", text: `\u8BF7\u590D\u5236\u8FD9\u53E5\u8BDD\u5230\u98DE\u4E66\u53D1\u9001\uFF1A${smokeText}` });
1800
+ }
1801
+ }
1802
+ async function copyServerDeployCommands() {
1803
+ try {
1804
+ await navigator.clipboard.writeText(serverDeployCommands);
1805
+ setNotice({ tone: "success", text: "\u5DF2\u590D\u5236\u670D\u52A1\u5668\u90E8\u7F72\u547D\u4EE4\u3002App Secret \u4ECD\u9700\u5DE5\u7A0B\u5E08\u5728\u670D\u52A1\u5668\u5B89\u5168\u8F93\u5165\u3002" });
1806
+ } catch {
1807
+ setNotice({ tone: "info", text: "\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u5728\u4E91\u670D\u52A1\u5668\u90E8\u7F72\u9762\u677F\u91CC\u624B\u52A8\u590D\u5236\u547D\u4EE4\u3002" });
1808
+ }
1809
+ }
1810
+ function exportedConfigText() {
1811
+ return JSON.stringify(portableConfig(configJson), null, 2);
1812
+ }
1813
+ async function copyConfigExport() {
1814
+ const text = exportedConfigText();
1815
+ try {
1816
+ await navigator.clipboard.writeText(text);
1817
+ setNotice({ tone: "success", text: "\u5DF2\u590D\u5236\u98DE\u4E66\u8FDE\u63A5\u5668\u914D\u7F6E\u3002App Secret \u548C\u8FD0\u884C\u65F6\u6388\u6743 token \u4E0D\u4F1A\u5BFC\u51FA\u3002" });
1818
+ } catch {
1819
+ setNotice({ tone: "info", text: "\u590D\u5236\u5931\u8D25\uFF0C\u53EF\u4EE5\u5728\u5BFC\u51FA\u914D\u7F6E\u9762\u677F\u91CC\u624B\u52A8\u9009\u4E2D JSON\u3002" });
1820
+ }
1821
+ }
1822
+ function previewConfigImport() {
1823
+ setImportConfigError(null);
1824
+ const trimmed = importConfigText.trim();
1825
+ if (!trimmed) {
1826
+ setImportConfigError("\u8BF7\u5148\u7C98\u8D34\u4E00\u6BB5\u914D\u7F6E JSON\u3002");
1827
+ return;
1828
+ }
1829
+ try {
1830
+ const parsed = JSON.parse(trimmed);
1831
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1832
+ throw new Error("\u914D\u7F6E JSON \u5FC5\u987B\u662F\u5BF9\u8C61\u3002");
1833
+ }
1834
+ const nextConfig = portableConfig(normalizeUiConfig(parsed));
1835
+ setConfigJson(nextConfig);
1836
+ setImportConfigText(JSON.stringify(nextConfig, null, 2));
1837
+ setToast({ tone: "info", text: "\u5DF2\u5BFC\u5165\u5230\u9875\u9762\uFF0C\u70B9\u51FB\u201C\u4FDD\u5B58\u914D\u7F6E\u201D\u540E\u751F\u6548\u3002" });
1838
+ setNotice({ tone: "info", text: "\u5DF2\u5BFC\u5165\u5230\u9875\u9762\uFF0C\u70B9\u51FB\u201C\u4FDD\u5B58\u914D\u7F6E\u201D\u540E\u751F\u6548\uFF1BApp Secret \u9700\u8981\u5728\u5F53\u524D\u670D\u52A1\u5668\u91CD\u65B0\u7ED1\u5B9A\u3002" });
1839
+ } catch (nextError) {
1840
+ setImportConfigError(readableError(nextError));
1841
+ }
1842
+ }
1843
+ function createEntryFromWizard() {
1844
+ const company = companies.find((item) => item.id === wizardDraft.companyId) ?? companies[0] ?? null;
1845
+ const agent = company?.agents.find((item) => item.id === wizardDraft.targetAgentId) ?? company?.agents[0] ?? null;
1846
+ const connection = connections.find((item) => item.id === wizardDraft.connectionId) ?? preferredConnection ?? connections[0] ?? null;
1847
+ if (!connection) {
1848
+ setNotice({ tone: "error", text: "\u8FD8\u6CA1\u6709\u53EF\u7528\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u8BF7\u5148\u5728\u201C\u98DE\u4E66\u5E94\u7528\u4E0E\u673A\u5668\u4EBA\u7ED1\u5B9A\u201D\u91CC\u7ED1\u5B9A\u6216\u6DFB\u52A0\u673A\u5668\u4EBA\u3002" });
1849
+ return;
1850
+ }
1851
+ if (!company || !agent) {
1852
+ setNotice({ tone: "error", text: "\u8FD8\u6CA1\u6709\u53EF\u7528\u7684 Paperclip \u516C\u53F8\u6216\u667A\u80FD\u4F53\u3002\u8BF7\u5148\u5728\u5B9E\u4F8B\u91CC\u521B\u5EFA\u667A\u80FD\u4F53\uFF0C\u518D\u56DE\u6765\u65B0\u589E\u98DE\u4E66\u5165\u53E3\u3002" });
1853
+ return;
1854
+ }
1855
+ const matchType = wizardDraft.matchType;
1856
+ const nextRoute = {
1857
+ id: `feishu-entry-${Date.now().toString(36)}`,
1858
+ connectionId: connection.id,
1859
+ enabled: true,
1860
+ priority: 10,
1861
+ matchType,
1862
+ companyId: company.id,
1863
+ companyRef: company.issuePrefix ?? company.name,
1864
+ targetAgentId: agent.id,
1865
+ targetAgentName: agent.name,
1866
+ replyMode: wizardDraft.replyMode,
1867
+ baseSinkId: wizardDraft.baseSinkId || void 0,
1868
+ ...matchType === "chat" ? { chatId: wizardDraft.chatId ?? "", chatName: wizardDraft.chatName } : {},
1869
+ ...matchType === "user" ? { userOpenId: wizardDraft.userOpenId ?? "", userName: wizardDraft.userName } : {},
1870
+ ...matchType === "keyword" ? { keyword: wizardDraft.keyword || "paperclip" } : {},
1871
+ ...matchType === "regex" ? { regex: wizardDraft.regex ?? "" } : {}
1872
+ };
1873
+ patchConfig({ routes: [...routes, nextRoute] });
1874
+ setShowEntryWizard(false);
1875
+ setNotice({ tone: "success", text: "\u5DF2\u65B0\u589E\u98DE\u4E66\u5165\u53E3\u3002\u4FDD\u5B58\u914D\u7F6E\u540E\uFF0C\u5C31\u53EF\u4EE5\u6309\u8FD9\u4E2A\u5165\u53E3\u63A5\u6536\u98DE\u4E66\u6D88\u606F\u3002" });
1876
+ }
1877
+ async function fixOldBotKeywordRoute() {
1878
+ const routeId = firstEnabledRouteSummary?.route.id;
1879
+ if (!routeId) return;
1880
+ const routeIndex = routes.findIndex((route) => route.id === routeId);
1881
+ if (routeIndex < 0) return;
1882
+ const nextRoutes = routes.map((route, index) => index === routeIndex ? {
1883
+ ...route,
1884
+ matchType: "keyword",
1885
+ keyword: "paperclip",
1886
+ regex: void 0
1887
+ } : route);
1888
+ const nextConfig = normalizeUiConfig({ ...configJson, routes: nextRoutes });
1889
+ setFixingRouteId(routeId);
1890
+ setNotice({ tone: "info", text: "\u6B63\u5728\u628A\u65E7\u89E6\u53D1\u8BCD\u6539\u6210 paperclip..." });
1891
+ try {
1892
+ await save(nextConfig);
1893
+ setConfigJson(nextConfig);
1894
+ setExpandedEntryRouteId(routeId);
1895
+ setNotice({ tone: "success", text: "\u5DF2\u4FDD\u5B58\uFF1A\u8FD9\u4E2A\u5165\u53E3\u73B0\u5728\u6309\u5173\u952E\u8BCD paperclip \u89E6\u53D1\u3002" });
1896
+ } catch (nextError) {
1897
+ setNotice({ tone: "error", text: readableError(nextError) });
1898
+ } finally {
1899
+ setFixingRouteId(null);
1900
+ }
1901
+ }
1902
+ async function startOfficialBindWizard() {
1903
+ const profileName = bindForm.profileName.trim() || suggestedNewProfileName;
1904
+ setStartingGuidedBind(true);
1905
+ setGuidedBindResult(null);
1906
+ setNotice(null);
1907
+ try {
1908
+ const result = await startGuidedBind({
1909
+ profileName,
1910
+ brand: "feishu"
1911
+ });
1912
+ setGuidedBindResult(result);
1913
+ setBindForm((prev) => ({ ...prev, profileName }));
1914
+ setNotice({
1915
+ tone: "info",
1916
+ text: result.url ? "\u5DF2\u751F\u6210\u98DE\u4E66\u6388\u6743\u94FE\u63A5\u3002\u6253\u5F00\u94FE\u63A5\u5B8C\u6210\u540E\uFF0C\u56DE\u5230\u8FD9\u91CC\u70B9\u201C\u6211\u5DF2\u5B8C\u6210\u6388\u6743\u201D\u3002" : "\u5DF2\u542F\u52A8\u98DE\u4E66\u5B98\u65B9\u7ED1\u5B9A\u5411\u5BFC\u3002\u5982\u679C\u6CA1\u6709\u770B\u5230\u94FE\u63A5\uFF0C\u8BF7\u67E5\u770B\u4E0B\u65B9\u8F93\u51FA\u6216\u7A0D\u540E\u5237\u65B0\u5DF2\u7ED1\u5B9A\u5E94\u7528\u3002"
1917
+ });
1918
+ } catch (nextError) {
1919
+ setNotice({ tone: "error", text: readableError(nextError) });
1920
+ } finally {
1921
+ setStartingGuidedBind(false);
1922
+ }
1923
+ }
1924
+ async function finishOfficialBindWizard() {
1925
+ const profileName = bindForm.profileName.trim() || guidedBindResult?.profileName || suggestedNewProfileName;
1926
+ if (!profileName) {
1927
+ setNotice({ tone: "error", text: "\u8BF7\u5148\u83B7\u53D6\u98DE\u4E66\u6388\u6743\u94FE\u63A5\u3002" });
1928
+ return;
1929
+ }
1930
+ setFinishingGuidedBind(true);
1931
+ setNotice(null);
1932
+ try {
1933
+ const result = await finishGuidedBind({ profileName });
1934
+ if (!result.profile?.name) {
1935
+ throw new Error("\u6CA1\u6709\u8BFB\u53D6\u5230\u521A\u521A\u7ED1\u5B9A\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u8BF7\u7A0D\u540E\u5237\u65B0\u518D\u8BD5\u3002");
1936
+ }
1937
+ await addProfileToPool(result.profile);
1938
+ profileCatalog.refresh();
1939
+ setShowBindPanel(false);
1940
+ setNotice({
1941
+ tone: result.warning ? "info" : "success",
1942
+ text: result.warning ?? "\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u786E\u8BA4\u5E76\u52A0\u5165\u5F53\u524D\u914D\u7F6E\u3002\u4E0B\u4E00\u6B65\u53EF\u4EE5\u65B0\u589E\u98DE\u4E66\u5165\u53E3\u3002"
1943
+ });
1944
+ } catch (nextError) {
1945
+ setNotice({ tone: "error", text: readableError(nextError) });
1946
+ } finally {
1947
+ setFinishingGuidedBind(false);
1948
+ }
1949
+ }
1950
+ async function startUserAuthFlow(profileName) {
1951
+ if (!profileName) {
1952
+ setNotice({ tone: "error", text: "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA\u3002" });
1953
+ return;
1954
+ }
1955
+ setStartingUserAuthProfileName(profileName);
1956
+ setNotice({ tone: "info", text: "\u6B63\u5728\u751F\u6210\u98DE\u4E66\u7528\u6237\u6388\u6743\u94FE\u63A5..." });
1957
+ try {
1958
+ const result = await startUserAuth({ profileName });
1959
+ setUserAuthResults((prev) => ({ ...prev, [profileName]: result }));
1960
+ setNotice({
1961
+ tone: "info",
1962
+ text: "\u5DF2\u751F\u6210\u7528\u6237\u6388\u6743\u94FE\u63A5\u3002\u53EA\u6709\u8981\u8BBF\u95EE\u4E2A\u4EBA\u6587\u6863\u3001\u65E5\u5386\u3001\u90AE\u7BB1\u65F6\u624D\u9700\u8981\u8865\uFF1B\u666E\u901A\u673A\u5668\u4EBA\u6536\u53D1\u6D88\u606F\u4E0D\u7528\u8865\u3002"
1963
+ });
1964
+ } catch (nextError) {
1965
+ setNotice({ tone: "error", text: readableError(nextError) });
1966
+ } finally {
1967
+ setStartingUserAuthProfileName(null);
1968
+ }
1969
+ }
1970
+ async function finishUserAuthFlow(profileName) {
1971
+ if (!profileName) {
1972
+ setNotice({ tone: "error", text: "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA\u3002" });
1973
+ return;
1974
+ }
1975
+ setFinishingUserAuthProfileName(profileName);
1976
+ setNotice({ tone: "info", text: "\u6B63\u5728\u786E\u8BA4\u98DE\u4E66\u7528\u6237\u6388\u6743..." });
1977
+ try {
1978
+ const result = await finishUserAuth({ profileName });
1979
+ setUserAuthResults((prev) => {
1980
+ const next = { ...prev };
1981
+ delete next[profileName];
1982
+ return next;
1983
+ });
1984
+ profileCatalog.refresh();
1985
+ const userName = result.profile?.user;
1986
+ setNotice({
1987
+ tone: userName ? "success" : "info",
1988
+ text: userName ? `\u5DF2\u8865\u5145\u7528\u6237\u6388\u6743\uFF1A${userName}\u3002` : "\u5DF2\u786E\u8BA4\u6388\u6743\u6D41\u7A0B\uFF0C\u4F46 lark-cli \u6682\u65F6\u6CA1\u6709\u8FD4\u56DE\u7528\u6237\u59D3\u540D\uFF1B\u673A\u5668\u4EBA\u6536\u53D1\u6D88\u606F\u4E0D\u53D7\u5F71\u54CD\uFF0C\u53EF\u5237\u65B0\u5217\u8868\u518D\u770B\u3002"
1989
+ });
1990
+ } catch (nextError) {
1991
+ setNotice({ tone: "error", text: readableError(nextError) });
1992
+ } finally {
1993
+ setFinishingUserAuthProfileName(null);
1994
+ }
1995
+ }
1996
+ async function bindNewFeishuApp() {
1997
+ const profileName = bindForm.profileName.trim() || suggestedNewProfileName;
1998
+ const displayName = bindForm.displayName.trim() || "\u98DE\u4E66\u673A\u5668\u4EBA";
1999
+ const botAliases = splitBotAliases(bindForm.botAliases || displayName).filter((alias) => !isPlaceholderBotName(alias));
2000
+ const appId = bindForm.appId.trim();
2001
+ const appSecret = bindForm.appSecret.trim();
2002
+ const appSecretRef = bindForm.appSecretRef.trim();
2003
+ if (!appId || !appSecret && !appSecretRef) {
2004
+ setNotice({ tone: "error", text: "\u8BF7\u586B\u5199\u98DE\u4E66 App ID\uFF0C\u5E76\u8F93\u5165 App Secret \u6216 Paperclip Secret Ref\u3002" });
2005
+ return;
2006
+ }
2007
+ setBinding(true);
2008
+ setNotice(null);
2009
+ try {
2010
+ const bindResult = await bindProfile({
2011
+ profileName,
2012
+ appId,
2013
+ appSecret: appSecret || void 0,
2014
+ appSecretRef: appSecret ? void 0 : appSecretRef,
2015
+ brand: "feishu"
2016
+ });
2017
+ const resolvedProfileName = bindResult.profileName?.trim() || profileName;
2018
+ const resolvedAppId = bindResult.appId?.trim() || appId;
2019
+ const existingConnection = connections.find(
2020
+ (connection) => connection.profileName === resolvedProfileName || connection.appId === resolvedAppId
2021
+ );
2022
+ const nextConnection = existingConnection ? {
2023
+ ...existingConnection,
2024
+ profileName: resolvedProfileName,
2025
+ appId: resolvedAppId,
2026
+ name: displayName,
2027
+ botAliases,
2028
+ enabled: true
2029
+ } : connectionFromProfile({
2030
+ index: connections.length,
2031
+ profileName: resolvedProfileName,
2032
+ appId: resolvedAppId,
2033
+ displayName
2034
+ });
2035
+ nextConnection.botAliases = botAliases;
2036
+ const nextConfig = normalizeUiConfig({
2037
+ ...configJson,
2038
+ connections: existingConnection ? connections.map((connection) => connection.id === existingConnection.id ? nextConnection : connection) : [...connections, nextConnection]
2039
+ });
2040
+ await save(nextConfig);
2041
+ setConfigJson(nextConfig);
2042
+ profileCatalog.refresh();
2043
+ setBindForm({
2044
+ displayName: "\u98DE\u4E66\u673A\u5668\u4EBA",
2045
+ botAliases: "",
2046
+ profileName: "",
2047
+ appId: "",
2048
+ appSecret: "",
2049
+ appSecretRef: ""
2050
+ });
2051
+ setShowBindPanel(false);
2052
+ setNotice({
2053
+ tone: "success",
2054
+ text: bindResult.reusedExistingProfile ? `\u8FD9\u4E2A App ID \u5DF2\u7ECF\u7ED1\u5B9A\u8FC7\uFF0C\u5DF2\u590D\u7528\u300C${resolvedProfileName}\u300D\u5E76\u66F4\u65B0\u673A\u5668\u4EBA\u914D\u7F6E\u3002\u4E0B\u4E00\u6B65\u914D\u7F6E\u63A5\u6536\u89C4\u5219\u5373\u53EF\u6D4B\u8BD5\u3002` : "\u98DE\u4E66\u5E94\u7528\u5DF2\u7ED1\u5B9A\uFF0C\u5E76\u5DF2\u6DFB\u52A0\u5230\u201C\u98DE\u4E66\u673A\u5668\u4EBA\u201D\u3002\u4E0B\u4E00\u6B65\u914D\u7F6E\u63A5\u6536\u89C4\u5219\u5373\u53EF\u6D4B\u8BD5\u3002"
2055
+ });
2056
+ } catch (nextError) {
2057
+ setNotice({ tone: "error", text: readableError(nextError) });
2058
+ } finally {
2059
+ setBinding(false);
2060
+ }
2061
+ }
2062
+ async function saveCurrentConfig(options = {}) {
2063
+ setNotice(null);
2064
+ try {
2065
+ await save(configJson);
2066
+ connectorStatus.refresh();
2067
+ const text = options.successText ?? "\u5DF2\u4FDD\u5B58\u3002\u65B0\u7684\u98DE\u4E66\u76D1\u542C\u914D\u7F6E\u4F1A\u81EA\u52A8\u751F\u6548\u3002";
2068
+ if (options.routeId) {
2069
+ setSavedEntry({ routeId: options.routeId, at: (/* @__PURE__ */ new Date()).toLocaleTimeString() });
2070
+ }
2071
+ setToast({ tone: "success", text });
2072
+ setNotice({ tone: "success", text });
2073
+ } catch (nextError) {
2074
+ const text = readableError(nextError);
2075
+ setToast({ tone: "error", text });
2076
+ setNotice({ tone: "error", text });
2077
+ }
2078
+ }
2079
+ async function patchRuntimeAndSave(patch, successText) {
2080
+ const nextConfig = normalizeUiConfig({ ...configJson, ...patch });
2081
+ setNotice(null);
2082
+ try {
2083
+ await save(nextConfig);
2084
+ setConfigJson(nextConfig);
2085
+ connectorStatus.refresh();
2086
+ setToast({ tone: "success", text: successText });
2087
+ setNotice({ tone: "success", text: successText });
2088
+ } catch (nextError) {
2089
+ const text = readableError(nextError);
2090
+ setToast({ tone: "error", text });
2091
+ setNotice({ tone: "error", text });
2092
+ }
2093
+ }
2094
+ function buildCheckReport(result) {
2095
+ const activeSubscriberCount2 = connectorStatus.data?.subscribers?.filter((subscriber) => activeConnections.some((connection) => connection.id === subscriber.connectionId)).length ?? 0;
2096
+ const latestRecord = connectorStatus.data?.recentRecords?.[0];
2097
+ const selectedProfileName = firstRouteConnection?.profileName ?? firstEnabledConnection?.profileName ?? "";
2098
+ const selectedProfile = firstEnabledRouteSummary ? firstRouteProfile : connectedProfile;
2099
+ const selectedConnectionLabel = appLabel(firstRouteConnection ?? firstEnabledConnection, selectedProfile);
2100
+ const routeTargetReady = Boolean(firstEnabledRouteSummary?.company && firstEnabledRouteSummary.agent && firstRouteConnectionReady);
2101
+ const items = [
2102
+ {
2103
+ tone: result.valid ? "success" : "error",
2104
+ title: "Paperclip \u914D\u7F6E",
2105
+ detail: result.valid ? "\u57FA\u7840\u914D\u7F6E\u683C\u5F0F\u6B63\u5E38\uFF0C\u53EF\u4EE5\u7EE7\u7EED\u68C0\u67E5\u98DE\u4E66\u94FE\u8DEF\u3002" : result.message ?? "\u914D\u7F6E\u683C\u5F0F\u68C0\u67E5\u672A\u901A\u8FC7\u3002"
2106
+ }
2107
+ ];
2108
+ if (!hasConnection) {
2109
+ items.push({
2110
+ tone: "error",
2111
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2112
+ detail: "\u8FD8\u6CA1\u6709\u9009\u62E9\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u5148\u70B9\u201C\u66F4\u6362\u201D\u6216\u201C\u7ED1\u5B9A\u65B0\u7684\u201D\u3002"
2113
+ });
2114
+ } else if (profileError) {
2115
+ items.push({
2116
+ tone: "error",
2117
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2118
+ detail: `lark-cli \u8BFB\u53D6\u5931\u8D25\uFF1A${profileError}`
2119
+ });
2120
+ } else if (!selectedProfile) {
2121
+ items.push({
2122
+ tone: "warning",
2123
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2124
+ detail: `\u5F53\u524D\u5165\u53E3\u4F7F\u7528\u201C${selectedConnectionLabel}\u201D\uFF08${selectedProfileName || "\u672A\u914D\u7F6E profile"}\uFF09\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u6CA1\u6709\u8BFB\u5230\u5B83\u3002\u8BF7\u6362\u6210\u53EF\u8FD0\u884C\u673A\u5668\u4EBA\uFF0C\u6216\u91CD\u65B0\u7ED1\u5B9A\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002`
2125
+ });
2126
+ } else if (!selectedProfile.botName && selectedConnectionLabel !== "\u98DE\u4E66\u5E94\u7528" && selectedConnectionLabel !== selectedProfile.name) {
2127
+ items.push({
2128
+ tone: "success",
2129
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2130
+ detail: `\u5DF2\u770B\u5230 ${selectedProfileName}\uFF0C\u9875\u9762\u663E\u793A\u4E3A\u201C${selectedConnectionLabel}\u201D\u3002\u98DE\u4E66\u672A\u8FD4\u56DE\u5B98\u65B9\u673A\u5668\u4EBA\u540D\u65F6\u5148\u7528\u9875\u9762\u540D\u79F0\u5C55\u793A\uFF0C\u4E0D\u5F71\u54CD\u6536\u53D1\u6D88\u606F\u3002`
2131
+ });
2132
+ } else if (!selectedProfile.botName) {
2133
+ items.push({
2134
+ tone: "warning",
2135
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2136
+ detail: `\u5DF2\u770B\u5230 ${selectedProfileName}\uFF0C\u4F46\u6CA1\u6709\u8BFB\u5230\u98DE\u4E66\u673A\u5668\u4EBA\u663E\u793A\u540D\u3002App \u6743\u9650\u6216 token \u53EF\u80FD\u9700\u8981\u786E\u8BA4\u3002`
2137
+ });
2138
+ } else {
2139
+ items.push({
2140
+ tone: "success",
2141
+ title: "\u98DE\u4E66\u673A\u5668\u4EBA",
2142
+ detail: `\u5DF2\u7ED1\u5B9A ${activeConnections.length} \u4E2A\u673A\u5668\u4EBA\uFF1B\u7B2C\u4E00\u6761\u5165\u53E3\u4F7F\u7528\u201C${selectedProfile.botName}\u201D\u3002App ID\uFF1A${maskTechnicalId(selectedProfile.appId ?? firstRouteConnection?.appId)}`
2143
+ });
2144
+ }
2145
+ if (enabledRouteCount === 0) {
2146
+ items.push({
2147
+ tone: "error",
2148
+ title: "\u6D88\u606F\u5165\u53E3",
2149
+ detail: "\u8FD8\u6CA1\u6709\u542F\u7528\u7684\u5165\u53E3\uFF0C\u98DE\u4E66\u6D88\u606F\u4E0D\u4F1A\u8FDB\u5165 Paperclip\u3002"
2150
+ });
2151
+ } else {
2152
+ items.push({
2153
+ tone: routeTargetReady ? "success" : "warning",
2154
+ title: "\u6D88\u606F\u5165\u53E3",
2155
+ detail: !firstRouteConnectionReady ? "\u5165\u53E3\u5B58\u5728\uFF0C\u4F46\u5B83\u7ED1\u5B9A\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u5F53\u524D\u4E0D\u53EF\u8FD0\u884C\u3002\u8BF7\u5148\u70B9\u5165\u53E3\u7684\u201C\u7F16\u8F91\u201D\uFF0C\u628A\u673A\u5668\u4EBA\u6362\u6210\u53EF\u8FD0\u884C\u7684\uFF0C\u6216\u91CD\u65B0\u7ED1\u5B9A\u7F3A\u5931\u673A\u5668\u4EBA\u3002" : routeTargetReady ? `${routeTitle(firstEnabledRouteSummary.route, 0)} \u4F1A\u4EA4\u7ED9 ${routeTargetLabel(firstEnabledRouteSummary.company, firstEnabledRouteSummary.agent)}\u3002` : "\u5165\u53E3\u5B58\u5728\uFF0C\u4F46\u516C\u53F8\u6216\u667A\u80FD\u4F53\u6CA1\u6709\u5B8C\u5168\u5339\u914D\u5230\u3002\u8BF7\u70B9\u201C\u7F16\u8F91\u5165\u53E3\u201D\u786E\u8BA4\u5904\u7406\u4EBA\u3002"
2156
+ });
2157
+ }
2158
+ items.push({
2159
+ tone: routeUsesOldBotKeyword ? "warning" : "success",
2160
+ title: "\u89E6\u53D1\u8BCD",
2161
+ detail: routeUsesOldBotKeyword ? "\u5165\u53E3\u91CC\u8FD8\u6709\u65E7\u89E6\u53D1\u8BCD\u201C\u9510\u601D\u201D\u3002\u5EFA\u8BAE\u70B9\u201C\u4E00\u952E\u6539\u6210 paperclip\u201D\uFF0C\u907F\u514D\u8BEF\u4EE5\u4E3A\u673A\u5668\u4EBA\u6CA1\u6362\u6210\u529F\u3002" : "\u89E6\u53D1\u8BCD\u548C\u5F53\u524D\u673A\u5668\u4EBA\u663E\u793A\u6CA1\u6709\u660E\u663E\u51B2\u7A81\u3002"
2162
+ });
2163
+ if (!isListening) {
2164
+ items.push({
2165
+ tone: "warning",
2166
+ title: "\u76D1\u542C\u98DE\u4E66\u6D88\u606F",
2167
+ detail: "\u76D1\u542C\u5F00\u5173\u672A\u5F00\u542F\u3002\u98DE\u4E66\u91CC\u53D1\u6D88\u606F\u4E0D\u4F1A\u81EA\u52A8\u8FDB\u5165 Paperclip\u3002"
2168
+ });
2169
+ } else if (activeSubscriberCount2 > 0) {
2170
+ items.push({
2171
+ tone: "success",
2172
+ title: "\u76D1\u542C\u98DE\u4E66\u6D88\u606F",
2173
+ detail: `\u76D1\u542C\u5DF2\u5F00\u542F\uFF0C\u5F53\u524D\u770B\u5230 ${activeSubscriberCount2} \u4E2A\u76D1\u542C\u8FDB\u7A0B\u3002`
2174
+ });
2175
+ } else {
2176
+ items.push({
2177
+ tone: "warning",
2178
+ title: "\u76D1\u542C\u98DE\u4E66\u6D88\u606F",
2179
+ detail: "\u76D1\u542C\u5F00\u5173\u5DF2\u5F00\u542F\uFF0C\u4F46\u6682\u65F6\u6CA1\u6709\u770B\u5230\u8FD0\u884C\u4E2D\u7684\u76D1\u542C\u8FDB\u7A0B\u3002\u4FDD\u5B58\u914D\u7F6E\u6216\u91CD\u542F\u670D\u52A1\u540E\u518D\u68C0\u67E5\u3002"
2180
+ });
2181
+ }
2182
+ items.push({
2183
+ tone: isSendingRealMessages ? "success" : "warning",
2184
+ title: "\u771F\u5B9E\u56DE\u590D\u98DE\u4E66",
2185
+ detail: isSendingRealMessages ? "\u5F53\u524D\u4F1A\u771F\u5B9E\u8C03\u7528 lark-cli \u56DE\u590D\u98DE\u4E66\u3002" : "\u5F53\u524D\u662F\u6A21\u62DF\u6A21\u5F0F\uFF0C\u53EA\u4F1A\u5728\u9875\u9762\u91CC\u9A8C\u8BC1\uFF0C\u4E0D\u4F1A\u771F\u7684\u56DE\u98DE\u4E66\u3002"
2186
+ });
2187
+ items.push({
2188
+ tone: isSendingRealMessages ? "success" : "warning",
2189
+ title: "\u98DE\u4E66\u9644\u4EF6\u5165\u5E93",
2190
+ detail: isSendingRealMessages ? "\u98DE\u4E66\u56FE\u7247\u3001\u6587\u4EF6\u3001\u97F3\u9891\u548C\u89C6\u9891\u4F1A\u4E0B\u8F7D\u5E76\u4F5C\u4E3A Paperclip \u4EFB\u52A1\u9644\u4EF6\u4EA4\u7ED9\u667A\u80FD\u4F53\u3002" : "\u6A21\u62DF\u6A21\u5F0F\u53EA\u4F1A\u8BB0\u5F55\u9644\u4EF6\u540D\u79F0\uFF0C\u4E0D\u4F1A\u771F\u6B63\u4E0B\u8F7D\u6216\u4E0A\u4F20\u9644\u4EF6\u3002"
2191
+ });
2192
+ items.push({
2193
+ tone: canTryFeishuSmokeTest ? "success" : "warning",
2194
+ title: "\u98DE\u4E66\u7AEF\u5B9E\u6D4B",
2195
+ detail: canTryFeishuSmokeTest ? `\u53BB\u76EE\u6807\u98DE\u4E66\u4F1A\u8BDD\u53D1\u9001\uFF1A${smokeText}` : "\u673A\u5668\u4EBA\u3001\u5165\u53E3\u3001\u76D1\u542C\u3001\u771F\u5B9E\u56DE\u590D\u5168\u90E8\u5C31\u7EEA\u540E\uFF0C\u518D\u53BB\u98DE\u4E66\u91CC\u505A\u771F\u5B9E\u6D4B\u8BD5\u3002"
2196
+ });
2197
+ if (connectorStatus.error) {
2198
+ items.push({
2199
+ tone: "warning",
2200
+ title: "\u8FD0\u884C\u65E5\u5FD7",
2201
+ detail: `\u72B6\u6001\u8BFB\u53D6\u5931\u8D25\uFF1A${connectorStatus.error.message}`
2202
+ });
2203
+ } else if (latestRecord) {
2204
+ items.push({
2205
+ tone: latestRecord.level === "error" ? "error" : latestRecord.level === "warning" ? "warning" : "success",
2206
+ title: "\u6700\u8FD1\u4E8B\u4EF6",
2207
+ detail: latestRecord.message
2208
+ });
2209
+ } else {
2210
+ items.push({
2211
+ tone: "success",
2212
+ title: "\u6700\u8FD1\u4E8B\u4EF6",
2213
+ detail: "\u6682\u65F6\u6CA1\u6709\u5F02\u5E38\u8BB0\u5F55\u3002"
2214
+ });
2215
+ }
2216
+ return items;
2217
+ }
2218
+ function buildConnectionCheckReport(connection, result) {
2219
+ const profile = profiles.find((item) => item.name === connection.profileName) ?? null;
2220
+ const routeCount = connectionUsageCounts.get(connection.id) ?? 0;
2221
+ const subscriber = connectorStatus.data?.subscribers?.find((item) => item.connectionId === connection.id);
2222
+ const appId = profile?.appId ?? connection.appId;
2223
+ const displayName = appLabel(connection, profile);
2224
+ const hasReadableDisplayName = Boolean(displayName && displayName !== "\u98DE\u4E66\u5E94\u7528" && displayName !== profile?.name);
2225
+ const items = [];
2226
+ if (result && !result.valid) {
2227
+ items.push({
2228
+ tone: "error",
2229
+ title: "Paperclip \u914D\u7F6E",
2230
+ detail: result.message ?? "\u5F53\u524D\u914D\u7F6E\u683C\u5F0F\u6CA1\u6709\u901A\u8FC7\u68C0\u67E5\u3002"
2231
+ });
2232
+ }
2233
+ if (profileError) {
2234
+ items.push({
2235
+ tone: "error",
2236
+ title: "\u6388\u6743\u4FE1\u606F",
2237
+ detail: `\u8BFB\u53D6\u98DE\u4E66\u673A\u5668\u4EBA\u5931\u8D25\uFF1A${profileError}`
2238
+ });
2239
+ } else if (!profile) {
2240
+ items.push({
2241
+ tone: "warning",
2242
+ title: "\u6388\u6743\u4FE1\u606F",
2243
+ detail: missingProfileHelp(connection)
2244
+ });
2245
+ } else {
2246
+ items.push({
2247
+ tone: "success",
2248
+ title: "\u6388\u6743\u4FE1\u606F",
2249
+ detail: `\u5DF2\u8BFB\u5230\u201C${appLabel(connection, profile)}\u201D\u3002${appId ? `App ID\uFF1A${maskTechnicalId(appId)}` : "\u98DE\u4E66\u6CA1\u6709\u8FD4\u56DE App ID\u3002"}`
2250
+ });
2251
+ }
2252
+ if (profile?.botName) {
2253
+ items.push({
2254
+ tone: "success",
2255
+ title: "\u673A\u5668\u4EBA\u540D\u79F0",
2256
+ detail: `\u98DE\u4E66\u8FD4\u56DE\u7684\u673A\u5668\u4EBA\u540D\u79F0\u662F\u201C${profile.botName}\u201D\u3002`
2257
+ });
2258
+ } else if (profile && hasReadableDisplayName) {
2259
+ items.push({
2260
+ tone: "success",
2261
+ title: "\u673A\u5668\u4EBA\u540D\u79F0",
2262
+ detail: `\u5F53\u524D\u9875\u9762\u663E\u793A\u4E3A\u201C${displayName}\u201D\u3002\u98DE\u4E66\u6CA1\u6709\u8FD4\u56DE\u5B98\u65B9\u673A\u5668\u4EBA\u540D\u65F6\uFF0C\u4F1A\u5148\u7528\u8FD9\u4E2A\u9875\u9762\u540D\u79F0\u5C55\u793A\uFF1B\u4E0D\u5F71\u54CD\u6536\u6D88\u606F\u548C\u56DE\u6D88\u606F\u3002`
2263
+ });
2264
+ } else {
2265
+ items.push({
2266
+ tone: "warning",
2267
+ title: "\u673A\u5668\u4EBA\u540D\u79F0",
2268
+ detail: missingBotNameHelp(connection)
2269
+ });
2270
+ }
2271
+ items.push({
2272
+ tone: routeCount > 0 ? "success" : "warning",
2273
+ title: "\u4E1A\u52A1\u5165\u53E3",
2274
+ detail: routeCount > 0 ? `\u5F53\u524D\u6709 ${routeCount} \u6761\u5165\u53E3\u4F7F\u7528\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002` : "\u5F53\u524D\u8FD8\u6CA1\u6709\u5165\u53E3\u4F7F\u7528\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002\u5B83\u5728\u6C60\u5B50\u91CC\uFF0C\u4F46\u4E0D\u4F1A\u5904\u7406\u4EFB\u4F55\u98DE\u4E66\u6D88\u606F\u3002"
2275
+ });
2276
+ if (!isListening) {
2277
+ items.push({
2278
+ tone: "warning",
2279
+ title: "\u76D1\u542C\u72B6\u6001",
2280
+ detail: "\u5168\u5C40\u76D1\u542C\u672A\u5F00\u542F\uFF0C\u98DE\u4E66\u65B0\u6D88\u606F\u4E0D\u4F1A\u81EA\u52A8\u8FDB\u5165 Paperclip\u3002"
2281
+ });
2282
+ } else if (subscriber) {
2283
+ items.push({
2284
+ tone: "success",
2285
+ title: "\u76D1\u542C\u72B6\u6001",
2286
+ detail: `\u5DF2\u770B\u5230\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u76D1\u542C\u8FDB\u7A0B${subscriber.pid ? `\uFF0CPID ${subscriber.pid}` : ""}\u3002`
2287
+ });
2288
+ } else {
2289
+ items.push({
2290
+ tone: "warning",
2291
+ title: "\u76D1\u542C\u72B6\u6001",
2292
+ detail: "\u5168\u5C40\u76D1\u542C\u5DF2\u5F00\u542F\uFF0C\u4F46\u6682\u65F6\u6CA1\u770B\u5230\u8FD9\u4E2A\u673A\u5668\u4EBA\u7684\u76D1\u542C\u8FDB\u7A0B\u3002\u4FDD\u5B58\u914D\u7F6E\u6216\u91CD\u542F\u670D\u52A1\u540E\u518D\u68C0\u67E5\u3002"
2293
+ });
2294
+ }
2295
+ items.push({
2296
+ tone: isSendingRealMessages ? "success" : "warning",
2297
+ title: "\u771F\u5B9E\u56DE\u590D",
2298
+ detail: isSendingRealMessages ? "\u771F\u5B9E\u56DE\u590D\u5DF2\u5F00\u542F\uFF0C\u667A\u80FD\u4F53\u5B8C\u6210\u540E\u4F1A\u56DE\u5230\u98DE\u4E66\u3002" : "\u5F53\u524D\u662F\u9875\u9762\u6A21\u62DF\u6A21\u5F0F\uFF0C\u4E0D\u4F1A\u771F\u5B9E\u56DE\u590D\u98DE\u4E66\u3002"
2299
+ });
2300
+ items.push({
2301
+ tone: isSendingRealMessages ? "success" : "warning",
2302
+ title: "\u9644\u4EF6\u5165\u5E93",
2303
+ detail: isSendingRealMessages ? "\u98DE\u4E66\u6587\u4EF6\u548C\u56FE\u7247\u4F1A\u4F5C\u4E3A Paperclip \u4EFB\u52A1\u9644\u4EF6\u4E0A\u4F20\u3002" : "\u6A21\u62DF\u6A21\u5F0F\u4E0D\u4F1A\u771F\u6B63\u4E0B\u8F7D\u98DE\u4E66\u9644\u4EF6\u3002"
2304
+ });
2305
+ return items;
2306
+ }
2307
+ async function checkConnection(connection) {
2308
+ setCheckingConnectionId(connection.id);
2309
+ setNotice({ tone: "info", text: `\u6B63\u5728\u68C0\u67E5\u201C${appLabel(connection, profiles.find((item) => item.name === connection.profileName))}\u201D...` });
2310
+ try {
2311
+ const result = await test(configJson);
2312
+ profileCatalog.refresh();
2313
+ connectorStatus.refresh();
2314
+ const items = buildConnectionCheckReport(connection, result);
2315
+ setConnectionCheckResults((prev) => ({
2316
+ ...prev,
2317
+ [connection.id]: {
2318
+ checkedAt: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
2319
+ items
2320
+ }
2321
+ }));
2322
+ const hasError = items.some((item) => item.tone === "error");
2323
+ const hasWarning = items.some((item) => item.tone === "warning");
2324
+ setNotice({
2325
+ tone: hasError ? "error" : hasWarning ? "info" : "success",
2326
+ text: hasError ? "\u8FD9\u4E2A\u673A\u5668\u4EBA\u8FD8\u6709\u963B\u585E\u9879\u3002" : hasWarning ? "\u8FD9\u4E2A\u673A\u5668\u4EBA\u57FA\u672C\u53EF\u7528\uFF0C\u4F46\u8FD8\u6709\u9700\u8981\u786E\u8BA4\u7684\u9879\u76EE\u3002" : "\u8FD9\u4E2A\u673A\u5668\u4EBA\u68C0\u67E5\u901A\u8FC7\uFF0C\u53EF\u4EE5\u7528\u4E8E\u98DE\u4E66\u5165\u53E3\u3002"
2327
+ });
2328
+ } catch (nextError) {
2329
+ setNotice({ tone: "error", text: readableError(nextError) });
2330
+ } finally {
2331
+ setCheckingConnectionId(null);
2332
+ }
2333
+ }
2334
+ async function testCurrentConfig() {
2335
+ setChecking(true);
2336
+ setLastCheckAt(null);
2337
+ setNotice({ tone: "info", text: "\u6B63\u5728\u68C0\u67E5\u673A\u5668\u4EBA\u3001\u6D88\u606F\u5165\u53E3\u548C\u8FD0\u884C\u5F00\u5173..." });
2338
+ try {
2339
+ const result = await test(configJson);
2340
+ profileCatalog.refresh();
2341
+ connectorStatus.refresh();
2342
+ const nextReport = buildCheckReport(result);
2343
+ setCheckReportItems(nextReport);
2344
+ setLastCheckAt((/* @__PURE__ */ new Date()).toLocaleTimeString());
2345
+ setNotice({
2346
+ tone: nextReport.some((item) => item.tone === "error") ? "error" : nextReport.some((item) => item.tone === "warning") ? "info" : "success",
2347
+ text: nextReport.some((item) => item.tone === "error") ? "\u68C0\u67E5\u53D1\u73B0\u963B\u585E\u9879\uFF0C\u6309\u4E0B\u65B9\u4F53\u68C0\u62A5\u544A\u5904\u7406\u3002" : nextReport.some((item) => item.tone === "warning") ? "\u57FA\u7840\u94FE\u8DEF\u53EF\u7528\uFF1B\u4E0B\u65B9\u63D0\u9192\u6309\u573A\u666F\u786E\u8BA4\u5373\u53EF\u3002" : "\u68C0\u67E5\u901A\u8FC7\u3002\u4E0B\u4E00\u6B65\u53BB\u98DE\u4E66\u91CC\u53D1\u9001\u6D4B\u8BD5\u8BDD\u672F\u786E\u8BA4\u771F\u5B9E\u6548\u679C\u3002"
2348
+ });
2349
+ } catch (nextError) {
2350
+ setNotice({ tone: "error", text: readableError(nextError) });
2351
+ } finally {
2352
+ setChecking(false);
2353
+ }
2354
+ }
2355
+ async function testEntryRoute(route) {
2356
+ setTestingRouteId(route.id);
2357
+ setNotice(null);
2358
+ setRouteTestResults((prev) => {
2359
+ const next = { ...prev };
2360
+ delete next[route.id];
2361
+ return next;
2362
+ });
2363
+ try {
2364
+ const result = await testRoute({ routeId: route.id });
2365
+ const text = result.message ? `${result.message}${result.sampleText ? ` \u6D4B\u8BD5\u6D88\u606F\uFF1A${result.sampleText}` : ""}` : "\u5165\u53E3\u6D4B\u8BD5\u5B8C\u6210\u3002";
2366
+ setRouteTestResults((prev) => ({
2367
+ ...prev,
2368
+ [route.id]: {
2369
+ tone: result.ok ? "success" : "error",
2370
+ text
2371
+ }
2372
+ }));
2373
+ setNotice({ tone: result.ok ? "success" : "error", text });
2374
+ } catch (nextError) {
2375
+ const text = readableError(nextError);
2376
+ setRouteTestResults((prev) => ({
2377
+ ...prev,
2378
+ [route.id]: { tone: "error", text }
2379
+ }));
2380
+ setNotice({ tone: "error", text });
2381
+ } finally {
2382
+ setTestingRouteId(null);
2383
+ }
2384
+ }
2385
+ async function runPermissionCheck() {
2386
+ setCheckingPermissions(true);
2387
+ setPermissionCheck(null);
2388
+ setNotice({ tone: "info", text: "\u6B63\u5728\u7528 lark-cli \u6821\u9A8C\u5F53\u524D profile \u7684\u98DE\u4E66\u6743\u9650..." });
2389
+ try {
2390
+ const result = await checkPermissions({
2391
+ connectionId: firstRouteConnection?.id ?? preferredConnection?.id
2392
+ });
2393
+ setPermissionCheck(result);
2394
+ setNotice({
2395
+ tone: result.ok ? "success" : "info",
2396
+ text: result.message ?? (result.ok ? "\u6743\u9650\u68C0\u67E5\u901A\u8FC7\u3002" : "\u6743\u9650\u68C0\u67E5\u5B8C\u6210\uFF0C\u4ECD\u6709\u7F3A\u5931\u9879\u3002")
2397
+ });
2398
+ } catch (nextError) {
2399
+ const text = readableError(nextError);
2400
+ setPermissionCheck({ ok: false, message: text });
2401
+ setNotice({ tone: "error", text });
2402
+ } finally {
2403
+ setCheckingPermissions(false);
2404
+ }
2405
+ }
2406
+ async function runRetryQueue() {
2407
+ setRetryingQueue(true);
2408
+ setNotice({ tone: "info", text: "\u6B63\u5728\u91CD\u8BD5\u98DE\u4E66\u5931\u8D25\u6295\u9012..." });
2409
+ try {
2410
+ const result = await retryFailedDeliveries({});
2411
+ connectorStatus.refresh();
2412
+ setNotice({
2413
+ tone: (result.failedCount ?? 0) > 0 ? "info" : "success",
2414
+ text: `\u91CD\u8BD5\u5B8C\u6210\uFF1A\u5C1D\u8BD5 ${result.attemptedCount ?? 0} \u6761\uFF0C\u6210\u529F ${result.successCount ?? 0} \u6761\uFF0C\u5931\u8D25 ${result.failedCount ?? 0} \u6761\u3002`
2415
+ });
2416
+ } catch (nextError) {
2417
+ setNotice({ tone: "error", text: readableError(nextError) });
2418
+ } finally {
2419
+ setRetryingQueue(false);
2420
+ }
2421
+ }
2422
+ if (loading) return /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u8FDE\u63A5\u5668\u914D\u7F6E..." });
2423
+ return /* @__PURE__ */ jsxs("div", { style: pageStyle, children: [
2424
+ /* @__PURE__ */ jsx("nav", { style: tabNavStyle, "aria-label": "\u98DE\u4E66\u8FDE\u63A5\u5668\u9875\u9762\u5BFC\u822A", children: mainTabs.map((tab) => /* @__PURE__ */ jsxs(
2425
+ "button",
2426
+ {
2427
+ type: "button",
2428
+ style: activeMainTab === tab.key ? activeTabLinkStyle : tabLinkStyle,
2429
+ onClick: () => selectMainTab(tab.key),
2430
+ children: [
2431
+ /* @__PURE__ */ jsx("span", { children: tab.label }, "label"),
2432
+ /* @__PURE__ */ jsx("span", { style: tabDetailStyle, children: tab.detail }, "detail")
2433
+ ]
2434
+ },
2435
+ tab.key
2436
+ )) }, "local-tabs"),
2437
+ showBindPanel ? /* @__PURE__ */ jsx(
2438
+ "div",
2439
+ {
2440
+ style: modalBackdropStyle,
2441
+ role: "dialog",
2442
+ "aria-modal": "true",
2443
+ "aria-label": bindPanelTitle,
2444
+ onClick: () => setShowBindPanel(false),
2445
+ children: /* @__PURE__ */ jsxs("div", { style: modalPanelStyle, onClick: (event) => event.stopPropagation(), children: [
2446
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2447
+ /* @__PURE__ */ jsxs("div", { children: [
2448
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "18px" }, children: bindPanelTitle }, "title"),
2449
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u652F\u6301\u4E24\u79CD\u65B9\u5F0F\uFF1A\u666E\u901A\u7528\u6237\u4F18\u5148\u7528\u98DE\u4E66\u6388\u6743\u94FE\u63A5\uFF1B\u7BA1\u7406\u5458\u4E5F\u53EF\u4EE5\u76F4\u63A5\u586B App ID \u548C App Secret\uFF0C\u6216\u586B Paperclip Secret Ref\u3002App Secret \u53EA\u4EA4\u7ED9 lark-cli \u5EFA\u7ACB profile\uFF0C\u4E0D\u4F1A\u4FDD\u5B58\u5230\u63D2\u4EF6\u914D\u7F6E\u91CC\u3002" }, "help")
2450
+ ] }, "copy"),
2451
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => setShowBindPanel(false), children: "\u5173\u95ED" }, "close")
2452
+ ] }, "head"),
2453
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2454
+ /* @__PURE__ */ jsx(
2455
+ "button",
2456
+ {
2457
+ type: "button",
2458
+ style: bindMethod === "guided" ? primaryButtonStyle : buttonStyle,
2459
+ onClick: () => {
2460
+ setBindMethod("guided");
2461
+ setNotice(null);
2462
+ },
2463
+ children: "\u7528\u98DE\u4E66\u6388\u6743\u94FE\u63A5\u7ED1\u5B9A"
2464
+ },
2465
+ "guided"
2466
+ ),
2467
+ /* @__PURE__ */ jsx(
2468
+ "button",
2469
+ {
2470
+ type: "button",
2471
+ style: bindMethod === "secret" ? primaryButtonStyle : buttonStyle,
2472
+ onClick: () => {
2473
+ setBindMethod("secret");
2474
+ setGuidedBindResult(null);
2475
+ setNotice(null);
2476
+ },
2477
+ children: "\u7528 App ID / Secret \u7ED1\u5B9A"
2478
+ },
2479
+ "secret"
2480
+ )
2481
+ ] }, "method"),
2482
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2483
+ /* @__PURE__ */ jsx(Field, { label: "\u7ED9\u8FD9\u4E2A\u673A\u5668\u4EBA\u8D77\u4E2A\u540D\u5B57", help: "\u7ED9\u4EBA\u770B\u7684\u540D\u5B57\uFF0C\u4F8B\u5982\u201C\u8001\u677F\u8D44\u8BAF\u673A\u5668\u4EBA\u201D\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: bindForm.displayName, onChange: (event) => setBindForm((prev) => ({ ...prev, displayName: event.target.value })) }) }, "displayName"),
2484
+ /* @__PURE__ */ jsx(Field, { label: "\u98DE\u4E66\u91CC @ \u5B83\u7684\u540D\u5B57", help: "\u7528\u4E8E\u9632\u6B62 @\u5C0F\u9510 \u65F6\u9510\u601D\u4E5F\u54CD\u5E94\u3002\u53EF\u586B\u591A\u4E2A\uFF0C\u7528\u9017\u53F7\u9694\u5F00\uFF0C\u4F8B\u5982\u201C\u5C0F\u9510, \u9510\u601D\u201D\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: bindForm.botAliases, placeholder: "\u4F8B\u5982\uFF1A\u5C0F\u9510", onChange: (event) => setBindForm((prev) => ({ ...prev, botAliases: event.target.value })) }) }, "botAliases"),
2485
+ /* @__PURE__ */ jsx(Field, { label: "\u5DE5\u7A0B\u6392\u969C\u4EE3\u53F7\uFF08\u53EF\u4E0D\u586B\uFF09", help: "\u9ED8\u8BA4\u81EA\u52A8\u751F\u6210\uFF1B\u666E\u901A\u7528\u6237\u4E0D\u7528\u6539\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: bindForm.profileName || suggestedNewProfileName, onChange: (event) => setBindForm((prev) => ({ ...prev, profileName: event.target.value })) }) }, "profileName")
2486
+ ] }, "fields"),
2487
+ bindMethod === "guided" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2488
+ /* @__PURE__ */ jsxs("div", { style: checklistGridStyle, children: [
2489
+ /* @__PURE__ */ jsx(ChecklistItem, { done: Boolean(guidedBindResult?.url), title: "1 \u83B7\u53D6\u6388\u6743\u94FE\u63A5", detail: "\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u9875\u9762\u5B8C\u6210\u5E94\u7528\u6388\u6743\u3002" }, "one"),
2490
+ /* @__PURE__ */ jsx(ChecklistItem, { done: Boolean(guidedBindResult?.url), title: "2 \u56DE\u5230\u8FD9\u91CC\u786E\u8BA4", detail: "\u6388\u6743\u5B8C\u6210\u540E\u70B9\u201C\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u663E\u793A\u5230\u5217\u8868\u201D\u3002" }, "two"),
2491
+ /* @__PURE__ */ jsx(ChecklistItem, { done: false, title: "3 \u9009\u62E9\u5165\u53E3\u4F7F\u7528", detail: "\u6BCF\u6761\u4E1A\u52A1\u5165\u53E3\u53EF\u4EE5\u5355\u72EC\u9009\u62E9\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002" }, "three")
2492
+ ] }, "steps"),
2493
+ /* @__PURE__ */ jsxs("div", { style: heroCommandStyle, children: [
2494
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900 }, children: "\u666E\u901A\u7528\u6237\u63A8\u8350\uFF1A\u7528\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u94FE\u63A5" }, "title"),
2495
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u4F60\u4E0D\u9700\u8981\u8BB0 App ID\uFF0C\u4E5F\u4E0D\u9700\u8981\u770B\u5230 App Secret\u3002\u70B9\u51FB\u4E0B\u9762\u7684\u201C\u83B7\u53D6\u98DE\u4E66\u6388\u6743\u94FE\u63A5\u201D\uFF0C\u5728\u98DE\u4E66\u9875\u9762\u5B8C\u6210\u6388\u6743\uFF0C\u518D\u56DE\u5230\u8FD9\u91CC\u786E\u8BA4\u5373\u53EF\u3002" }, "body"),
2496
+ /* @__PURE__ */ jsxs("div", { style: flowGridStyle, children: [
2497
+ /* @__PURE__ */ jsx(FlowStep, { title: "1. Paperclip \u751F\u6210\u94FE\u63A5", value: guidedBindResult?.url ? "\u5DF2\u751F\u6210" : "\u5F85\u751F\u6210", detail: "\u94FE\u63A5\u7531\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u7684 lark-cli \u521B\u5EFA\u3002" }, "link"),
2498
+ /* @__PURE__ */ jsx(FlowStep, { title: "2. \u53BB\u98DE\u4E66\u786E\u8BA4", value: "\u626B\u7801\u6216\u6253\u5F00\u94FE\u63A5", detail: "\u5982\u679C\u98DE\u4E66\u8981\u6C42\u7BA1\u7406\u5458\u5BA1\u6279\uFF0C\u9700\u8981\u5148\u5B8C\u6210\u5BA1\u6279\u3002" }, "feishu"),
2499
+ /* @__PURE__ */ jsx(FlowStep, { title: "3. \u56DE\u5230 Paperclip", value: "\u663E\u793A\u5230\u673A\u5668\u4EBA\u6C60", detail: "\u65B0\u673A\u5668\u4EBA\u51FA\u73B0\u540E\uFF0C\u5C31\u53EF\u4EE5\u88AB\u4E0D\u540C\u5165\u53E3\u5206\u522B\u9009\u62E9\u3002" }, "back")
2500
+ ] }, "flow")
2501
+ ] }, "guided-visual"),
2502
+ guidedBindResult?.url ? /* @__PURE__ */ jsxs("div", { style: successBoxStyle, children: [
2503
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u6388\u6743\u94FE\u63A5\u5DF2\u751F\u6210" }, "title"),
2504
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5982\u679C\u98DE\u4E66\u9875\u9762\u5DF2\u7ECF\u5B8C\u6210\u6388\u6743\uFF0C\u5C31\u70B9\u4E0B\u9762\u7684\u786E\u8BA4\u6309\u94AE\u3002" }, "help"),
2505
+ /* @__PURE__ */ jsx("a", { href: guidedBindResult.url, target: "_blank", rel: "noreferrer", style: { ...linkButtonStyle, marginTop: "10px" }, children: "\u6253\u5F00\u98DE\u4E66\u6388\u6743\u94FE\u63A5" }, "url")
2506
+ ] }, "url-box") : null,
2507
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
2508
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u5982\u679C\u5B8C\u6210\u6388\u6743\u540E\u5217\u8868\u91CC\u6CA1\u51FA\u73B0" }, "title"),
2509
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5148\u70B9\u201C\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868\u201D\u3002\u5982\u679C\u8FD8\u662F\u6CA1\u6709\uFF0C\u901A\u5E38\u662F\u98DE\u4E66\u6388\u6743\u6CA1\u6709\u70B9\u5B8C\u3001lark-cli \u6CA1\u628A profile \u5199\u5230\u5F53\u524D\u8FD0\u884C\u73AF\u5883\uFF0C\u6216\u672C\u5730\u6D4B\u8BD5\u548C\u4E91\u670D\u52A1\u5668\u4E0D\u662F\u540C\u4E00\u53F0\u673A\u5668\u3002" }, "help")
2510
+ ] }, "bind-troubleshooting"),
2511
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2512
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, disabled: startingGuidedBind, onClick: () => void startOfficialBindWizard(), children: startingGuidedBind ? "\u6B63\u5728\u751F\u6210..." : "\u83B7\u53D6\u98DE\u4E66\u6388\u6743\u94FE\u63A5" }, "start"),
2513
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: finishingGuidedBind, onClick: () => void finishOfficialBindWizard(), children: finishingGuidedBind ? "\u6B63\u5728\u786E\u8BA4..." : "\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u663E\u793A\u5230\u5217\u8868" }, "finish"),
2514
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: refreshProfilesWithNotice, children: "\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868" }, "refresh"),
2515
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => setShowBindPanel(false), children: "\u53D6\u6D88" }, "cancel")
2516
+ ] }, "actions")
2517
+ ] }, "guided-bind-flow") : /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
2518
+ /* @__PURE__ */ jsxs("div", { style: recommendedBoxStyle, children: [
2519
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u7BA1\u7406\u5458\u76F4\u63A5\u7ED1\u5B9A" }, "title"),
2520
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "App ID \u548C App Secret \u5728\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u7684\u201C\u51ED\u8BC1\u4E0E\u57FA\u7840\u4FE1\u606F\u201D\u91CC\u3002\u4E91\u7AEF\u5EFA\u8BAE\u5148\u628A App Secret \u5B58\u5165 Paperclip Secret/Vault\uFF0C\u518D\u5728\u8FD9\u91CC\u586B Secret Ref\uFF1B\u4FDD\u5B58\u5B8C\u6210\u540E\u63D2\u4EF6\u53EA\u8BB0\u5F55\u673A\u5668\u4EBA\u663E\u793A\u540D\u548C profile \u4EE3\u53F7\uFF0C\u4E0D\u4FDD\u5B58 Secret \u660E\u6587\u3002" }, "body"),
2521
+ /* @__PURE__ */ jsx("a", { href: "https://open.feishu.cn/app", target: "_blank", rel: "noreferrer", style: { ...linkButtonStyle, marginTop: "10px" }, children: "\u6253\u5F00\u98DE\u4E66\u5F00\u653E\u5E73\u53F0" }, "platform")
2522
+ ] }, "secret-help"),
2523
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2524
+ /* @__PURE__ */ jsx(Field, { label: "\u98DE\u4E66 App ID", help: "\u901A\u5E38\u4EE5 cli_ \u5F00\u5934\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: bindForm.appId, placeholder: "cli_xxxxxxxxxxxxx", onChange: (event) => setBindForm((prev) => ({ ...prev, appId: event.target.value })) }) }, "appId"),
2525
+ /* @__PURE__ */ jsx(Field, { label: "\u98DE\u4E66 App Secret", help: "\u53EA\u5728\u672C\u6B21\u7ED1\u5B9A\u65F6\u53D1\u9001\u7ED9 lark-cli\u3002\u4E0D\u8981\u622A\u56FE\u5916\u53D1\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, type: "password", autoComplete: "off", value: bindForm.appSecret, placeholder: "\u8F93\u5165 App Secret", onChange: (event) => setBindForm((prev) => ({ ...prev, appSecret: event.target.value })) }) }, "appSecret"),
2526
+ /* @__PURE__ */ jsx(Field, { label: "Paperclip Secret Ref", help: "\u5982\u679C App Secret \u5DF2\u5728 Paperclip/Vault \u91CC\u6258\u7BA1\uFF0C\u586B\u8FD9\u4E2A\u5F15\u7528\u5373\u53EF\uFF1B\u4E0E\u660E\u6587 Secret \u4E8C\u9009\u4E00\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: bindForm.appSecretRef, placeholder: "\u4F8B\u5982\uFF1Afeishu/app-secret", onChange: (event) => setBindForm((prev) => ({ ...prev, appSecretRef: event.target.value })) }) }, "appSecretRef")
2527
+ ] }, "secret-fields"),
2528
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2529
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, disabled: binding, onClick: () => void bindNewFeishuApp(), children: binding ? "\u6B63\u5728\u7ED1\u5B9A..." : "\u7ACB\u5373\u7ED1\u5B9A\u5E76\u52A0\u5165\u673A\u5668\u4EBA\u6C60" }, "bind"),
2530
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => setShowBindPanel(false), children: "\u53D6\u6D88" }, "cancel")
2531
+ ] }, "actions")
2532
+ ] }, "secret-flow")
2533
+ ] }, "panel")
2534
+ },
2535
+ "bind-modal"
2536
+ ) : null,
2537
+ toast ? /* @__PURE__ */ jsx("div", { style: floatingToastStyle, children: /* @__PURE__ */ jsx(NoticeBanner, { notice: toast }) }, "toast") : null,
2538
+ notice && activeMainTab !== "overview" ? /* @__PURE__ */ jsx(
2539
+ NoticeBanner,
2540
+ {
2541
+ notice,
2542
+ meta: lastCheckAt ? `\u6700\u8FD1\u68C0\u67E5\u65F6\u95F4\uFF1A${lastCheckAt}` : null
2543
+ },
2544
+ "tab-notice"
2545
+ ) : null,
2546
+ activeMainTab === "overview" ? /* @__PURE__ */ jsxs("div", { id: "feishu-overview", style: heroStyle, children: [
2547
+ /* @__PURE__ */ jsxs("div", { style: actionBarStyle, children: [
2548
+ /* @__PURE__ */ jsxs("div", { children: [
2549
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "6px", fontSize: "18px" }, children: overviewTitle }, "intro-title"),
2550
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
2551
+ statusTitle,
2552
+ "\u3002\u591A\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA\u53EF\u4EE5\u540C\u65F6\u5B58\u5728\uFF1B\u6BCF\u6761\u4E1A\u52A1\u5165\u53E3\u5355\u72EC\u9009\u62E9\u673A\u5668\u4EBA\u3001\u516C\u53F8\u548C\u667A\u80FD\u4F53\u3002"
2553
+ ] }, "intro-body")
2554
+ ] }, "copy"),
2555
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2556
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openEntryWizard(), children: "\u65B0\u589E\u5165\u53E3" }, "add-entry"),
2557
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: saving || checking, onClick: () => void testCurrentConfig(), children: checking ? "\u6B63\u5728\u68C0\u67E5..." : "\u68C0\u67E5\u8FDE\u63A5" }, "test"),
2558
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => void copySmokeText(), children: "\u590D\u5236\u6D4B\u8BD5\u8BDD\u672F" }, "copy")
2559
+ ] }, "actions")
2560
+ ] }, "top"),
2561
+ notice ? /* @__PURE__ */ jsx(
2562
+ NoticeBanner,
2563
+ {
2564
+ notice,
2565
+ meta: lastCheckAt ? `\u6700\u8FD1\u68C0\u67E5\u65F6\u95F4\uFF1A${lastCheckAt}` : null
2566
+ },
2567
+ "top-notice"
2568
+ ) : null,
2569
+ checkReportItems.length > 0 ? /* @__PURE__ */ jsx(CheckReport, { items: checkReportItems }, "check-report") : null,
2570
+ /* @__PURE__ */ jsxs("div", { style: nextStepStyle, children: [
2571
+ /* @__PURE__ */ jsxs("div", { children: [
2572
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "16px" }, children: nextStepCopy.title }, "title"),
2573
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: nextStepCopy.detail }, "detail")
2574
+ ] }, "copy"),
2575
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2576
+ nextStepKind === "bind" ? /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openBindPanel(), children: "\u63A5\u5165\u98DE\u4E66\u673A\u5668\u4EBA" }, "bind") : null,
2577
+ nextStepKind === "rebind" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2578
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openBindPanel(connectionToFix ?? firstEnabledConnection), children: "\u91CD\u65B0\u7ED1\u5B9A\u673A\u5668\u4EBA" }, "rebind"),
2579
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: refreshProfilesWithNotice, children: "\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868" }, "refresh")
2580
+ ] }, "next-rebind-actions") : null,
2581
+ nextStepKind === "entry" ? /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openEntryWizard(), children: "\u65B0\u589E\u4E1A\u52A1\u5165\u53E3" }, "entry") : null,
2582
+ nextStepKind === "edit-entry" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2583
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openEntryEditor(firstMissingRouteSummary?.route.id), children: "\u7F16\u8F91\u8FD9\u6761\u5165\u53E3" }, "edit"),
2584
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openBindPanel(connectionToFix ?? void 0), children: "\u91CD\u65B0\u7ED1\u5B9A\u673A\u5668\u4EBA" }, "rebind")
2585
+ ] }, "next-edit-entry-actions") : null,
2586
+ nextStepKind === "enable-listen" ? /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, disabled: saving, onClick: () => void patchRuntimeAndSave({ enableEventSubscriber: true }, "\u5DF2\u5F00\u542F\u98DE\u4E66\u6D88\u606F\u76D1\u542C\u5E76\u4FDD\u5B58\u3002\u73B0\u5728\u53EF\u4EE5\u53BB\u98DE\u4E66\u91CC\u53D1\u6D4B\u8BD5\u8BDD\u672F\u3002"), children: "\u5F00\u542F\u76D1\u542C\u5E76\u4FDD\u5B58" }, "listen") : null,
2587
+ nextStepKind === "enable-real" ? /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, disabled: saving, onClick: () => void patchRuntimeAndSave({ dryRunCli: false }, "\u5DF2\u5F00\u542F\u771F\u5B9E\u98DE\u4E66\u56DE\u590D\u5E76\u4FDD\u5B58\u3002\u4E0B\u4E00\u6B65\u53BB\u98DE\u4E66\u5B9E\u6D4B\u3002"), children: "\u5F00\u542F\u771F\u5B9E\u56DE\u590D\u5E76\u4FDD\u5B58" }, "real") : null,
2588
+ nextStepKind === "test" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2589
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => void copySmokeText(), children: "\u590D\u5236\u98DE\u4E66\u6D4B\u8BD5\u8BDD\u672F" }, "copy"),
2590
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: checking, onClick: () => void testCurrentConfig(), children: checking ? "\u68C0\u67E5\u4E2D..." : "\u68C0\u67E5\u8FDE\u63A5" }, "check")
2591
+ ] }, "next-test-actions") : null
2592
+ ] }, "actions")
2593
+ ] }, "next-step"),
2594
+ /* @__PURE__ */ jsxs("div", { style: metricGridStyle, children: [
2595
+ /* @__PURE__ */ jsxs("div", { style: metricCardStyle, children: [
2596
+ /* @__PURE__ */ jsxs("div", { style: metricHeaderStyle, children: [
2597
+ /* @__PURE__ */ jsx("span", { style: { ...metricIconStyle, background: "color-mix(in oklab, #2563eb 14%, var(--background))", color: "#2563eb" }, children: "\u673A" }, "icon"),
2598
+ /* @__PURE__ */ jsx("span", { children: "\u673A\u5668\u4EBA\u6C60" }, "text")
2599
+ ] }, "label"),
2600
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "22px" }, children: missingProfileConnections.length > 0 ? `${usableConnections.length} \u4E2A\u53EF\u8FD0\u884C / ${activeConnections.length} \u4E2A\u5DF2\u914D\u7F6E` : `${activeConnections.length} \u4E2A\u53EF\u7528` }, "value"),
2601
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: activeConnectionLabels.join("\u3001") || "\u5C1A\u672A\u7ED1\u5B9A\u673A\u5668\u4EBA" }, "detail")
2602
+ ] }, "metric-bots"),
2603
+ /* @__PURE__ */ jsxs("div", { style: metricCardStyle, children: [
2604
+ /* @__PURE__ */ jsxs("div", { style: metricHeaderStyle, children: [
2605
+ /* @__PURE__ */ jsx("span", { style: { ...metricIconStyle, background: "color-mix(in oklab, #16a34a 14%, var(--background))", color: "#16a34a" }, children: "\u5165" }, "icon"),
2606
+ /* @__PURE__ */ jsx("span", { children: "\u4E1A\u52A1\u5165\u53E3" }, "text")
2607
+ ] }, "label"),
2608
+ /* @__PURE__ */ jsxs("div", { style: { fontWeight: 900, fontSize: "22px" }, children: [
2609
+ routes.length,
2610
+ " \u6761\u5165\u53E3"
2611
+ ] }, "value"),
2612
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: routeSummaries.slice(0, 3).map(({ route }, index) => routeTitle(route, index)).join(" / ") || "\u8FD8\u6CA1\u6709\u4E1A\u52A1\u5165\u53E3" }, "detail")
2613
+ ] }, "metric-routes"),
2614
+ /* @__PURE__ */ jsxs("div", { style: metricCardStyle, children: [
2615
+ /* @__PURE__ */ jsxs("div", { style: metricHeaderStyle, children: [
2616
+ /* @__PURE__ */ jsx("span", { style: { ...metricIconStyle, background: "color-mix(in oklab, #22c55e 14%, var(--background))", color: "#16a34a" }, children: "\u542C" }, "icon"),
2617
+ /* @__PURE__ */ jsx("span", { children: "\u8FD0\u884C\u72B6\u6001" }, "text")
2618
+ ] }, "label"),
2619
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "22px" }, children: runtimeStatusLabel }, "value"),
2620
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: runtimeStatusDetail }, "detail")
2621
+ ] }, "metric-runtime")
2622
+ ] }, "metric-grid"),
2623
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
2624
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2625
+ /* @__PURE__ */ jsxs("div", { children: [
2626
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "16px" }, children: "\u6700\u8FD1\u98DE\u4E66\u4E8B\u4EF6\u8BCA\u65AD" }, "title"),
2627
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: latestFeishuEvent ? "\u8FD9\u91CC\u663E\u793A\u6700\u8FD1\u6536\u5230\u7684\u98DE\u4E66\u6D88\u606F\u3001\u547D\u4E2D\u7684\u5165\u53E3\u548C\u672A\u547D\u4E2D\u539F\u56E0\u3002" : "\u5982\u679C\u4F60\u521A\u5728\u98DE\u4E66\u91CC\u53D1\u4E86\u6D4B\u8BD5\u6D88\u606F\uFF0C\u4F46\u8FD9\u91CC\u6CA1\u6709\u65B0\u8BB0\u5F55\uFF0C\u8BF4\u660E\u6D88\u606F\u6CA1\u6709\u8FDB\u5165\u5F53\u524D\u63D2\u4EF6\u76D1\u542C\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u3002" }, "body")
2628
+ ] }, "copy"),
2629
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => connectorStatus.refresh(), children: "\u5237\u65B0" }, "refresh")
2630
+ ] }, "header"),
2631
+ /* @__PURE__ */ jsx(
2632
+ RecentEventList,
2633
+ {
2634
+ records: feishuEventRecords.slice(0, 3),
2635
+ emptyText: feishuEventEmptyText
2636
+ },
2637
+ "events"
2638
+ ),
2639
+ !latestFeishuEvent && latestOperationalRecord ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "8px" }, children: [
2640
+ "\u63D2\u4EF6\u6700\u8FD1\u72B6\u6001\uFF1A",
2641
+ latestOperationalRecord.message,
2642
+ "\uFF08",
2643
+ latestOperationalRecord.createdAt,
2644
+ "\uFF09\u3002"
2645
+ ] }, "latest-operational-record") : null
2646
+ ] }, "event-diagnostics"),
2647
+ /* @__PURE__ */ jsxs("div", { style: heroCommandStyle, children: [
2648
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2649
+ /* @__PURE__ */ jsxs("div", { children: [
2650
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "16px" }, children: "\u63A5\u5165\u8FDB\u5EA6" }, "title"),
2651
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u65B0\u7528\u6237\u53EA\u770B\u8FD9\u91CC\u5C31\u591F\u4E86\uFF1A\u5148\u9009\u673A\u5668\u4EBA\uFF0C\u518D\u5EFA\u4E1A\u52A1\u5165\u53E3\uFF0C\u6700\u540E\u5230\u98DE\u4E66\u91CC\u771F\u5B9E\u6D4B\u8BD5\u3002\u66F4\u591A\u5DE5\u7A0B\u914D\u7F6E\u653E\u5728\u201C\u9AD8\u7EA7\u201D\u9875\u3002" }, "body")
2652
+ ] }, "copy"),
2653
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2654
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openBindPanel(void 0, "guided"), children: "\u7ED1\u5B9A\u673A\u5668\u4EBA" }, "guided"),
2655
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openBindPanel(void 0, "secret"), children: "\u7BA1\u7406\u5458\u7ED1\u5B9A" }, "secret")
2656
+ ] }, "actions")
2657
+ ] }, "header"),
2658
+ /* @__PURE__ */ jsx("div", { style: stepGridStyle, children: setupProgressSteps.map((step, index) => /* @__PURE__ */ jsx(
2659
+ SetupStep,
2660
+ {
2661
+ index: index + 1,
2662
+ done: step.done,
2663
+ title: step.title,
2664
+ detail: step.detail,
2665
+ action: step.action
2666
+ },
2667
+ step.title
2668
+ )) }, "steps")
2669
+ ] }, "setup-progress")
2670
+ ] }, "intro") : null,
2671
+ activeMainTab === "entries" ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("section", { id: "feishu-entries", style: productSectionStyle, children: [
2672
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2673
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "18px" }, children: "\u4E1A\u52A1\u5165\u53E3" }, "title"),
2674
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openEntryWizard(), children: "\u65B0\u589E\u4E1A\u52A1\u5165\u53E3" }, "add")
2675
+ ] }, "header"),
2676
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
2677
+ routeSummaries.length === 0 ? /* @__PURE__ */ jsxs("div", { style: productEntryStyle, children: [
2678
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u8FD8\u6CA1\u6709\u4E1A\u52A1\u5165\u53E3" }, "title"),
2679
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5148\u5EFA\u4E00\u6761\u201C\u5305\u542B paperclip \u7684\u98DE\u4E66\u6D88\u606F \u2192 \u6307\u5B9A\u667A\u80FD\u4F53\u201D\u7684\u6D4B\u8BD5\u5165\u53E3\u3002" }, "body")
2680
+ ] }, "empty") : null,
2681
+ routeSummaries.map(({ route, company, agent }, index) => {
2682
+ const routeIndex = routes.findIndex((item) => item.id === route.id);
2683
+ const connection = connections.find((item) => item.id === route.connectionId) ?? preferredConnection;
2684
+ const profile = profiles.find((item) => item.name === connection?.profileName) ?? null;
2685
+ const testResult = routeTestResults[route.id];
2686
+ const agents = company?.agents ?? [];
2687
+ const matchType = route.matchType ?? "keyword";
2688
+ return /* @__PURE__ */ jsxs("div", { id: `product-entry-${route.id}`, style: productEntryStyle, children: [
2689
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2690
+ /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
2691
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2692
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: "16px" }, children: routeTitle(route, index) }, "title"),
2693
+ /* @__PURE__ */ jsx(StatusBadge, { tone: route.enabled === false ? "neutral" : "success", children: route.enabled === false ? "\u5DF2\u6682\u505C" : "\u542F\u7528\u4E2D" }, "status")
2694
+ ] }, "title-row"),
2695
+ /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "6px" }, children: [
2696
+ "\u6765\u6E90\uFF1A",
2697
+ routeSourceLabel(route),
2698
+ " \u2192 \u673A\u5668\u4EBA\uFF1A",
2699
+ appLabel(connection, profile),
2700
+ " \u2192 \u516C\u53F8\uFF1A",
2701
+ company ? companyLabel(company) : "\u672A\u9009\u62E9",
2702
+ " \u2192 \u667A\u80FD\u4F53\uFF1A",
2703
+ agent ? agentLabel(agent) : "\u672A\u9009\u62E9"
2704
+ ] }, "meta")
2705
+ ] }, "copy"),
2706
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2707
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: testingRouteId === route.id, onClick: () => void testEntryRoute(route), children: testingRouteId === route.id ? "\u6D4B\u8BD5\u4E2D..." : "\u6D4B\u8BD5" }, "test"),
2708
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openEntryEditor(route.id), children: "\u7F16\u8F91" }, "edit"),
2709
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => routeIndex >= 0 && patchRoute(routeIndex, { enabled: route.enabled === false }), children: route.enabled === false ? "\u542F\u7528" : "\u6682\u505C" }, "pause")
2710
+ ] }, "actions")
2711
+ ] }, "top"),
2712
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2713
+ /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
2714
+ "\u89E6\u53D1\u6761\u4EF6\u3000",
2715
+ routeSourceLabel(route)
2716
+ ] }, "source"),
2717
+ /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
2718
+ "\u56DE\u590D\u65B9\u5F0F\u3000",
2719
+ replyModeLabels[route.replyMode ?? "thread"]
2720
+ ] }, "reply"),
2721
+ route.baseSinkId ? /* @__PURE__ */ jsx("span", { style: compactPillStyle, children: "\u5199\u5165\u591A\u7EF4\u8868\u683C" }, "base") : null
2722
+ ] }, "chips"),
2723
+ testResult ? /* @__PURE__ */ jsx("div", { style: { ...helpStyle, color: testResult.tone === "success" ? "var(--foreground)" : "var(--destructive)" }, children: testResult.text }, "result") : null,
2724
+ expandedEntryRouteId === route.id && routeIndex >= 0 ? /* @__PURE__ */ jsxs("div", { style: productEntryEditorStyle, children: [
2725
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2726
+ /* @__PURE__ */ jsxs("div", { children: [
2727
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u7F16\u8F91\u8FD9\u4E2A\u5165\u53E3" }, "title"),
2728
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u53EA\u6539\u8FD9\u6761\u4E1A\u52A1\u5165\u53E3\uFF0C\u4E0D\u5F71\u54CD\u5176\u4ED6\u98DE\u4E66\u673A\u5668\u4EBA\u548C\u5176\u4ED6\u516C\u53F8\u3002" }, "help")
2729
+ ] }, "copy"),
2730
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => setExpandedEntryRouteId(null), children: "\u6536\u8D77" }, "close")
2731
+ ] }, "editor-head"),
2732
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2733
+ /* @__PURE__ */ jsx(Field, { label: "\u4F7F\u7528\u54EA\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA", children: /* @__PURE__ */ jsx(
2734
+ "select",
2735
+ {
2736
+ style: selectStyle,
2737
+ value: route.connectionId ?? preferredConnection?.id ?? "",
2738
+ onChange: (event) => patchRoute(routeIndex, { connectionId: event.target.value }),
2739
+ children: connectionOptionNodes(connections, `product-route-${routeIndex}`, void 0, profiles)
2740
+ }
2741
+ ) }, "connectionId"),
2742
+ /* @__PURE__ */ jsx(Field, { label: "\u54EA\u4E9B\u6D88\u606F\u8FDB\u5165 Paperclip", children: /* @__PURE__ */ jsx(
2743
+ "select",
2744
+ {
2745
+ style: selectStyle,
2746
+ value: matchType,
2747
+ onChange: (event) => patchRoute(routeIndex, { matchType: event.target.value }),
2748
+ children: Object.entries(matchTypeLabels).map(([value, label], optionIndex) => /* @__PURE__ */ jsx("option", { value, children: label }, `product-match-${routeIndex}-${optionIndex}-${value}`))
2749
+ }
2750
+ ) }, "matchType"),
2751
+ matchType === "keyword" ? /* @__PURE__ */ jsx(Field, { label: "\u5173\u952E\u8BCD\uFF08\u4E0D\u533A\u5206\u5927\u5C0F\u5199\uFF09", help: "\u4E0D\u662F\u5FC5\u987B\u586B paperclip\u3002\u53EF\u4EE5\u586B\u201C\u5C0F\u601D\u201D\u201C\u627E\u4EBA\u201D\u201C\u8D44\u8BAF\u201D\u7B49\u4E1A\u52A1\u8BCD\uFF1B\u6D88\u606F\u91CC\u5305\u542B\u5B83\u5C31\u4F1A\u8FDB\u5165 Paperclip\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: route.keyword ?? "", onChange: (event) => patchRoute(routeIndex, { keyword: event.target.value }) }) }, "keyword") : null,
2752
+ matchType === "regex" ? /* @__PURE__ */ jsx(Field, { label: "\u9AD8\u7EA7\u89C4\u5219", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: route.regex ?? "", onChange: (event) => patchRoute(routeIndex, { regex: event.target.value }) }) }, "regex") : null,
2753
+ /* @__PURE__ */ jsx(Field, { label: "Paperclip \u516C\u53F8", children: /* @__PURE__ */ jsx(
2754
+ "select",
2755
+ {
2756
+ style: selectStyle,
2757
+ value: company?.id ?? "",
2758
+ onChange: (event) => {
2759
+ const nextCompany = companies.find((item) => item.id === event.target.value);
2760
+ const nextAgent = nextCompany?.agents[0];
2761
+ patchRoute(routeIndex, {
2762
+ companyId: nextCompany?.id,
2763
+ companyRef: nextCompany?.issuePrefix ?? nextCompany?.name,
2764
+ targetAgentId: nextAgent?.id,
2765
+ targetAgentName: nextAgent?.name
2766
+ });
2767
+ },
2768
+ children: companyOptionNodes(companies, `product-route-${routeIndex}`)
2769
+ }
2770
+ ) }, "company"),
2771
+ /* @__PURE__ */ jsx(Field, { label: "\u4EA4\u7ED9\u54EA\u4E2A\u667A\u80FD\u4F53", children: /* @__PURE__ */ jsx(
2772
+ "select",
2773
+ {
2774
+ style: selectStyle,
2775
+ value: agent?.id ?? "",
2776
+ disabled: !company,
2777
+ onChange: (event) => {
2778
+ const nextAgent = agents.find((item) => item.id === event.target.value);
2779
+ patchRoute(routeIndex, {
2780
+ targetAgentId: nextAgent?.id,
2781
+ targetAgentName: nextAgent?.name
2782
+ });
2783
+ },
2784
+ children: agentOptionNodes(agents, `product-route-${routeIndex}`)
2785
+ }
2786
+ ) }, "agent"),
2787
+ /* @__PURE__ */ jsx(Field, { label: "\u56DE\u590D\u65B9\u5F0F", children: /* @__PURE__ */ jsx(
2788
+ "select",
2789
+ {
2790
+ style: selectStyle,
2791
+ value: route.replyMode ?? "thread",
2792
+ onChange: (event) => patchRoute(routeIndex, { replyMode: event.target.value }),
2793
+ children: Object.entries(replyModeLabels).map(([value, label], optionIndex) => /* @__PURE__ */ jsx("option", { value, children: label }, `product-reply-${routeIndex}-${optionIndex}-${value}`))
2794
+ }
2795
+ ) }, "replyMode")
2796
+ ] }, "editor-fields"),
2797
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2798
+ /* @__PURE__ */ jsx(
2799
+ "button",
2800
+ {
2801
+ type: "button",
2802
+ style: primaryButtonStyle,
2803
+ disabled: saving,
2804
+ onClick: () => void saveCurrentConfig({
2805
+ routeId: route.id,
2806
+ successText: `\u5DF2\u4FDD\u5B58\u5165\u53E3\u201C${routeTitle(route, routeIndex)}\u201D\u3002\u65B0\u7684\u98DE\u4E66\u6D88\u606F\u4F1A\u6309\u8FD9\u4E2A\u5165\u53E3\u5904\u7406\u3002`
2807
+ }),
2808
+ children: saving ? "\u6B63\u5728\u4FDD\u5B58..." : "\u4FDD\u5B58\u8FD9\u4E2A\u5165\u53E3"
2809
+ },
2810
+ "save"
2811
+ ),
2812
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: testingRouteId === route.id, onClick: () => void testEntryRoute(route), children: testingRouteId === route.id ? "\u6D4B\u8BD5\u4E2D..." : "\u6D4B\u8BD5\u8FD9\u4E2A\u5165\u53E3" }, "test")
2813
+ ] }, "editor-actions"),
2814
+ savedEntry?.routeId === route.id ? /* @__PURE__ */ jsxs("div", { style: { ...successBoxStyle, marginTop: "2px" }, children: [
2815
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u8FD9\u4E2A\u5165\u53E3\u5DF2\u4FDD\u5B58" }, "title"),
2816
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
2817
+ "\u4FDD\u5B58\u65F6\u95F4\uFF1A",
2818
+ savedEntry.at,
2819
+ "\u3002\u73B0\u5728\u98DE\u4E66\u6D88\u606F\u4F1A\u4EA4\u7ED9 ",
2820
+ routeTargetLabel(company, agent),
2821
+ " \u5904\u7406\u3002"
2822
+ ] }, "detail")
2823
+ ] }, "entry-save-ok") : null
2824
+ ] }, "editor") : null
2825
+ ] }, `product-entry-${route.id}`);
2826
+ })
2827
+ ] }, "list")
2828
+ ] }, "product-entries") }, "entries-list-tab") : null,
2829
+ activeMainTab === "robots" ? /* @__PURE__ */ jsxs("section", { id: "feishu-robots", style: productSectionStyle, children: [
2830
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2831
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "18px" }, children: "\u673A\u5668\u4EBA\u6C60" }, "title"),
2832
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openBindPanel(), children: "\u7ED1\u5B9A\u65B0\u673A\u5668\u4EBA" }, "bind")
2833
+ ] }, "header"),
2834
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2835
+ activeConnections.length === 0 ? /* @__PURE__ */ jsxs("div", { style: productEntryStyle, children: [
2836
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u8FD8\u6CA1\u6709\u53EF\u7528\u673A\u5668\u4EBA" }, "title"),
2837
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u7ED1\u5B9A\u516C\u53F8\u901A\u7528\u673A\u5668\u4EBA\u540E\uFF0C\u518D\u4E3A\u4E1A\u52A1\u5165\u53E3\u9009\u62E9\u5B83\u3002" }, "body")
2838
+ ] }, "empty") : null,
2839
+ activeConnections.map((connection, index) => {
2840
+ const profile = profiles.find((item) => item.name === connection.profileName) ?? null;
2841
+ const routeCount = connectionUsageCounts.get(connection.id) ?? 0;
2842
+ const connectionCheck = connectionCheckResults[connection.id];
2843
+ const authResult = userAuthResults[connection.profileName];
2844
+ const isStartingUserAuth = startingUserAuthProfileName === connection.profileName;
2845
+ const isFinishingUserAuth = finishingUserAuthProfileName === connection.profileName;
2846
+ const aliasText = formatBotAliases(connection);
2847
+ return /* @__PURE__ */ jsxs("div", { style: productEntryStyle, children: [
2848
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "14px", alignItems: "center" }, children: [
2849
+ /* @__PURE__ */ jsx("div", { style: { ...botIconStyle, background: index % 2 === 0 ? "#2563eb" : "#5b21b6", color: "#fff" }, children: "\u98DE" }, "icon"),
2850
+ /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
2851
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginBottom: "4px" }, children: [
2852
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: "16px" }, children: appLabel(connection, profile) }, "label"),
2853
+ /* @__PURE__ */ jsx(StatusBadge, { tone: profile ? "success" : "warning", children: profile ? "\u5DF2\u542F\u7528" : "\u9700\u91CD\u65B0\u7ED1\u5B9A" }, "status"),
2854
+ /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
2855
+ routeCount,
2856
+ " \u6761\u5165\u53E3\u4F7F\u7528"
2857
+ ] }, "count")
2858
+ ] }, "name"),
2859
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
2860
+ "App ID\uFF1A",
2861
+ maskTechnicalId(connection.appId ?? profile?.appId)
2862
+ ] }, "appid"),
2863
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: profile ? profileAuthLabel(profile) : "\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u672A\u8BFB\u5230\u8FD9\u4E2A\u673A\u5668\u4EBA profile" }, "user"),
2864
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: profile ? profileAuthDetail(profile) : missingProfileHelp(connection) }, "auth-detail"),
2865
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "6px", marginTop: "8px" }, children: [
2866
+ /* @__PURE__ */ jsx("label", { style: { fontWeight: 700 }, children: "\u98DE\u4E66\u91CC @ \u5B83\u7684\u540D\u5B57" }, "label"),
2867
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, alignItems: "stretch" }, children: [
2868
+ /* @__PURE__ */ jsx(
2869
+ "input",
2870
+ {
2871
+ style: { ...inputStyle, minWidth: "220px" },
2872
+ value: aliasText,
2873
+ placeholder: `\u4F8B\u5982\uFF1A${profile?.botName || appLabel(connection, profile)}`,
2874
+ onChange: (event) => patchConnectionById(connection.id, { botAliases: splitBotAliases(event.target.value) })
2875
+ },
2876
+ "input"
2877
+ ),
2878
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: saving, onClick: () => void saveCurrentConfig({ successText: "\u5DF2\u4FDD\u5B58\u673A\u5668\u4EBA @ \u540D\u79F0\u3002\u4E4B\u540E\u4F1A\u7528\u5B83\u5224\u65AD\u662F\u4E0D\u662F @ \u4E86\u5F53\u524D\u673A\u5668\u4EBA\u3002" }), children: "\u4FDD\u5B58 @ \u540D\u79F0" }, "save-alias")
2879
+ ] }, "row"),
2880
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u586B\u5199\u98DE\u4E66\u91CC @ \u5B83\u65F6\u770B\u5230\u7684\u540D\u5B57\uFF0C\u4F8B\u5982\u201C\u5C0F\u9510\u201D\u3002\u5982\u679C\u98DE\u4E66\u6CA1\u6709\u8FD4\u56DE\u5B98\u65B9\u673A\u5668\u4EBA\u540D\uFF0C\u8FD9\u4E2A\u540D\u5B57\u4F1A\u7528\u6765\u9632\u6B62 @\u5C0F\u9510 \u65F6\u9510\u601D\u4E5F\u54CD\u5E94\u3002" }, "help")
2881
+ ] }, "aliases"),
2882
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
2883
+ "\u72B6\u6001\uFF1A",
2884
+ profile ? "\u53EF\u53D1\u9001 / \u53EF\u76D1\u542C" : "\u5F53\u524D\u4E0D\u53EF\u8FD0\u884C\uFF0C\u5148\u91CD\u65B0\u7ED1\u5B9A\u6216\u6362\u7528\u5176\u4ED6\u673A\u5668\u4EBA"
2885
+ ] }, "state")
2886
+ ] }, "copy")
2887
+ ] }, "top"),
2888
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2889
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => selectMainTab("entries"), children: "\u67E5\u770B\u5165\u53E3" }, "entries"),
2890
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: checkingConnectionId === connection.id, onClick: () => void checkConnection(connection), children: checkingConnectionId === connection.id ? "\u68C0\u67E5\u4E2D..." : "\u68C0\u67E5\u8FD9\u4E2A\u673A\u5668\u4EBA" }, "check"),
2891
+ profile && !profile.user ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: isStartingUserAuth, onClick: () => void startUserAuthFlow(connection.profileName), children: isStartingUserAuth ? "\u751F\u6210\u4E2D..." : "\u8BBF\u95EE\u4E2A\u4EBA\u8D44\u6E90\u65F6\u6388\u6743" }, "user-auth") : null,
2892
+ !profile ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: refreshProfilesWithNotice, children: "\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868" }, "refresh") : null,
2893
+ !profile ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => openBindPanel(connection), children: "\u91CD\u65B0\u7ED1\u5B9A" }, "rebind") : null
2894
+ ] }, "actions"),
2895
+ authResult?.url ? /* @__PURE__ */ jsxs("div", { style: successBoxStyle, children: [
2896
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u9700\u8981\u8BBF\u95EE\u4E2A\u4EBA\u8D44\u6E90\u65F6\uFF0C\u6253\u5F00\u8FD9\u4E2A\u94FE\u63A5\u6388\u6743" }, "title"),
2897
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6536\u53D1\u98DE\u4E66\u6D88\u606F\u4E0D\u9700\u8981\u8FD9\u4E00\u6B65\u3002\u53EA\u6709\u8BA9\u673A\u5668\u4EBA\u8BBF\u95EE\u4F60\u7684\u4E2A\u4EBA\u4E91\u6587\u6863\u3001\u65E5\u5386\u3001\u90AE\u7BB1\u7B49\u8D44\u6E90\u65F6\u624D\u9700\u8981\u4E2A\u4EBA\u6388\u6743\u3002" }, "help"),
2898
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "10px" }, children: [
2899
+ /* @__PURE__ */ jsx("a", { href: authResult.url, target: "_blank", rel: "noreferrer", style: linkButtonStyle, children: "\u6253\u5F00\u6388\u6743\u94FE\u63A5" }, "open"),
2900
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: isFinishingUserAuth, onClick: () => void finishUserAuthFlow(connection.profileName), children: isFinishingUserAuth ? "\u786E\u8BA4\u4E2D..." : "\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u5237\u65B0\u72B6\u6001" }, "finish")
2901
+ ] }, "actions")
2902
+ ] }, "user-auth-result") : null,
2903
+ connectionCheck ? /* @__PURE__ */ jsx(InlineCheckReport, { items: connectionCheck.items, checkedAt: connectionCheck.checkedAt }, "check-result") : null
2904
+ ] }, `product-bot-${connection.id}-${index}`);
2905
+ })
2906
+ ] }, "cards"),
2907
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u673A\u5668\u4EBA\u53EA\u662F\u8D26\u53F7\u6C60\uFF1B\u771F\u6B63\u7528\u54EA\u4E2A\u673A\u5668\u4EBA\uFF0C\u5728\u6BCF\u6761\u5165\u53E3\u91CC\u9009\u62E9\u3002" }, "hint")
2908
+ ] }, "product-robots") : null,
2909
+ activeMainTab === "entries" ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("section", { id: "feishu-entry-wizard", style: productSectionStyle, children: [
2910
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
2911
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "18px" }, children: "\u65B0\u589E\u4E1A\u52A1\u5165\u53E3" }, "title"),
2912
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => showEntryWizard ? setShowEntryWizard(false) : openEntryWizard(), children: showEntryWizard ? "\u6536\u8D77" : "\u6253\u5F00\u5411\u5BFC" }, "toggle")
2913
+ ] }, "header"),
2914
+ !showEntryWizard ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
2915
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u9700\u8981\u65B0\u589E\u5165\u53E3\u65F6\u518D\u6253\u5F00\u5411\u5BFC" }, "title"),
2916
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u73B0\u6709\u5165\u53E3\u5DF2\u7ECF\u5728\u4E0A\u9762\u5C55\u793A\u3002\u65B0\u589E\u5165\u53E3\u4F1A\u8BA9\u53E6\u4E00\u7C7B\u98DE\u4E66\u6D88\u606F\u8FDB\u5165 Paperclip\uFF0C\u5E76\u6307\u5B9A\u673A\u5668\u4EBA\u3001\u516C\u53F8\u3001\u667A\u80FD\u4F53\u548C\u56DE\u590D\u65B9\u5F0F\u3002" }, "help")
2917
+ ] }, "collapsed") : null,
2918
+ /* @__PURE__ */ jsxs("div", { style: { ...wizardStepperStyle, display: showEntryWizard ? "grid" : "none" }, children: [
2919
+ /* @__PURE__ */ jsx(FlowStep, { title: "1 \u9009\u62E9\u6D88\u606F\u6765\u6E90", value: matchTypeLabels[wizardDraft.matchType], detail: "\u7FA4/\u5355\u804A/\u53D1\u6D88\u606F\u4EBA/\u5173\u952E\u8BCD" }, "source"),
2920
+ /* @__PURE__ */ jsx(FlowStep, { title: "2 \u9009\u62E9\u673A\u5668\u4EBA", value: appLabel(connections.find((connection) => connection.id === wizardDraft.connectionId) ?? preferredConnection, profiles.find((profile) => profile.name === (connections.find((connection) => connection.id === wizardDraft.connectionId) ?? preferredConnection)?.profileName)), detail: "\u4ECE\u673A\u5668\u4EBA\u6C60\u91CC\u6311\u9009" }, "bot"),
2921
+ /* @__PURE__ */ jsx(FlowStep, { title: "3 \u9009\u62E9 Paperclip \u516C\u53F8\u548C\u667A\u80FD\u4F53", value: (() => {
2922
+ const company = companies.find((item) => item.id === wizardDraft.companyId) ?? firstEnabledRouteSummary?.company ?? companies[0] ?? null;
2923
+ const agent = company?.agents.find((item) => item.id === wizardDraft.targetAgentId) ?? (company?.id === firstEnabledRouteSummary?.company?.id ? firstEnabledRouteSummary.agent : null) ?? company?.agents[0] ?? null;
2924
+ return routeTargetLabel(company, agent);
2925
+ })(), detail: "\u6307\u5B9A\u516C\u53F8\u4E0E\u667A\u80FD\u4F53\u5904\u7406" }, "agent"),
2926
+ /* @__PURE__ */ jsx(FlowStep, { title: "4 \u56DE\u590D\u4E0E\u6C89\u6DC0", value: replyModeLabels[wizardDraft.replyMode], detail: "\u56DE\u590D\u65B9\u5F0F\u4E0E\u5199\u5165\u89C4\u5219" }, "reply")
2927
+ ] }, "steps"),
2928
+ /* @__PURE__ */ jsxs("div", { style: { display: showEntryWizard ? "grid" : "none", gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))", gap: "10px" }, children: [
2929
+ /* @__PURE__ */ jsx(Field, { label: "\u6D88\u606F\u6765\u6E90", children: /* @__PURE__ */ jsx("select", { style: selectStyle, value: wizardDraft.matchType, onChange: (event) => patchWizardDraft({ matchType: event.target.value }), children: Object.entries(matchTypeLabels).map(([value, label], optionIndex) => /* @__PURE__ */ jsx("option", { value, children: label }, `product-wizard-match-${optionIndex}-${value}`)) }) }, "matchType"),
2930
+ /* @__PURE__ */ jsx(Field, { label: "\u98DE\u4E66\u673A\u5668\u4EBA", children: /* @__PURE__ */ jsx("select", { style: selectStyle, value: wizardDraft.connectionId ?? preferredConnection?.id ?? "", onChange: (event) => patchWizardDraft({ connectionId: event.target.value }), children: connectionOptionNodes(activeConnections.length > 0 ? activeConnections : connections, "product-wizard-connection", void 0, profiles) }) }, "connection"),
2931
+ /* @__PURE__ */ jsx(Field, { label: "Paperclip \u516C\u53F8", children: /* @__PURE__ */ jsx(
2932
+ "select",
2933
+ {
2934
+ style: selectStyle,
2935
+ value: (companies.find((item) => item.id === wizardDraft.companyId) ?? firstEnabledRouteSummary?.company ?? companies[0])?.id ?? "",
2936
+ onChange: (event) => {
2937
+ const nextCompany = companies.find((item) => item.id === event.target.value);
2938
+ const nextAgent = nextCompany?.agents[0];
2939
+ patchWizardDraft({ companyId: nextCompany?.id, targetAgentId: nextAgent?.id });
2940
+ },
2941
+ children: companyOptionNodes(companies, "product-wizard-company")
2942
+ }
2943
+ ) }, "company"),
2944
+ /* @__PURE__ */ jsx(Field, { label: "\u667A\u80FD\u4F53", children: (() => {
2945
+ const company = companies.find((item) => item.id === wizardDraft.companyId) ?? firstEnabledRouteSummary?.company ?? companies[0] ?? null;
2946
+ const agents = company?.agents ?? [];
2947
+ const agent = agents.find((item) => item.id === wizardDraft.targetAgentId) ?? (company?.id === firstEnabledRouteSummary?.company?.id ? firstEnabledRouteSummary.agent : null) ?? agents[0] ?? null;
2948
+ return /* @__PURE__ */ jsx("select", { style: selectStyle, value: agent?.id ?? "", disabled: !company, onChange: (event) => patchWizardDraft({ targetAgentId: event.target.value }), children: agentOptionNodes(agents, "product-wizard-agent") });
2949
+ })() }, "agent"),
2950
+ /* @__PURE__ */ jsx(Field, { label: "\u56DE\u590D\u65B9\u5F0F", children: /* @__PURE__ */ jsx("select", { style: selectStyle, value: wizardDraft.replyMode, onChange: (event) => patchWizardDraft({ replyMode: event.target.value }), children: Object.entries(replyModeLabels).map(([value, label], optionIndex) => /* @__PURE__ */ jsx("option", { value, children: label }, `product-wizard-reply-${optionIndex}-${value}`)) }) }, "reply")
2951
+ ] }, "compact-fields"),
2952
+ showEntryWizard ? /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
2953
+ wizardDraft.matchType === "keyword" ? /* @__PURE__ */ jsx(Field, { label: "\u5173\u952E\u8BCD\uFF08\u4E0D\u533A\u5206\u5927\u5C0F\u5199\uFF09", help: "\u4E0D\u662F\u5FC5\u987B\u586B paperclip\u3002\u53EF\u4EE5\u586B\u201C\u5C0F\u601D\u201D\u201C\u627E\u4EBA\u201D\u201C\u8D44\u8BAF\u201D\u7B49\u4E1A\u52A1\u8BCD\uFF1B\u6D88\u606F\u91CC\u5305\u542B\u5B83\u5C31\u4F1A\u8FDB\u5165 Paperclip\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: wizardDraft.keyword ?? "", onChange: (event) => patchWizardDraft({ keyword: event.target.value }) }) }, "keyword") : null,
2954
+ wizardDraft.matchType === "regex" ? /* @__PURE__ */ jsx(Field, { label: "\u9AD8\u7EA7\u89C4\u5219", help: "\u5DE5\u7A0B\u5E08\u7528\u3002\u666E\u901A\u573A\u666F\u5EFA\u8BAE\u4F18\u5148\u9009\u62E9\u5173\u952E\u8BCD\u6216\u6307\u5B9A\u7FA4\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: wizardDraft.regex ?? "", onChange: (event) => patchWizardDraft({ regex: event.target.value }) }) }, "regex") : null,
2955
+ showEntryWizard && wizardDraft.matchType === "chat" ? /* @__PURE__ */ jsx(Field, { label: "\u9009\u62E9\u98DE\u4E66\u7FA4\u6216\u5355\u804A", children: /* @__PURE__ */ jsx(
2956
+ ChatSearchControl,
2957
+ {
2958
+ query: chatSearchQuery,
2959
+ onQueryChange: setChatSearchQuery,
2960
+ chats: directoryCatalog.data?.chats ?? [],
2961
+ loading: directoryCatalog.loading,
2962
+ error: directoryCatalog.data?.chatError ?? directoryCatalog.error?.message,
2963
+ currentChatId: wizardDraft.chatId,
2964
+ currentChatName: wizardDraft.chatName,
2965
+ profileName: directoryCatalog.data?.profileName ?? directoryProfileName,
2966
+ onSelect: selectChatForWizard
2967
+ }
2968
+ ) }, "chat") : null,
2969
+ showEntryWizard && wizardDraft.matchType === "user" ? /* @__PURE__ */ jsx(Field, { label: "\u9009\u62E9\u53D1\u6D88\u606F\u4EBA", children: /* @__PURE__ */ jsx(
2970
+ UserSearchControl,
2971
+ {
2972
+ query: userSearchQuery,
2973
+ onQueryChange: setUserSearchQuery,
2974
+ users: directoryCatalog.data?.users ?? [],
2975
+ loading: directoryCatalog.loading,
2976
+ error: directoryCatalog.data?.userError ?? directoryCatalog.error?.message,
2977
+ currentUserOpenId: wizardDraft.userOpenId,
2978
+ currentUserName: wizardDraft.userName,
2979
+ profileName: directoryCatalog.data?.profileName ?? directoryProfileName,
2980
+ onSelect: selectUserForWizard
2981
+ }
2982
+ ) }, "user") : null
2983
+ ] }, "detail-fields") : null,
2984
+ showEntryWizard ? /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
2985
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: createEntryFromWizard, children: "\u521B\u5EFA\u5165\u53E3" }, "create"),
2986
+ /* @__PURE__ */ jsx("span", { style: helpStyle, children: "\u521B\u5EFA\u540E\u4FDD\u5B58\u914D\u7F6E\uFF0C\u518D\u5230\u673A\u5668\u4EBA\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\u53D1\u9001\u6D4B\u8BD5\u8BDD\u672F\u3002" }, "hint")
2987
+ ] }, "actions") : null
2988
+ ] }, "product-wizard") }, "entries-wizard-tab") : null,
2989
+ activeMainTab === "test" ? /* @__PURE__ */ jsxs("section", { id: "feishu-test", style: productSectionStyle, children: [
2990
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "18px" }, children: "4. \u771F\u5B9E\u6D4B\u8BD5" }, "title"),
2991
+ /* @__PURE__ */ jsxs(Field, { label: "\u6D4B\u8BD5\u8BDD\u672F\uFF08\u4F18\u5148\u53D1\u7ED9\u673A\u5668\u4EBA\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\uFF09", children: [
2992
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "minmax(0, 1fr) auto", gap: "10px" }, children: [
2993
+ /* @__PURE__ */ jsx("code", { style: { ...codeStyle, fontSize: "14px", padding: "11px 12px" }, children: smokeText }, "text"),
2994
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => void copySmokeText(), children: "\u590D\u5236" }, "copy")
2995
+ ] }, "copy-row"),
2996
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
2997
+ "\u9875\u9762\u6A21\u62DF\u53EA\u9A8C\u8BC1\u5165\u53E3\u89C4\u5219\uFF0C\u4F1A\u4F7F\u7528\u8FDE\u901A\u6027\u53E3\u4EE4\uFF1A",
2998
+ quickSmokeText,
2999
+ "\u3002\u771F\u5B9E\u98DE\u4E66\u9A8C\u6536\u4F18\u5148\u53D1\u7ED9\u673A\u5668\u4EBA\u5355\u804A\u6216\u53EA\u5305\u542B\u6D4B\u8BD5\u4EBA\u5458\u7684\u4F1A\u8BDD\uFF0C\u591A\u4EBA\u7FA4\u53EA\u505A\u6700\u7EC8\u6F14\u793A\u786E\u8BA4\u3002"
3000
+ ] }, "quick-hint")
3001
+ ] }, "smoke"),
3002
+ /* @__PURE__ */ jsxs("div", { style: heroCommandStyle, children: [
3003
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3004
+ /* @__PURE__ */ jsxs("div", { children: [
3005
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "16px" }, children: "\u771F\u5B9E\u6D4B\u8BD5\u94FE\u8DEF" }, "title"),
3006
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u8FD9\u4E9B\u90FD\u53D8\u6210\u201C\u5B8C\u6210\u201D\u540E\uFF0C\u518D\u53BB\u98DE\u4E66\u53D1\u6D4B\u8BD5\u6D88\u606F\u3002\u4F18\u5148\u7528\u673A\u5668\u4EBA\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\u9A8C\u8BC1\uFF0C\u6700\u7EC8\u4EE5\u98DE\u4E66\u4F1A\u8BDD\u91CC\u7684\u771F\u5B9E\u56DE\u590D\u4E3A\u51C6\u3002" }, "help")
3007
+ ] }, "copy"),
3008
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: checking, onClick: () => void testCurrentConfig(), children: checking ? "\u68C0\u67E5\u4E2D..." : "\u68C0\u67E5\u8FDE\u63A5" }, "check")
3009
+ ] }, "header"),
3010
+ /* @__PURE__ */ jsx("div", { style: pipelineStyle, children: realTestPipeline.map((step) => /* @__PURE__ */ jsx(PipelineStep, { done: step.done, label: step.label, detail: step.detail }, step.label)) }, "pipeline")
3011
+ ] }, "real-test-pipeline"),
3012
+ /* @__PURE__ */ jsxs("div", { style: checklistGridStyle, children: [
3013
+ /* @__PURE__ */ jsx(
3014
+ ChecklistItem,
3015
+ {
3016
+ done: firstRouteConnectionReady,
3017
+ title: "\u5F53\u524D\u5165\u53E3\u673A\u5668\u4EBA\u53EF\u8FD0\u884C",
3018
+ detail: firstRouteConnectionReady ? "\u6D4B\u8BD5\u5165\u53E3\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u5728\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u53EF\u7528\u3002" : hasUsableConnection ? "\u6709\u5176\u4ED6\u673A\u5668\u4EBA\u53EF\u7528\uFF0C\u4F46\u5F53\u524D\u5165\u53E3\u7ED1\u5B9A\u7684\u673A\u5668\u4EBA\u4E0D\u53EF\u8FD0\u884C\u3002\u8BF7\u5148\u7F16\u8F91\u5165\u53E3\u6362\u673A\u5668\u4EBA\u3002" : hasConnection ? "\u914D\u7F6E\u91CC\u6709\u673A\u5668\u4EBA\uFF0C\u4F46\u5F53\u524D lark-cli \u6CA1\u6709\u8BFB\u5230\u5BF9\u5E94 profile\u3002" : "\u5148\u7ED1\u5B9A\u673A\u5668\u4EBA\u3002"
3019
+ },
3020
+ "bot"
3021
+ ),
3022
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isListening, title: "\u76D1\u542C\u5F00\u5173\u5DF2\u5F00\u542F", detail: isListening ? "\u76D1\u542C\u5DF2\u5F00\u542F\u3002" : "\u6253\u5F00\u76D1\u542C\u540E\u518D\u5B9E\u6D4B\u3002" }, "event"),
3023
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isListening, title: "\u76D1\u542C\u8FDB\u7A0B\u8FD0\u884C\u4E2D", detail: runtimeStatusLabel }, "listen"),
3024
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isSendingRealMessages, title: "\u771F\u5B9E\u56DE\u590D\u5F00\u542F", detail: isSendingRealMessages ? "\u4F1A\u56DE\u5230\u98DE\u4E66\u3002" : "\u5F53\u524D\u662F\u6D4B\u8BD5\u6A21\u5F0F\u3002" }, "send"),
3025
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isSendingRealMessages, title: "\u9644\u4EF6\u8FDB\u5165\u4EFB\u52A1", detail: isSendingRealMessages ? "\u98DE\u4E66\u56FE\u7247/\u6587\u4EF6\u4F1A\u4F5C\u4E3A\u4EFB\u52A1\u9644\u4EF6\u3002" : "\u6D4B\u8BD5\u6A21\u5F0F\u53EA\u8BB0\u5F55\u9644\u4EF6\u540D\u3002" }, "attachments")
3026
+ ] }, "checks"),
3027
+ /* @__PURE__ */ jsx(CheckReport, { title: "\u80FD\u529B\u4F53\u68C0", items: capabilityChecks }, "capability-checks"),
3028
+ productionMonitor ? /* @__PURE__ */ jsx(
3029
+ CheckReport,
3030
+ {
3031
+ title: `\u8FD0\u884C\u63D0\u9192\uFF1A${friendlyMonitorMessage(productionMonitor.message)}`,
3032
+ items: productionMonitorChecks
3033
+ },
3034
+ "production-monitor"
3035
+ ) : null,
3036
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3037
+ /* @__PURE__ */ jsx(
3038
+ "button",
3039
+ {
3040
+ type: "button",
3041
+ style: primaryButtonStyle,
3042
+ disabled: !firstEnabledRouteSummary || testingRouteId === firstEnabledRouteSummary.route.id,
3043
+ onClick: () => firstEnabledRouteSummary && void testEntryRoute(firstEnabledRouteSummary.route),
3044
+ children: firstEnabledRouteSummary && testingRouteId === firstEnabledRouteSummary.route.id ? "\u6D4B\u8BD5\u4E2D..." : "\u8FD0\u884C\u9875\u9762\u6A21\u62DF\u6D4B\u8BD5"
3045
+ },
3046
+ "test"
3047
+ ),
3048
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: openFeishuTestGuide, children: showFeishuTestGuide ? "\u6536\u8D77\u6D4B\u8BD5\u8BF4\u660E" : "\u67E5\u770B\u98DE\u4E66\u6D4B\u8BD5\u8BF4\u660E" }, "doc")
3049
+ ] }, "actions"),
3050
+ showFeishuTestGuide ? /* @__PURE__ */ jsxs("div", { id: "feishu-test-guide", style: successBoxStyle, children: [
3051
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u98DE\u4E66\u91CC\u600E\u4E48\u786E\u8BA4\u771F\u7684\u751F\u6548" }, "title"),
3052
+ /* @__PURE__ */ jsxs("div", { style: flowGridStyle, children: [
3053
+ /* @__PURE__ */ jsx(FlowStep, { title: "1. \u5148\u770B\u76EE\u6807\u4F1A\u8BDD", value: "\u673A\u5668\u4EBA\u5728\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\u91CC", detail: "\u5982\u679C\u76EE\u6807\u4F1A\u8BDD\u91CC\u6CA1\u6709\u8FD9\u4E2A\u673A\u5668\u4EBA\uFF0C\u98DE\u4E66\u4E0D\u4F1A\u628A\u6D88\u606F\u4EA4\u7ED9\u5B83\u3002" }, "step-1"),
3054
+ /* @__PURE__ */ jsx(FlowStep, { title: "2. \u590D\u5236\u8BDD\u672F", value: smokeText, detail: "\u4F18\u5148\u7C98\u8D34\u5230\u673A\u5668\u4EBA\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\u91CC\u53D1\u9001\u3002" }, "step-2"),
3055
+ /* @__PURE__ */ jsx(FlowStep, { title: "3. \u53EF\u5E26\u4E00\u4E2A\u9644\u4EF6", value: "\u56FE\u7247\u6216\u6587\u4EF6\u4F1A\u8FDB\u4EFB\u52A1\u9644\u4EF6", detail: "\u771F\u5B9E\u53D1\u9001\u65F6\uFF0C\u9644\u4EF6\u4F1A\u4E0B\u8F7D\u5230 Paperclip \u4EFB\u52A1\u91CC\uFF0C\u667A\u80FD\u4F53\u80FD\u770B\u5230\u9644\u4EF6\u540D\u79F0\u548C\u4E0A\u4F20\u7ED3\u679C\u3002" }, "step-3"),
3056
+ /* @__PURE__ */ jsx(FlowStep, { title: "4. \u56DE\u6765\u770B Paperclip", value: "\u4F1A\u751F\u6210\u4EFB\u52A1\u6216\u663E\u793A\u6D4B\u8BD5\u7ED3\u679C", detail: "\u9875\u9762\u6A21\u62DF\u901A\u8FC7\u53EA\u8BC1\u660E\u89C4\u5219\u80FD\u5339\u914D\uFF0C\u771F\u5B9E\u6548\u679C\u4EE5\u98DE\u4E66\u6D88\u606F\u4E3A\u51C6\u3002" }, "step-4"),
3057
+ /* @__PURE__ */ jsx(FlowStep, { title: "5. \u6CA1\u56DE\u590D\u65F6", value: "\u5148\u68C0\u67E5\u673A\u5668\u4EBA\u5361\u7247", detail: "\u770B\u6388\u6743\u3001\u5165\u53E3\u3001\u76D1\u542C\u3001\u771F\u5B9E\u56DE\u590D\u56DB\u9879\u662F\u5426\u90FD\u901A\u8FC7\u3002" }, "step-5")
3058
+ ] }, "steps"),
3059
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "12px" }, children: [
3060
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => void copySmokeText(), children: "\u590D\u5236\u6D4B\u8BD5\u8BDD\u672F" }, "copy"),
3061
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: checking, onClick: () => void testCurrentConfig(), children: checking ? "\u68C0\u67E5\u4E2D..." : "\u68C0\u67E5\u6574\u4F53\u8FDE\u63A5" }, "check")
3062
+ ] }, "actions")
3063
+ ] }, "guide") : null
3064
+ ] }, "product-test") : null,
3065
+ activeMainTab === "advanced" ? /* @__PURE__ */ jsxs("section", { id: "feishu-advanced", style: productSectionStyle, children: [
3066
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3067
+ /* @__PURE__ */ jsxs("div", { children: [
3068
+ /* @__PURE__ */ jsx("h3", { style: { margin: 0, fontSize: "18px" }, children: "\u9AD8\u7EA7\u8BBE\u7F6E\uFF08\u5DE5\u7A0B\u5E08\uFF09" }, "title"),
3069
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u65E5\u5E38\u4E0D\u7528\u6253\u5F00\u3002\u8FD9\u91CC\u6309\u4E3B\u9898\u62C6\u5F00\uFF0C\u70B9\u54EA\u4E00\u9879\u53EA\u770B\u54EA\u4E00\u9879\uFF0C\u4E0D\u518D\u51FA\u73B0\u6574\u9875\u539F\u59CB\u914D\u7F6E\u3002" }, "help")
3070
+ ] }, "copy"),
3071
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3072
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, disabled: saving, onClick: () => void saveCurrentConfig(), children: saving ? "\u6B63\u5728\u4FDD\u5B58..." : "\u4FDD\u5B58\u914D\u7F6E" }, "save"),
3073
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: saving || checking, onClick: () => void testCurrentConfig(), children: checking ? "\u6B63\u5728\u68C0\u67E5..." : "\u68C0\u67E5\u8FDE\u63A5" }, "check")
3074
+ ] }, "actions")
3075
+ ] }, "header"),
3076
+ /* @__PURE__ */ jsx("div", { style: settingsShellStyle, children: [
3077
+ { key: "auth", label: "\u98DE\u4E66\u5E94\u7528\u6388\u6743\u4E0E App Secret", detail: `${profiles.length} \u4E2A lark-cli profile\uFF0C${activeConnections.length} \u4E2A\u5DF2\u52A0\u5165\u673A\u5668\u4EBA\u6C60` },
3078
+ { key: "capabilities", label: "\u80FD\u529B\u4E2D\u5FC3", detail: capabilityCenter.loading ? "\u6B63\u5728\u8BFB\u53D6\u80FD\u529B\u76EE\u5F55" : `${enabledCapabilityCount} \u9879\u5DF2\u5F00\u542F \xB7 lark-* skills \u4E0D\u81EA\u52A8\u540C\u6B65` },
3079
+ { key: "deploy", label: "\u672C\u5730\u6D4B\u8BD5 / \u4E91\u670D\u52A1\u5668\u90E8\u7F72", detail: `${runningOnLocalhost ? "\u5F53\u524D\u5728\u672C\u5730\u6D4B\u8BD5" : "\u5F53\u524D\u5728\u670D\u52A1\u5668\u8FD0\u884C"} \xB7 profile ${serverProfileName(serverDeployConnection)}` },
3080
+ { key: "runtime", label: "lark-cli \u8FD0\u884C\u73AF\u5883", detail: `${isSendingRealMessages ? "\u771F\u5B9E\u53D1\u9001" : "\u6A21\u62DF\u53D1\u9001"} \xB7 ${isListening ? "\u76D1\u542C\u5DF2\u5F00\u542F" : "\u76D1\u542C\u672A\u5F00\u542F"}` },
3081
+ { key: "events", label: "\u4E8B\u4EF6\u8BA2\u9605\u4E0E\u65E5\u5FD7", detail: `${connectorStatus.data?.subscribers?.length ?? 0} \u4E2A\u76D1\u542C\u8FDB\u7A0B \xB7 \u6700\u8FD1\u4E8B\u4EF6 ${connectorStatus.data?.recentRecords?.length ?? 0} \u6761` },
3082
+ { key: "base", label: "\u591A\u7EF4\u8868\u683C\u540C\u6B65", detail: baseSinks.length > 0 ? `${baseSinks.length} \u6761\u5199\u5165\u89C4\u5219` : "\u672A\u914D\u7F6E\uFF0C\u53EF\u7559\u7A7A" },
3083
+ { key: "config", label: "\u5BFC\u5165 / \u5BFC\u51FA\u914D\u7F6E", detail: "\u8FC1\u79FB\u5165\u53E3\u548C\u673A\u5668\u4EBA\u6C60\uFF0C\u4E0D\u5BFC\u51FA App Secret" }
3084
+ ].map((item) => /* @__PURE__ */ jsxs(
3085
+ "button",
3086
+ {
3087
+ type: "button",
3088
+ style: {
3089
+ ...buttonStyle,
3090
+ height: "auto",
3091
+ minHeight: "52px",
3092
+ justifyContent: "space-between",
3093
+ textAlign: "left",
3094
+ width: "100%",
3095
+ display: "flex",
3096
+ padding: "10px 12px",
3097
+ border: showAdvancedSettings && activeAdvancedPanel === item.key ? "1px solid var(--foreground)" : buttonStyle.border,
3098
+ background: showAdvancedSettings && activeAdvancedPanel === item.key ? "var(--muted)" : buttonStyle.background
3099
+ },
3100
+ onClick: () => {
3101
+ setShowAdvancedSettings(true);
3102
+ setActiveAdvancedPanel(item.key);
3103
+ },
3104
+ children: [
3105
+ /* @__PURE__ */ jsxs("span", { style: { display: "grid", gap: "2px" }, children: [
3106
+ /* @__PURE__ */ jsx("strong", { children: item.label }, "title"),
3107
+ /* @__PURE__ */ jsx("span", { style: helpStyle, children: item.detail }, "detail")
3108
+ ] }, "label"),
3109
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u203A" }, "chevron")
3110
+ ]
3111
+ },
3112
+ item.key
3113
+ )) }, "advanced-links"),
3114
+ showAdvancedSettings ? /* @__PURE__ */ jsxs("div", { style: productEntryEditorStyle, children: [
3115
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3116
+ /* @__PURE__ */ jsxs("div", { children: [
3117
+ /* @__PURE__ */ jsxs("div", { style: { fontWeight: 800 }, children: [
3118
+ activeAdvancedPanel === "auth" ? "\u98DE\u4E66\u5E94\u7528\u6388\u6743\u4E0E App Secret" : null,
3119
+ activeAdvancedPanel === "capabilities" ? "\u80FD\u529B\u4E2D\u5FC3" : null,
3120
+ activeAdvancedPanel === "deploy" ? "\u672C\u5730\u6D4B\u8BD5 / \u4E91\u670D\u52A1\u5668\u90E8\u7F72" : null,
3121
+ activeAdvancedPanel === "runtime" ? "lark-cli \u8FD0\u884C\u73AF\u5883" : null,
3122
+ activeAdvancedPanel === "events" ? "\u4E8B\u4EF6\u8BA2\u9605\u4E0E\u65E5\u5FD7" : null,
3123
+ activeAdvancedPanel === "base" ? "\u591A\u7EF4\u8868\u683C\u540C\u6B65" : null,
3124
+ activeAdvancedPanel === "config" ? "\u5BFC\u5165 / \u5BFC\u51FA\u914D\u7F6E" : null
3125
+ ] }, "title"),
3126
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
3127
+ activeAdvancedPanel === "auth" ? "\u666E\u901A\u7528\u6237\u53EA\u9700\u8981\u786E\u8BA4\u673A\u5668\u4EBA\u53EF\u7528\uFF1BApp Secret \u4E0D\u5728\u9875\u9762\u5C55\u793A\uFF0C\u907F\u514D\u8BEF\u622A\u56FE\u6CC4\u9732\u3002" : null,
3128
+ activeAdvancedPanel === "capabilities" ? "\u8FD9\u91CC\u5C55\u793A Agent \u53EF\u4EE5\u901A\u8FC7\u63D2\u4EF6\u8C03\u7528\u54EA\u4E9B\u98DE\u4E66\u80FD\u529B\uFF0C\u4EE5\u53CA\u5B83\u4EEC\u548C lark-cli\u3001lark-* skills \u7684\u5173\u7CFB\u3002" : null,
3129
+ activeAdvancedPanel === "deploy" ? "\u672C\u5730\u80FD\u8DD1\u901A\u4E0D\u7B49\u4E8E\u4E91\u7AEF\u5DF2\u7ECF\u53EF\u7528\uFF1B\u4E91\u670D\u52A1\u5668\u4E5F\u8981\u7ED1\u5B9A\u540C\u4E00\u4E2A\u98DE\u4E66\u5E94\u7528\uFF0C\u5E76\u4E14\u53EA\u4FDD\u7559\u4E00\u4E2A\u6B63\u5F0F\u76D1\u542C\u5B9E\u4F8B\u3002" : null,
3130
+ activeAdvancedPanel === "runtime" ? "\u63A7\u5236\u662F\u5426\u76D1\u542C\u98DE\u4E66\u6D88\u606F\u3001\u662F\u5426\u771F\u5B9E\u56DE\u590D\uFF0C\u4EE5\u53CA\u672C\u673A lark-cli \u8DEF\u5F84\u3002" : null,
3131
+ activeAdvancedPanel === "events" ? "\u770B\u76D1\u542C\u662F\u5426\u5728\u8DD1\uFF0C\u4EE5\u53CA\u6700\u8FD1\u6709\u6CA1\u6709\u9519\u8BEF\u3002\u8FD9\u91CC\u4E0D\u8981\u6C42\u666E\u901A\u7528\u6237\u586B\u5199\u4EFB\u4F55\u5185\u90E8 ID\u3002" : null,
3132
+ activeAdvancedPanel === "base" ? "\u9700\u8981\u628A\u9700\u6C42\u6C89\u6DC0\u5230\u98DE\u4E66\u591A\u7EF4\u8868\u683C\u65F6\u518D\u914D\u7F6E\uFF1B\u4E0D\u9700\u8981\u5C31\u4FDD\u6301\u4E3A\u7A7A\u3002" : null,
3133
+ activeAdvancedPanel === "config" ? "\u7528\u4E8E\u628A\u5165\u53E3\u3001\u673A\u5668\u4EBA\u6C60\u548C\u80FD\u529B\u5F00\u5173\u8FC1\u79FB\u5230\u53E6\u4E00\u5957 Paperclip\uFF1B\u5BFC\u5165\u540E\u4ECD\u9700\u70B9\u51FB\u4FDD\u5B58\u914D\u7F6E\u3002" : null
3134
+ ] }, "help")
3135
+ ] }, "copy"),
3136
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => setShowAdvancedSettings(false), children: "\u56DE\u5230\u9AD8\u7EA7\u5217\u8868" }, "close")
3137
+ ] }, "advanced-panel-head"),
3138
+ activeAdvancedPanel === "auth" ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
3139
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3140
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u9996\u88C5\u68C0\u67E5\u6E05\u5355" }, "title"),
3141
+ /* @__PURE__ */ jsxs("div", { style: checklistGridStyle, children: [
3142
+ /* @__PURE__ */ jsx(ChecklistItem, { done: profiles.length > 0 || activeConnections.length > 0, title: "1. \u521B\u5EFA\u6216\u9009\u62E9\u98DE\u4E66\u5E94\u7528", detail: "\u666E\u901A\u7528\u6237\u9009\u5DF2\u6709\u516C\u53F8\u673A\u5668\u4EBA\uFF1B\u7BA1\u7406\u5458\u53EF\u4EE5\u65B0\u5EFA\u98DE\u4E66\u673A\u5668\u4EBA\u5E94\u7528\u3002" }, "create-app"),
3143
+ /* @__PURE__ */ jsx(ChecklistItem, { done: activeConnections.length > 0, title: "2. \u5F00\u542F\u673A\u5668\u4EBA\u80FD\u529B", detail: "\u98DE\u4E66\u5E94\u7528\u5FC5\u987B\u6709\u673A\u5668\u4EBA\u80FD\u529B\uFF0C\u5E76\u52A0\u5165\u76EE\u6807\u7FA4\u804A\u3002" }, "bot-enabled"),
3144
+ /* @__PURE__ */ jsx(ChecklistItem, { done: enabledCapabilityCount > 0, title: "3. \u5BFC\u5165\u63A8\u8350\u6743\u9650", detail: "\u5230\u80FD\u529B\u4E2D\u5FC3\u590D\u5236\u63A8\u8350\u6743\u9650 JSON\uFF1B\u5DF2\u63A5\u5165\u80FD\u529B\u9ED8\u8BA4\u6309\u98DE\u4E66\u5E94\u7528\u6388\u6743\u5F00\u653E\uFF0C\u4E0D\u9700\u8981\u9010\u9879\u786E\u8BA4\u3002" }, "permissions"),
3145
+ /* @__PURE__ */ jsx(ChecklistItem, { done: false, title: "4. \u53D1\u5E03\u98DE\u4E66\u5E94\u7528", detail: "\u98DE\u4E66\u53EF\u80FD\u9700\u8981\u7BA1\u7406\u5458\u786E\u8BA4\u3001\u53D1\u5E03\u7248\u672C\u3001\u914D\u7F6E\u4E8B\u4EF6\u8BA2\u9605\u548C\u53EF\u89C1\u8303\u56F4\u3002" }, "publish"),
3146
+ /* @__PURE__ */ jsx(ChecklistItem, { done: hasUsableConnection, title: "5. \u56DE\u5230 Paperclip \u68C0\u67E5\u8FDE\u63A5", detail: "\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868\u540E\u70B9\u201C\u68C0\u67E5\u8FDE\u63A5\u201D\uFF0C\u518D\u53BB\u98DE\u4E66\u7FA4\u91CC\u53D1\u6D4B\u8BD5\u8BDD\u672F\u3002" }, "paperclip-check")
3147
+ ] }, "steps")
3148
+ ] }, "first-install-checklist"),
3149
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3150
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: refreshProfilesWithNotice, children: "\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868" }, "refresh"),
3151
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openBindPanel(), children: "\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA" }, "bind"),
3152
+ /* @__PURE__ */ jsx("a", { href: "https://open.feishu.cn/app", target: "_blank", rel: "noreferrer", style: linkButtonStyle, children: "\u6253\u5F00\u98DE\u4E66\u5F00\u653E\u5E73\u53F0" }, "platform")
3153
+ ] }, "auth-actions"),
3154
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3155
+ profiles.length === 0 ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3156
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 700 }, children: "\u8FD8\u6CA1\u6709\u53D1\u73B0\u98DE\u4E66\u673A\u5668\u4EBA" }, "title"),
3157
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u70B9\u51FB\u201C\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u201D\uFF0C\u6309\u5B98\u65B9\u94FE\u63A5\u5B8C\u6210\u6388\u6743\u540E\u518D\u5237\u65B0\u3002" }, "help")
3158
+ ] }, "empty") : null,
3159
+ profiles.map((profile, index) => {
3160
+ const connection = connections.find((item) => item.profileName === profile.name);
3161
+ const enabled = connection?.enabled !== false && Boolean(connection);
3162
+ const authResult = userAuthResults[profile.name];
3163
+ const isStartingUserAuth = startingUserAuthProfileName === profile.name;
3164
+ const isFinishingUserAuth = finishingUserAuthProfileName === profile.name;
3165
+ return /* @__PURE__ */ jsxs("div", { style: guideCardStyle, children: [
3166
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: appLabel(connection, profile) }, "title"),
3167
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: profileLabel(profile) }, "meta"),
3168
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
3169
+ "App ID\uFF1A",
3170
+ maskTechnicalId(profile.appId ?? connection?.appId)
3171
+ ] }, "state"),
3172
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: profileAuthDetail(profile) }, "auth-detail"),
3173
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3174
+ /* @__PURE__ */ jsx(StatusBadge, { tone: enabled ? "success" : "warning", children: enabled ? "\u5DF2\u52A0\u5165\u673A\u5668\u4EBA\u6C60" : "\u672A\u52A0\u5165\u673A\u5668\u4EBA\u6C60" }, "status"),
3175
+ !enabled ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => addConnectionFromProfile(profile), children: "\u52A0\u5165\u673A\u5668\u4EBA\u6C60" }, "add") : null,
3176
+ !profile.user ? /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: isStartingUserAuth, onClick: () => void startUserAuthFlow(profile.name), children: isStartingUserAuth ? "\u751F\u6210\u4E2D..." : "\u8BBF\u95EE\u4E2A\u4EBA\u8D44\u6E90\u65F6\u6388\u6743" }, "user-auth") : null
3177
+ ] }, "actions"),
3178
+ authResult?.url ? /* @__PURE__ */ jsxs("div", { style: { ...successBoxStyle, marginTop: "10px" }, children: [
3179
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u5DF2\u751F\u6210\u7528\u6237\u6388\u6743\u94FE\u63A5" }, "title"),
3180
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6388\u6743\u540E\u8FD9\u91CC\u4F1A\u663E\u793A\u6388\u6743\u7528\u6237\u59D3\u540D\uFF1B\u4E0D\u8865\u4E5F\u4E0D\u5F71\u54CD\u673A\u5668\u4EBA\u6536\u53D1\u6D88\u606F\u3002" }, "help"),
3181
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "10px" }, children: [
3182
+ /* @__PURE__ */ jsx("a", { href: authResult.url, target: "_blank", rel: "noreferrer", style: linkButtonStyle, children: "\u6253\u5F00\u6388\u6743\u94FE\u63A5" }, "open"),
3183
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: isFinishingUserAuth, onClick: () => void finishUserAuthFlow(profile.name), children: isFinishingUserAuth ? "\u786E\u8BA4\u4E2D..." : "\u6211\u5DF2\u5B8C\u6210\u6388\u6743\uFF0C\u5237\u65B0\u72B6\u6001" }, "finish")
3184
+ ] }, "actions")
3185
+ ] }, "user-auth-result") : null
3186
+ ] }, `${profile.name}-${index}`);
3187
+ })
3188
+ ] }, "profiles"),
3189
+ !showBindPanel && !profileCatalog.loading && !profileError && profiles.length === 0 ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3190
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u8FD8\u6CA1\u6709\u53D1\u73B0\u98DE\u4E66\u673A\u5668\u4EBA" }, "title"),
3191
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginBottom: "10px" }, children: "\u70B9\u51FB\u201C\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA\u201D\u4F1A\u5F39\u51FA\u7ED1\u5B9A\u7A97\u53E3\uFF0C\u4E0D\u9700\u8981\u5728\u8FD9\u91CC\u624B\u586B App ID \u6216 App Secret\u3002" }, "bind-help"),
3192
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryButtonStyle, onClick: () => openBindPanel(), children: "\u7ED1\u5B9A\u65B0\u7684\u98DE\u4E66\u673A\u5668\u4EBA" }, "open")
3193
+ ] }, "bind-panel") : null
3194
+ ] }, "auth-panel") : null,
3195
+ activeAdvancedPanel === "capabilities" ? /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "12px" }, children: capabilityCenter.loading ? /* @__PURE__ */ jsx("div", { style: subtleBoxStyle, children: "\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u80FD\u529B\u4E2D\u5FC3..." }, "loading") : capabilityCenter.error ? /* @__PURE__ */ jsxs("div", { style: { ...subtleBoxStyle, color: "var(--destructive)" }, children: [
3196
+ "\u80FD\u529B\u4E2D\u5FC3\u8BFB\u53D6\u5931\u8D25\uFF1A",
3197
+ capabilityCenter.error.message
3198
+ ] }, "error") : /* @__PURE__ */ jsxs(Fragment, { children: [
3199
+ /* @__PURE__ */ jsxs("div", { style: successBoxStyle, children: [
3200
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900 }, children: "Agent \u8C03\u7528\u7684\u662F\u63D2\u4EF6\u53D7\u63A7\u5DE5\u5177\uFF0C\u4E0D\u662F\u88F8\u8DD1 lark-cli" }, "title"),
3201
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: capabilityCenter.data?.summary }, "body")
3202
+ ] }, "summary"),
3203
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3204
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u9ED8\u8BA4\u5F00\u653E\u7B56\u7565" }, "label"),
3205
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: capabilityCenter.data?.defaultPolicy?.mode === "conservative" ? "\u4FDD\u5B88\u6A21\u5F0F" : "\u6309\u98DE\u4E66\u5E94\u7528\u6388\u6743\u5F00\u653E" }, "value"),
3206
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: capabilityCenter.data?.defaultPolicy?.text }, "detail")
3207
+ ] }, "default-policy"),
3208
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3209
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3210
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "lark-cli" }, "label"),
3211
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u8FD0\u884C\u65F6 API \u5BA2\u6237\u7AEF" }, "value"),
3212
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u4E91\u7AEF\u63D2\u4EF6\u5305\u4F1A\u5E26 CLI\uFF1Bprofile\u3001App Secret \u548C\u6743\u9650\u4ECD\u5C5E\u4E8E\u670D\u52A1\u5668\u8FD0\u884C\u73AF\u5883\u3002" }, "detail")
3213
+ ] }, "cli"),
3214
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3215
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "lark-* skills" }, "label"),
3216
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u672C\u5730 Agent \u4F7F\u7528\u8BF4\u660E" }, "value"),
3217
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: capabilityCenter.data?.syncPolicy.text }, "detail")
3218
+ ] }, "skills")
3219
+ ] }, "relationship"),
3220
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3221
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3222
+ /* @__PURE__ */ jsxs("div", { children: [
3223
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "lark-cli schema / skills \u540C\u6B65\u72B6\u6001" }, "title"),
3224
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: capabilityCenter.data?.schemaDiscovery.summary }, "detail")
3225
+ ] }, "copy"),
3226
+ /* @__PURE__ */ jsx(StatusBadge, { tone: capabilityCenter.data?.schemaDiscovery.checked ? "success" : "warning", children: capabilityCenter.data?.schemaDiscovery.checked ? "\u5DF2\u626B\u63CF" : "\u672A\u626B\u63CF" }, "status")
3227
+ ] }, "head"),
3228
+ capabilityCenter.data?.schemaDiscovery.reason ? /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "8px" }, children: capabilityCenter.data.schemaDiscovery.reason }, "reason") : null,
3229
+ capabilityCenter.data?.schemaDiscovery.updateNotice?.message ? /* @__PURE__ */ jsx("div", { style: { ...subtleBoxStyle, marginTop: "10px", background: "var(--background)" }, children: capabilityCenter.data.schemaDiscovery.updateNotice.message }, "update") : null,
3230
+ /* @__PURE__ */ jsx("div", { style: { ...rowStyle, marginTop: "10px" }, children: (capabilityCenter.data?.schemaDiscovery.services ?? []).slice(0, 8).map((service) => /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3231
+ service.name,
3232
+ "\uFF1A",
3233
+ service.available ? `${service.methodCount} \u4E2A\u63A5\u53E3 / ${service.scopeCount} \u4E2A scope` : "\u4E0D\u53EF\u7528"
3234
+ ] }, service.name)) }, "services")
3235
+ ] }, "schema-discovery"),
3236
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3237
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3238
+ /* @__PURE__ */ jsxs("div", { children: [
3239
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u6743\u9650\u68C0\u67E5\u7B56\u7565" }, "title"),
3240
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: capabilityCenter.data?.permissionStrategy }, "detail")
3241
+ ] }, "copy"),
3242
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, disabled: checkingPermissions, onClick: () => void runPermissionCheck(), children: checkingPermissions ? "\u68C0\u67E5\u4E2D..." : "\u68C0\u67E5\u5F53\u524D\u6743\u9650" }, "check")
3243
+ ] }, "head"),
3244
+ permissionCheck ? /* @__PURE__ */ jsxs("div", { style: { ...subtleBoxStyle, marginTop: "10px", background: "var(--background)" }, children: [
3245
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginBottom: "6px" }, children: [
3246
+ /* @__PURE__ */ jsx(StatusBadge, { tone: permissionCheck.ok ? "success" : "warning", children: permissionCheck.ok ? "\u6743\u9650\u8986\u76D6\u63A8\u8350\u6E05\u5355" : "\u6709\u6743\u9650\u7F3A\u53E3" }, "status"),
3247
+ permissionCheck.profileName ? /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3248
+ "profile\uFF1A",
3249
+ permissionCheck.profileName
3250
+ ] }, "profile") : null,
3251
+ permissionCheck.identity ? /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3252
+ "\u8EAB\u4EFD\uFF1A",
3253
+ permissionCheck.identity
3254
+ ] }, "identity") : null
3255
+ ] }, "state"),
3256
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: permissionCheck.message }, "message"),
3257
+ permissionCheck.missingScopes?.length ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "8px", overflowWrap: "anywhere" }, children: [
3258
+ "\u7F3A\u5931\u6743\u9650\uFF1A",
3259
+ permissionCheck.missingScopes.join("\u3001")
3260
+ ] }, "missing") : null
3261
+ ] }, "permission-result") : null
3262
+ ] }, "permission"),
3263
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3264
+ /* @__PURE__ */ jsx("div", { style: sectionHeaderStyle, children: /* @__PURE__ */ jsxs("div", { children: [
3265
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u63A8\u8350\u6743\u9650 JSON" }, "title"),
3266
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: capabilityCenter.data?.recommendedPermissionJson.note }, "detail")
3267
+ ] }, "copy") }, "head"),
3268
+ /* @__PURE__ */ jsx("code", { style: { ...codeStyle, marginTop: "10px" }, children: JSON.stringify(capabilityCenter.data?.recommendedPermissionJson ?? {}, null, 2) }, "json")
3269
+ ] }, "permission-json"),
3270
+ (capabilityCenter.data?.groups ?? []).map((group) => /* @__PURE__ */ jsxs("div", { style: productEntryStyle, children: [
3271
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "16px" }, children: group.name }, "group-title"),
3272
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "10px" }, children: group.capabilities.map((capability) => {
3273
+ const override = capabilityOverrides.find((item) => item.key === capability.key);
3274
+ const checked = override?.enabled ?? capability.enabled;
3275
+ const selectedScope = override?.scope ?? capability.scope ?? "instance";
3276
+ const selectedConnectionId = override?.connectionId ?? capability.connectionId ?? preferredConnection?.id ?? activeConnections[0]?.id ?? "";
3277
+ const selectedRouteId = override?.routeId ?? capability.routeId ?? firstEnabledRouteSummary?.route.id ?? routes[0]?.id ?? "";
3278
+ const selectedAgentId = override?.agentId ?? capability.agentId ?? firstEnabledRouteSummary?.agent?.id ?? allAgentOptions[0]?.agent.id ?? "";
3279
+ const statusTone = !checked ? "neutral" : capability.implemented ? capability.recommendedScopes.length > 0 ? "warning" : "success" : "warning";
3280
+ return /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3281
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3282
+ /* @__PURE__ */ jsxs("div", { children: [
3283
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3284
+ /* @__PURE__ */ jsx("strong", { children: capability.title }, "title"),
3285
+ /* @__PURE__ */ jsx(StatusBadge, { tone: statusTone, children: checked ? capability.statusLabel : "\u672A\u5F00\u542F" }, "status"),
3286
+ /* @__PURE__ */ jsx("span", { style: compactPillStyle, children: capability.scopeLabel }, "scope")
3287
+ ] }, "title-row"),
3288
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "6px" }, children: capability.description }, "desc")
3289
+ ] }, "copy"),
3290
+ /* @__PURE__ */ jsx(
3291
+ "button",
3292
+ {
3293
+ type: "button",
3294
+ style: checked ? buttonStyle : primaryButtonStyle,
3295
+ onClick: () => patchCapability(capability.key, { enabled: !checked }),
3296
+ children: checked ? "\u5173\u95ED" : "\u5F00\u542F"
3297
+ },
3298
+ "toggle"
3299
+ )
3300
+ ] }, "head"),
3301
+ /* @__PURE__ */ jsxs("div", { style: { ...gridTwoStyle, marginTop: "10px" }, children: [
3302
+ /* @__PURE__ */ jsx(Field, { label: "\u5F00\u542F\u8303\u56F4", children: /* @__PURE__ */ jsxs(
3303
+ "select",
3304
+ {
3305
+ style: selectStyle,
3306
+ value: selectedScope,
3307
+ onChange: (event) => patchCapabilityScope(capability.key, event.target.value),
3308
+ children: [
3309
+ /* @__PURE__ */ jsx("option", { value: "instance", children: "\u5168\u5B9E\u4F8B\u5F00\u542F" }),
3310
+ /* @__PURE__ */ jsx("option", { value: "bot", children: "\u67D0\u4E2A\u673A\u5668\u4EBA\u5F00\u542F" }),
3311
+ /* @__PURE__ */ jsx("option", { value: "entry", children: "\u67D0\u4E2A\u5165\u53E3\u5F00\u542F" }),
3312
+ /* @__PURE__ */ jsx("option", { value: "agent", children: "\u67D0\u4E2A Agent \u5F00\u542F" })
3313
+ ]
3314
+ }
3315
+ ) }, "scope"),
3316
+ selectedScope === "bot" ? /* @__PURE__ */ jsx(Field, { label: "\u76EE\u6807\u673A\u5668\u4EBA", children: /* @__PURE__ */ jsx(
3317
+ "select",
3318
+ {
3319
+ style: selectStyle,
3320
+ value: selectedConnectionId,
3321
+ onChange: (event) => patchCapability(capability.key, {
3322
+ scope: "bot",
3323
+ connectionId: event.target.value,
3324
+ routeId: void 0,
3325
+ agentId: void 0
3326
+ }),
3327
+ children: activeConnections.map((connection) => /* @__PURE__ */ jsx("option", { value: connection.id, children: appLabel(connection, profiles.find((profile) => profile.name === connection.profileName)) }, connection.id))
3328
+ }
3329
+ ) }, "bot-target") : null,
3330
+ selectedScope === "entry" ? /* @__PURE__ */ jsx(Field, { label: "\u76EE\u6807\u5165\u53E3", children: /* @__PURE__ */ jsx(
3331
+ "select",
3332
+ {
3333
+ style: selectStyle,
3334
+ value: selectedRouteId,
3335
+ onChange: (event) => patchCapability(capability.key, {
3336
+ scope: "entry",
3337
+ routeId: event.target.value,
3338
+ connectionId: void 0,
3339
+ agentId: void 0
3340
+ }),
3341
+ children: routeSummaries.map(({ route }, routeIndex) => /* @__PURE__ */ jsx("option", { value: route.id, children: routeTitle(route, routeIndex) }, route.id))
3342
+ }
3343
+ ) }, "entry-target") : null,
3344
+ selectedScope === "agent" ? /* @__PURE__ */ jsx(Field, { label: "\u76EE\u6807 Agent", children: /* @__PURE__ */ jsx(
3345
+ "select",
3346
+ {
3347
+ style: selectStyle,
3348
+ value: selectedAgentId,
3349
+ onChange: (event) => patchCapability(capability.key, {
3350
+ scope: "agent",
3351
+ agentId: event.target.value,
3352
+ connectionId: void 0,
3353
+ routeId: void 0
3354
+ }),
3355
+ children: allAgentOptions.map(({ company, agent }) => /* @__PURE__ */ jsxs("option", { value: agent.id, children: [
3356
+ agentLabel(agent),
3357
+ "\uFF08",
3358
+ companyLabel(company),
3359
+ "\uFF09"
3360
+ ] }, `${company.id}-${agent.id}`))
3361
+ }
3362
+ ) }, "agent-target") : null
3363
+ ] }, "scope-controls"),
3364
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "10px" }, children: [
3365
+ capability.toolName ? /* @__PURE__ */ jsx("span", { style: compactPillStyle, children: capability.toolName }, "tool") : null,
3366
+ capability.legacyToolName ? /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3367
+ "\u517C\u5BB9\uFF1A",
3368
+ capability.legacyToolName
3369
+ ] }, "legacy") : null,
3370
+ capability.larkCliCommands.map((command) => /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3371
+ "lark-cli ",
3372
+ command
3373
+ ] }, `cmd-${command}`)),
3374
+ capability.relatedSkills.map((skill) => /* @__PURE__ */ jsx("span", { style: compactPillStyle, children: skill }, `skill-${skill}`))
3375
+ ] }, "meta"),
3376
+ capability.schemaCommands?.length ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "8px" }, children: [
3377
+ "CLI \u53D1\u73B0\uFF1A",
3378
+ capability.schemaCommands.map((command) => `${command.command}\uFF1A${command.status === "schema_backed" ? "schema \u8986\u76D6" : command.status === "cli_help_backed" ? "CLI help \u8986\u76D6" : "\u672A\u53D1\u73B0"}`).join("\uFF1B")
3379
+ ] }, "schema") : null,
3380
+ capability.recommendedScopes.length > 0 ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "8px" }, children: [
3381
+ "\u63A8\u8350\u6743\u9650\uFF1A",
3382
+ capability.recommendedScopes.join("\u3001")
3383
+ ] }, "scopes") : null
3384
+ ] }, capability.key);
3385
+ }) }, "items")
3386
+ ] }, group.name))
3387
+ ] }, "capability-content") }, "capabilities-panel") : null,
3388
+ activeAdvancedPanel === "deploy" ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
3389
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3390
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "6px" }, children: "\u5F53\u524D\u8FD0\u884C\u4F4D\u7F6E" }, "title"),
3391
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: runtimeHint }, "hint"),
3392
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "10px" }, children: [
3393
+ /* @__PURE__ */ jsx(StatusBadge, { tone: runningOnLocalhost ? "warning" : "success", children: runningOnLocalhost ? "\u672C\u5730\u6D4B\u8BD5\u73AF\u5883" : "\u4E91\u7AEF\u6B63\u5F0F\u73AF\u5883" }, "mode-badge"),
3394
+ /* @__PURE__ */ jsxs("span", { style: compactPillStyle, children: [
3395
+ "profile\uFF1A",
3396
+ serverProfileName(serverDeployConnection)
3397
+ ] }, "profile")
3398
+ ] }, "mode")
3399
+ ] }, "runtime-position"),
3400
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3401
+ /* @__PURE__ */ jsxs("div", { style: guideCardStyle, children: [
3402
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u672C\u5730\u6D4B\u8BD5" }, "title"),
3403
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u9002\u5408\u73B0\u5728\u9A8C\u8BC1\u98DE\u4E66\u662F\u5426\u80FD\u6536\u6D88\u606F\u3001\u56DE\u6D88\u606F\u3001\u521B\u5EFA\u4EFB\u52A1\u548C\u4E0A\u4F20\u9644\u4EF6\u3002\u8BFB\u53D6\u7684\u662F\u8FD9\u53F0 Mac \u4E0A\u7684 lark-cli profile\u3002" }, "body")
3404
+ ] }, "local"),
3405
+ /* @__PURE__ */ jsxs("div", { style: guideCardStyle, children: [
3406
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u4E91\u7AEF\u6B63\u5F0F\u90E8\u7F72" }, "title"),
3407
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "Paperclip \u8DD1\u5230\u670D\u52A1\u5668\u540E\uFF0C\u63D2\u4EF6\u4F1A\u4F18\u5148\u4F7F\u7528\u4E91\u7AEF\u63D2\u4EF6\u5305\u81EA\u5E26\u7684 lark-cli\uFF0C\u4F46 profile \u548C App \u6388\u6743\u4ECD\u5C5E\u4E8E\u670D\u52A1\u5668\u8FD0\u884C\u73AF\u5883\u3002\u4E1A\u52A1\u5165\u53E3\u914D\u7F6E\u53EF\u4EE5\u6CBF\u7528\uFF0C\u98DE\u4E66\u5E94\u7528\u6388\u6743\u5FC5\u987B\u5728\u670D\u52A1\u5668\u4E0A\u4E5F\u5B8C\u6210\u4E00\u6B21\u3002" }, "body")
3408
+ ] }, "server")
3409
+ ] }, "deploy-cards"),
3410
+ /* @__PURE__ */ jsxs("div", { style: checklistGridStyle, children: [
3411
+ /* @__PURE__ */ jsx(ChecklistItem, { done: hasConnection, title: "\u540C\u540D profile", detail: `\u670D\u52A1\u5668\u4E0A\u4E5F\u8981\u6709 ${serverProfileName(serverDeployConnection)}` }, "same-profile"),
3412
+ /* @__PURE__ */ jsx(ChecklistItem, { done: true, title: "App Secret \u4E0D\u8FDB\u9875\u9762", detail: "\u53EA\u5728\u670D\u52A1\u5668\u6216\u5BC6\u94A5\u7CFB\u7EDF\u91CC\u8F93\u5165\uFF0C\u4E0D\u622A\u56FE\u3001\u4E0D\u53D1\u804A\u5929\u3002" }, "secret"),
3413
+ /* @__PURE__ */ jsx(ChecklistItem, { done: (connectorStatus.data?.subscribers?.length ?? 0) <= activeConnections.length, title: "\u53EA\u4FDD\u7559\u6B63\u5F0F\u76D1\u542C", detail: "\u4E0A\u4E91\u540E\u4E0D\u8981\u8BA9\u672C\u673A\u548C\u670D\u52A1\u5668\u540C\u65F6\u76D1\u542C\u540C\u4E00\u4E2A\u673A\u5668\u4EBA\u3002" }, "single-listener"),
3414
+ /* @__PURE__ */ jsx(ChecklistItem, { done: !runningOnLocalhost, title: "\u670D\u52A1\u5668\u4E0A\u91CD\u65B0\u68C0\u67E5", detail: runningOnLocalhost ? "\u90E8\u7F72\u5230\u670D\u52A1\u5668\u540E\uFF0C\u518D\u5728\u670D\u52A1\u5668\u9875\u9762\u70B9\u68C0\u67E5\u8FDE\u63A5\u3002" : "\u5F53\u524D\u9875\u9762\u5DF2\u5728\u670D\u52A1\u5668\u73AF\u5883\u3002" }, "recheck")
3415
+ ] }, "checklist"),
3416
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3417
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3418
+ /* @__PURE__ */ jsxs("div", { children: [
3419
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u7ED9\u5DE5\u7A0B\u5E08\u7684\u670D\u52A1\u5668\u7ED1\u5B9A\u547D\u4EE4" }, "title"),
3420
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5728 Paperclip \u670D\u52A1\u5668\u4E0A\u6267\u884C\u3002\u547D\u4EE4\u91CC\u7684 App Secret \u5360\u4F4D\u7B26\u5FC5\u987B\u7531\u7BA1\u7406\u5458\u5728\u670D\u52A1\u5668\u5B89\u5168\u8F93\u5165\u3002" }, "help")
3421
+ ] }, "copy"),
3422
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => void copyServerDeployCommands(), children: "\u590D\u5236\u547D\u4EE4" }, "copy")
3423
+ ] }, "head"),
3424
+ /* @__PURE__ */ jsx("code", { style: { ...codeStyle, marginTop: "10px" }, children: serverDeployCommands }, "code")
3425
+ ] }, "commands"),
3426
+ /* @__PURE__ */ jsxs("div", { style: successBoxStyle, children: [
3427
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "6px" }, children: "\u4E0A\u4E91\u540E\u600E\u4E48\u786E\u8BA4\u771F\u7684\u751F\u6548" }, "title"),
3428
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5728\u670D\u52A1\u5668\u9875\u9762\u5237\u65B0\u673A\u5668\u4EBA\u5217\u8868\uFF0C\u786E\u8BA4\u673A\u5668\u4EBA\u6C60\u91CC\u80FD\u770B\u5230\u540C\u540D\u673A\u5668\u4EBA\uFF1B\u4FDD\u5B58\u914D\u7F6E\uFF1B\u6253\u5F00\u201C\u81EA\u52A8\u76D1\u542C\u98DE\u4E66\u65B0\u6D88\u606F\u201D\u548C\u201C\u6B63\u5F0F\u53D1\u9001\u98DE\u4E66\u6D88\u606F\u201D\uFF1B\u6700\u540E\u4F18\u5148\u5728\u673A\u5668\u4EBA\u5355\u804A\u6216\u6D4B\u8BD5\u4F1A\u8BDD\u53D1\u9001\u771F\u5B9E\u6D4B\u8BD5\u8BDD\u672F\u3002" }, "body")
3429
+ ] }, "after-deploy")
3430
+ ] }, "deploy-panel") : null,
3431
+ activeAdvancedPanel === "runtime" ? /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3432
+ /* @__PURE__ */ jsx(ToggleField, { label: "\u6B63\u5F0F\u53D1\u9001\u98DE\u4E66\u6D88\u606F", checked: configJson.dryRunCli !== true, onChange: (checked) => patchConfig({ dryRunCli: !checked }), help: "\u5173\u95ED\u65F6\u53EA\u662F\u9875\u9762\u6A21\u62DF\uFF0C\u4E0D\u4F1A\u771F\u7684\u56DE\u590D\u98DE\u4E66\u3002" }, "dryRunCli"),
3433
+ /* @__PURE__ */ jsx(ToggleField, { label: "\u81EA\u52A8\u76D1\u542C\u98DE\u4E66\u65B0\u6D88\u606F", checked: configJson.enableEventSubscriber === true, onChange: (checked) => patchConfig({ enableEventSubscriber: checked }), help: "\u672C\u5730\u6D4B\u8BD5\u53EF\u4EE5\u6253\u5F00\uFF1B\u4E0A\u4E91\u540E\u53EA\u4FDD\u7559\u670D\u52A1\u5668\u76D1\u542C\u3002" }, "enableEventSubscriber"),
3434
+ /* @__PURE__ */ jsx(ToggleField, { label: "\u6536\u5230\u9700\u6C42\u540E\u5148\u56DE\u201C\u5DF2\u6536\u5230\u201D", checked: configJson.ackOnInbound === true, onChange: (checked) => patchConfig({ ackOnInbound: checked }) }, "ackOnInbound"),
3435
+ /* @__PURE__ */ jsx(ToggleField, { label: "\u6D4B\u8BD5\u53E3\u4EE4\u201C\u53EA\u56DE\u590D ok\u201D", checked: configJson.enableQuickReply !== false, onChange: (checked) => patchConfig({ enableQuickReply: checked }) }, "enableQuickReply"),
3436
+ /* @__PURE__ */ jsx(Field, { label: "lark-cli \u547D\u4EE4\u8DEF\u5F84", help: "\u666E\u901A\u7528\u6237\u4E0D\u7528\u6539\u3002\u7559\u7A7A\u6216\u4FDD\u6301 lark-cli \u65F6\uFF0C\u63D2\u4EF6\u4F1A\u4F18\u5148\u4F7F\u7528\u5305\u5185\u81EA\u5E26 CLI\uFF1B\u9700\u8981\u5F3A\u5236\u8D70\u670D\u52A1\u5668\u56FA\u5B9A\u8DEF\u5F84\u65F6\u624D\u586B\u5199\u5B8C\u6574\u8DEF\u5F84\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: configJson.larkCliBin ?? DEFAULT_CONFIG.larkCliBin, onChange: (event) => patchConfig({ larkCliBin: event.target.value }) }) }, "larkCliBin"),
3437
+ /* @__PURE__ */ jsx(Field, { label: "Paperclip \u5185\u90E8\u8BBF\u95EE\u5730\u5740", help: "\u53EF\u9009\u3002\u586B\u4E91\u7AEF\u57DF\u540D\u540E\uFF0C\u98DE\u4E66\u91CC\u4F1A\u9644\u5E26\u5185\u90E8\u4EFB\u52A1\u94FE\u63A5\uFF1B\u6CA1\u6709 Paperclip \u8D26\u53F7\u7684\u4EBA\u6253\u4E0D\u5F00\u3002", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: configJson.paperclipBaseUrl ?? "", placeholder: "https://paperclip.company.com", onChange: (event) => patchConfig({ paperclipBaseUrl: event.target.value }) }) }, "paperclipBaseUrl"),
3438
+ /* @__PURE__ */ jsx(Field, { label: "\u667A\u80FD\u4F53\u5B8C\u6210\u540E\u7684\u98DE\u4E66\u56DE\u590D", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: configJson.completionMessageTemplate ?? DEFAULT_CONFIG.completionMessageTemplate, onChange: (event) => patchConfig({ completionMessageTemplate: event.target.value }) }) }, "completionMessageTemplate")
3439
+ ] }, "runtime-panel") : null,
3440
+ activeAdvancedPanel === "events" ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
3441
+ productionMonitor ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3442
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u751F\u4EA7\u76D1\u63A7" }, "title"),
3443
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
3444
+ productionMonitor.message,
3445
+ "\u3002\u76D1\u542C\u8FDB\u7A0B ",
3446
+ productionMonitor.activeSubscriberCount,
3447
+ "/",
3448
+ productionMonitor.expectedSubscriberCount,
3449
+ "\uFF0C \u6700\u8FD1 30 \u5206\u949F\u9519\u8BEF ",
3450
+ productionMonitor.recentErrorCount,
3451
+ " \u6761\u3001\u63D0\u9192 ",
3452
+ productionMonitor.recentWarningCount,
3453
+ " \u6761\u3002",
3454
+ productionMonitor.lastWatchdogAt ? ` \u6700\u8FD1\u81EA\u68C0\uFF1A${productionMonitor.lastWatchdogAt}` : " \u81EA\u68C0\u4F1A\u5728\u670D\u52A1\u8FD0\u884C\u540E\u81EA\u52A8\u5F00\u59CB\u3002"
3455
+ ] }, "body")
3456
+ ] }, "monitor-summary") : null,
3457
+ productionMonitorChecks.length > 0 ? /* @__PURE__ */ jsx(CheckReport, { title: "\u76D1\u63A7\u68C0\u67E5\u9879", items: productionMonitorChecks }, "monitor-checks") : null,
3458
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3459
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u516C\u7F51\u56DE\u8C03\u5B89\u5168" }, "title"),
3460
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginBottom: "10px" }, children: "\u4E91\u7AEF webhook \u5EFA\u8BAE\u914D\u7F6E\u98DE\u4E66\u4E8B\u4EF6\u8BA2\u9605\u91CC\u7684 Verification Token \u548C Encrypt Key\u3002\u8FD9\u91CC\u586B\u5199 Paperclip Secret/Vault \u5F15\u7528\uFF0C\u63D2\u4EF6\u4E0D\u4F1A\u4FDD\u5B58\u5BC6\u94A5\u660E\u6587\u3002" }, "help"),
3461
+ /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3462
+ /* @__PURE__ */ jsx(Field, { label: "Verification Token Secret Ref", children: /* @__PURE__ */ jsx(
3463
+ "input",
3464
+ {
3465
+ style: inputStyle,
3466
+ value: configJson.eventVerificationTokenRef ?? "",
3467
+ placeholder: "\u4F8B\u5982\uFF1Afeishu/event-verification-token",
3468
+ onChange: (event) => patchConfig({ eventVerificationTokenRef: event.target.value })
3469
+ }
3470
+ ) }, "verification"),
3471
+ /* @__PURE__ */ jsx(Field, { label: "Encrypt Key Secret Ref", children: /* @__PURE__ */ jsx(
3472
+ "input",
3473
+ {
3474
+ style: inputStyle,
3475
+ value: configJson.eventEncryptKeyRef ?? "",
3476
+ placeholder: "\u4F8B\u5982\uFF1Afeishu/event-encrypt-key",
3477
+ onChange: (event) => patchConfig({ eventEncryptKeyRef: event.target.value })
3478
+ }
3479
+ ) }, "encrypt")
3480
+ ] }, "fields"),
3481
+ /* @__PURE__ */ jsxs("label", { style: { ...rowStyle, marginTop: "10px", justifyContent: "flex-start" }, children: [
3482
+ /* @__PURE__ */ jsx(
3483
+ "input",
3484
+ {
3485
+ type: "checkbox",
3486
+ checked: configJson.eventRequireSignature === true,
3487
+ onChange: (event) => patchConfig({ eventRequireSignature: event.target.checked })
3488
+ }
3489
+ ),
3490
+ /* @__PURE__ */ jsx("span", { children: "\u516C\u7F51\u56DE\u8C03\u5FC5\u987B\u6821\u9A8C x-lark-signature" })
3491
+ ] }, "signature")
3492
+ ] }, "webhook-security"),
3493
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3494
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3495
+ /* @__PURE__ */ jsxs("div", { children: [
3496
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3497
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u91CD\u8BD5\u961F\u5217" }, "title"),
3498
+ /* @__PURE__ */ jsx(StatusBadge, { tone: (retryQueue?.pendingCount ?? 0) > 0 ? "warning" : "success", children: (retryQueue?.pendingCount ?? 0) > 0 ? `${retryQueue?.pendingCount ?? 0} \u6761\u5F85\u91CD\u8BD5` : "\u6CA1\u6709\u5F85\u91CD\u8BD5\u6295\u9012" }, "status")
3499
+ ] }, "title-row"),
3500
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u98DE\u4E66\u56DE\u6267\u3001\u591A\u7EF4\u8868\u683C\u5199\u5165\u5931\u8D25\u65F6\u4F1A\u5148\u5165\u961F\uFF1B\u6743\u9650\u6216\u7F51\u7EDC\u6062\u590D\u540E\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u91CD\u8BD5\u3002" }, "detail")
3501
+ ] }, "copy"),
3502
+ /* @__PURE__ */ jsx(
3503
+ "button",
3504
+ {
3505
+ type: "button",
3506
+ style: buttonStyle,
3507
+ disabled: retryingQueue || (retryQueue?.pendingCount ?? 0) === 0,
3508
+ onClick: () => void runRetryQueue(),
3509
+ children: retryingQueue ? "\u91CD\u8BD5\u4E2D..." : "\u91CD\u8BD5\u5931\u8D25\u6295\u9012"
3510
+ },
3511
+ "retry"
3512
+ )
3513
+ ] }, "head"),
3514
+ (retryQueue?.items ?? []).length > 0 ? /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "8px", marginTop: "10px" }, children: (retryQueue?.items ?? []).slice(0, 3).map((item) => /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, overflowWrap: "anywhere" }, children: [
3515
+ item.status === "succeeded" ? "\u5DF2\u6210\u529F" : item.status === "failed" ? "\u5931\u8D25" : "\u5F85\u91CD\u8BD5",
3516
+ "\uFF1A",
3517
+ item.reason,
3518
+ " \xB7 ",
3519
+ item.profileName,
3520
+ " \xB7 \u5C1D\u8BD5 ",
3521
+ item.attemptCount,
3522
+ " \u6B21",
3523
+ item.lastError ? ` \xB7 ${item.lastError}` : ""
3524
+ ] }, item.id)) }, "items") : null
3525
+ ] }, "retry-queue"),
3526
+ /* @__PURE__ */ jsxs("div", { style: checklistGridStyle, children: [
3527
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isListening, title: "\u76D1\u542C\u5F00\u5173", detail: isListening ? "\u5DF2\u5F00\u542F" : "\u672A\u5F00\u542F" }, "listener"),
3528
+ /* @__PURE__ */ jsx(ChecklistItem, { done: (connectorStatus.data?.subscribers?.length ?? 0) > 0, title: "\u76D1\u542C\u8FDB\u7A0B", detail: `${connectorStatus.data?.subscribers?.length ?? 0} \u4E2A` }, "subscriber"),
3529
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isSendingRealMessages, title: "\u771F\u5B9E\u56DE\u590D", detail: isSendingRealMessages ? "\u5DF2\u5F00\u542F" : "\u6A21\u62DF\u6A21\u5F0F" }, "reply"),
3530
+ /* @__PURE__ */ jsx(ChecklistItem, { done: isSendingRealMessages, title: "\u9644\u4EF6\u4E0A\u4F20", detail: isSendingRealMessages ? "\u771F\u5B9E\u4E0B\u8F7D\u5E76\u6302\u5230\u4EFB\u52A1" : "\u53EA\u505A\u9644\u4EF6\u6A21\u62DF\u8BB0\u5F55" }, "attachment-upload")
3531
+ ] }, "state"),
3532
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3533
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u6700\u8FD1\u4E8B\u4EF6" }, "title"),
3534
+ /* @__PURE__ */ jsx(
3535
+ RecentEventList,
3536
+ {
3537
+ records: (connectorStatus.data?.recentRecords ?? []).slice(0, 8),
3538
+ emptyText: "\u6682\u65E0\u4E8B\u4EF6\u65E5\u5FD7\u3002"
3539
+ }
3540
+ )
3541
+ ] }, "logs")
3542
+ ] }, "events-panel") : null,
3543
+ activeAdvancedPanel === "base" ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
3544
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3545
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6CA1\u6709\u9700\u6C42\u6C60\u6C89\u6DC0\u8981\u6C42\u65F6\u53EF\u4EE5\u4E0D\u914D\u3002\u9700\u8981\u65F6\u65B0\u589E\u4E00\u5F20\u98DE\u4E66\u591A\u7EF4\u8868\u683C\u5199\u5165\u89C4\u5219\u3002" }, "copy"),
3546
+ /* @__PURE__ */ jsx(
3547
+ "button",
3548
+ {
3549
+ type: "button",
3550
+ style: buttonStyle,
3551
+ onClick: () => patchConfig({
3552
+ baseSinks: [
3553
+ ...baseSinks,
3554
+ {
3555
+ id: baseSinks.length === 0 ? "feishu-base" : `feishu-base-${baseSinks.length + 1}`,
3556
+ connectionId: preferredConnection?.id,
3557
+ enabled: true,
3558
+ baseToken: "",
3559
+ tableIdOrName: "\u9700\u6C42\u6C60",
3560
+ identity: "bot",
3561
+ fieldMap: {}
3562
+ }
3563
+ ]
3564
+ }),
3565
+ children: "\u6DFB\u52A0\u591A\u7EF4\u8868\u683C\u89C4\u5219"
3566
+ },
3567
+ "add"
3568
+ )
3569
+ ] }, "header"),
3570
+ baseSinks.length === 0 ? /* @__PURE__ */ jsx("div", { style: subtleBoxStyle, children: "\u5F53\u524D\u6CA1\u6709\u914D\u7F6E\u591A\u7EF4\u8868\u683C\u540C\u6B65\u3002" }, "empty") : null,
3571
+ baseSinks.map((sink, index) => /* @__PURE__ */ jsx("div", { style: subtleBoxStyle, children: /* @__PURE__ */ jsxs("div", { style: gridTwoStyle, children: [
3572
+ /* @__PURE__ */ jsx(Field, { label: "\u89C4\u5219\u540D\u79F0", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: sink.id ?? "", onChange: (event) => patchBaseSink(index, { id: event.target.value }) }) }, "id"),
3573
+ /* @__PURE__ */ jsx(Field, { label: "Base Token", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: sink.baseToken ?? "", onChange: (event) => patchBaseSink(index, { baseToken: event.target.value }) }) }, "baseToken"),
3574
+ /* @__PURE__ */ jsx(Field, { label: "\u6570\u636E\u8868\u540D\u79F0\u6216 ID", children: /* @__PURE__ */ jsx("input", { style: inputStyle, value: sink.tableIdOrName ?? "", onChange: (event) => patchBaseSink(index, { tableIdOrName: event.target.value }) }) }, "tableIdOrName"),
3575
+ /* @__PURE__ */ jsx(Field, { label: "\u4F7F\u7528\u54EA\u4E2A\u98DE\u4E66\u673A\u5668\u4EBA", children: /* @__PURE__ */ jsx("select", { style: selectStyle, value: sink.connectionId ?? preferredConnection?.id ?? "", onChange: (event) => patchBaseSink(index, { connectionId: event.target.value }), children: connectionOptionNodes(connections, `base-sink-${index}`, void 0, profiles) }) }, "connectionId")
3576
+ ] }, "fields") }, `${sink.id}-${index}`))
3577
+ ] }, "base-panel") : null,
3578
+ activeAdvancedPanel === "config" ? /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "12px" }, children: [
3579
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3580
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "6px" }, children: "\u53EF\u8FC1\u79FB\u5185\u5BB9" }, "title"),
3581
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u4F1A\u5BFC\u51FA\u5165\u53E3\u3001\u673A\u5668\u4EBA\u6C60\u3001\u80FD\u529B\u5F00\u5173\u3001\u591A\u7EF4\u8868\u683C\u89C4\u5219\u548C\u8FD0\u884C\u5F00\u5173\u3002App Secret\u3001\u8BBF\u95EE token\u3001\u4E8B\u4EF6\u5BC6\u94A5\u660E\u6587\u4E0D\u4F1A\u5BFC\u51FA\uFF1BSecret Ref \u4F1A\u4FDD\u7559\uFF0CBase Token \u4F1A\u968F\u591A\u7EF4\u8868\u683C\u89C4\u5219\u5BFC\u51FA\u3002" }, "body")
3582
+ ] }, "summary"),
3583
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3584
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3585
+ /* @__PURE__ */ jsxs("div", { children: [
3586
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u5BFC\u51FA\u5F53\u524D\u914D\u7F6E" }, "title"),
3587
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u9002\u5408\u8FC1\u79FB\u5230\u4E91\u7AEF\u6216\u53D1\u7ED9\u5DE5\u7A0B\u5E08\u590D\u73B0\u5165\u53E3\u89C4\u5219\u3002" }, "detail")
3588
+ ] }, "copy"),
3589
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: () => void copyConfigExport(), children: "\u590D\u5236\u914D\u7F6E JSON" }, "copy")
3590
+ ] }, "head"),
3591
+ /* @__PURE__ */ jsx("code", { style: { ...codeStyle, marginTop: "10px", maxHeight: "260px", overflow: "auto" }, children: exportedConfigText() }, "json")
3592
+ ] }, "export"),
3593
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3594
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3595
+ /* @__PURE__ */ jsxs("div", { children: [
3596
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u5BFC\u5165\u914D\u7F6E JSON" }, "title"),
3597
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5BFC\u5165\u53EA\u66F4\u65B0\u5F53\u524D\u9875\u9762\u72B6\u6001\uFF1B\u786E\u8BA4\u65E0\u8BEF\u540E\u518D\u70B9\u51FB\u9876\u90E8\u201C\u4FDD\u5B58\u914D\u7F6E\u201D\u3002" }, "detail")
3598
+ ] }, "copy"),
3599
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: previewConfigImport, children: "\u5BFC\u5165\u5230\u9875\u9762" }, "preview")
3600
+ ] }, "head"),
3601
+ /* @__PURE__ */ jsx(
3602
+ "textarea",
3603
+ {
3604
+ style: {
3605
+ ...inputStyle,
3606
+ height: "180px",
3607
+ marginTop: "10px",
3608
+ padding: "10px 12px",
3609
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
3610
+ resize: "vertical",
3611
+ lineHeight: 1.45
3612
+ },
3613
+ value: importConfigText,
3614
+ placeholder: '{\n "connections": [],\n "routes": []\n}',
3615
+ onChange: (event) => {
3616
+ setImportConfigText(event.target.value);
3617
+ setImportConfigError(null);
3618
+ }
3619
+ },
3620
+ "textarea"
3621
+ ),
3622
+ importConfigError ? /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, color: "var(--destructive)", marginTop: "8px" }, children: [
3623
+ "\u5BFC\u5165\u5931\u8D25\uFF1A",
3624
+ importConfigError
3625
+ ] }, "error") : null
3626
+ ] }, "import")
3627
+ ] }, "config-panel") : null,
3628
+ error ? /* @__PURE__ */ jsx("div", { style: { ...subtleBoxStyle, color: "var(--destructive)" }, children: error }, "error") : null
3629
+ ] }, "advanced-panel") : /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3630
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "6px" }, children: "\u70B9\u5F00\u4E00\u9879\u518D\u770B\u7EC6\u8282" }, "title"),
3631
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u666E\u901A\u7528\u6237\u901A\u5E38\u4E0D\u7528\u8FDB\u5165\u8FD9\u91CC\u3002\u9700\u8981\u5904\u7406 App Secret\u3001\u670D\u52A1\u5668\u90E8\u7F72\u3001\u76D1\u542C\u65E5\u5FD7\u6216\u591A\u7EF4\u8868\u683C\u540C\u6B65\u65F6\uFF0C\u518D\u9009\u62E9\u5BF9\u5E94\u9879\u76EE\u3002" }, "help")
3632
+ ] }, "advanced-empty")
3633
+ ] }, "product-advanced-links") : null
3634
+ ] });
3635
+ }
3636
+ function DashboardWidget(_props) {
3637
+ const { data, loading, error } = usePluginData(DATA_KEYS.status);
3638
+ if (loading) return /* @__PURE__ */ jsx("div", { children: "\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u8FDE\u63A5\u5668\u72B6\u6001..." });
3639
+ if (error) return /* @__PURE__ */ jsxs("div", { children: [
3640
+ "\u98DE\u4E66\u8FDE\u63A5\u5668\u72B6\u6001\u8BFB\u53D6\u5931\u8D25\uFF1A",
3641
+ error.message
3642
+ ] });
3643
+ const latest = data?.recentRecords?.[0];
3644
+ const health = connectorHealthLabel(data);
3645
+ const listenerCount = data?.subscribers?.filter((subscriber) => subscriber.running !== false && !subscriber.killed).length ?? 0;
3646
+ return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
3647
+ /* @__PURE__ */ jsx("strong", { children: "\u98DE\u4E66\u8FDE\u63A5\u5668" }),
3648
+ /* @__PURE__ */ jsxs("div", { style: rowStyle, children: [
3649
+ /* @__PURE__ */ jsx(Badge, { children: health }),
3650
+ /* @__PURE__ */ jsx(Badge, { children: data?.dryRunCli ? "\u6A21\u62DF\u56DE\u590D" : "\u771F\u5B9E\u56DE\u590D" }),
3651
+ /* @__PURE__ */ jsx(Badge, { children: `${data?.connectionCount ?? 0} \u4E2A\u673A\u5668\u4EBA` }),
3652
+ /* @__PURE__ */ jsx(Badge, { children: `${data?.routeCount ?? 0} \u6761\u5165\u53E3` })
3653
+ ] }),
3654
+ /* @__PURE__ */ jsxs("div", { children: [
3655
+ "\u63A5\u6536\u98DE\u4E66\u6D88\u606F\uFF1A",
3656
+ data?.eventSubscriberEnabled ? `\u5DF2\u5F00\u542F\uFF08${listenerCount} \u4E2A\u76D1\u542C\uFF09` : "\u672A\u5F00\u542F"
3657
+ ] }),
3658
+ latest ? /* @__PURE__ */ jsxs("div", { children: [
3659
+ "\u6700\u8FD1\u52A8\u6001\uFF1A",
3660
+ friendlyMonitorMessage(latest.message)
3661
+ ] }) : /* @__PURE__ */ jsx("div", { children: "\u6682\u65E0\u98DE\u4E66\u4E8B\u4EF6\u3002" })
3662
+ ] });
3663
+ }
3664
+ function FeishuSidebarLink(props) {
3665
+ const { data } = usePluginData(DATA_KEYS.status);
3666
+ const health = data?.monitor?.health;
3667
+ const toneColor = health === "error" ? "var(--destructive)" : health === "warning" ? "color-mix(in oklab, var(--primary) 62%, #b45309)" : "var(--primary)";
3668
+ return /* @__PURE__ */ jsxs(
3669
+ "a",
3670
+ {
3671
+ href: pluginSettingsHref(props),
3672
+ style: {
3673
+ display: "flex",
3674
+ alignItems: "center",
3675
+ gap: "10px",
3676
+ padding: "8px 12px",
3677
+ color: "var(--foreground)",
3678
+ textDecoration: "none",
3679
+ fontSize: "13px",
3680
+ fontWeight: 600
3681
+ },
3682
+ children: [
3683
+ /* @__PURE__ */ jsx(
3684
+ "span",
3685
+ {
3686
+ "aria-hidden": "true",
3687
+ style: {
3688
+ width: "8px",
3689
+ height: "8px",
3690
+ borderRadius: "999px",
3691
+ background: toneColor,
3692
+ flex: "0 0 auto"
3693
+ }
3694
+ }
3695
+ ),
3696
+ /* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: "\u98DE\u4E66\u8FDE\u63A5\u5668" }),
3697
+ data ? /* @__PURE__ */ jsx("span", { style: { marginLeft: "auto", color: "var(--muted-foreground)", fontSize: "11px" }, children: data.routeCount }) : null
3698
+ ]
3699
+ }
3700
+ );
3701
+ }
3702
+ function FeishuSidebarPanel(props = {}) {
3703
+ const { data, loading, error } = usePluginData(DATA_KEYS.status);
3704
+ if (loading) return /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u98DE\u4E66\u72B6\u6001\u8BFB\u53D6\u4E2D..." });
3705
+ if (error) return /* @__PURE__ */ jsx("div", { style: { ...helpStyle, color: "var(--destructive)" }, children: "\u98DE\u4E66\u72B6\u6001\u8BFB\u53D6\u5931\u8D25" });
3706
+ const monitor = data?.monitor;
3707
+ const nextHint = monitor?.message ? friendlyMonitorMessage(monitor.message) : data?.connectionCount ? "\u98DE\u4E66\u8FDE\u63A5\u5668\u5DF2\u914D\u7F6E\u3002" : "\u8FD8\u6CA1\u6709\u7ED1\u5B9A\u98DE\u4E66\u673A\u5668\u4EBA\u3002";
3708
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "8px", fontSize: "12px" }, children: [
3709
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u98DE\u4E66\u8FDE\u63A5\u5668" }),
3710
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "4px", color: "var(--muted-foreground)" }, children: [
3711
+ /* @__PURE__ */ jsxs("div", { children: [
3712
+ "\u673A\u5668\u4EBA\uFF1A",
3713
+ data?.connectionCount ?? 0,
3714
+ " \u4E2A"
3715
+ ] }),
3716
+ /* @__PURE__ */ jsxs("div", { children: [
3717
+ "\u5165\u53E3\uFF1A",
3718
+ data?.routeCount ?? 0,
3719
+ " \u6761"
3720
+ ] }),
3721
+ /* @__PURE__ */ jsxs("div", { children: [
3722
+ "\u72B6\u6001\uFF1A",
3723
+ connectorHealthLabel(data)
3724
+ ] })
3725
+ ] }),
3726
+ /* @__PURE__ */ jsx("div", { style: { lineHeight: 1.45 }, children: nextHint }),
3727
+ /* @__PURE__ */ jsx("a", { href: pluginSettingsHref(props), style: { color: "var(--primary)", textDecoration: "none", fontWeight: 700 }, children: "\u6253\u5F00\u914D\u7F6E" })
3728
+ ] });
3729
+ }
3730
+ function FeishuCommentReplyAction({ context }) {
3731
+ const replyIssueCommentToFeishu = usePluginAction(ACTION_KEYS.replyIssueCommentToFeishu);
3732
+ const [busy, setBusy] = useState(false);
3733
+ const [done, setDone] = useState(false);
3734
+ async function replyComment() {
3735
+ setBusy(true);
3736
+ setDone(false);
3737
+ try {
3738
+ await replyIssueCommentToFeishu({
3739
+ issueId: context.parentEntityId,
3740
+ commentId: context.entityId
3741
+ });
3742
+ setDone(true);
3743
+ window.setTimeout(() => setDone(false), 2400);
3744
+ } finally {
3745
+ setBusy(false);
3746
+ }
3747
+ }
3748
+ return /* @__PURE__ */ jsx(
3749
+ "button",
3750
+ {
3751
+ type: "button",
3752
+ onClick: () => void replyComment(),
3753
+ disabled: busy,
3754
+ style: {
3755
+ border: "1px solid var(--border)",
3756
+ borderRadius: "999px",
3757
+ padding: "2px 8px",
3758
+ background: "var(--background)",
3759
+ color: done ? "var(--primary)" : "var(--muted-foreground)",
3760
+ fontSize: "12px",
3761
+ cursor: busy ? "default" : "pointer"
3762
+ },
3763
+ title: "\u628A\u8FD9\u6761 Paperclip \u8BC4\u8BBA\u56DE\u590D\u5230\u539F\u98DE\u4E66\u7EBF\u7A0B",
3764
+ children: busy ? "\u56DE\u98DE\u4E66\u4E2D..." : done ? "\u5DF2\u56DE\u98DE\u4E66" : "\u56DE\u98DE\u4E66"
3765
+ }
3766
+ );
3767
+ }
3768
+ function FeishuIssueTab({ context }) {
3769
+ const { data, loading, error, refresh } = usePluginData(DATA_KEYS.issueSource, {
3770
+ issueId: context.entityId
3771
+ });
3772
+ const replyIssueSourceThread = usePluginAction(ACTION_KEYS.replyIssueSourceThread);
3773
+ const downloadIssueAttachments = usePluginAction(ACTION_KEYS.downloadIssueAttachments);
3774
+ const writeIssueBaseRecord = usePluginAction(ACTION_KEYS.writeIssueBaseRecord);
3775
+ const lookupIssueRequester = usePluginAction(ACTION_KEYS.lookupIssueRequester);
3776
+ const replyIssueCommentToFeishu = usePluginAction(ACTION_KEYS.replyIssueCommentToFeishu);
3777
+ const sendMessage = usePluginAction(ACTION_KEYS.sendMessage);
3778
+ const [replyText, setReplyText] = useState("");
3779
+ const [busyAction, setBusyAction] = useState(null);
3780
+ const [actionNotice, setActionNotice] = useState(null);
3781
+ async function runIssueAction(label, fn) {
3782
+ setBusyAction(label);
3783
+ setActionNotice(null);
3784
+ try {
3785
+ const result = await fn();
3786
+ if (result?.error) {
3787
+ setActionNotice({ tone: "error", text: result.error });
3788
+ return;
3789
+ }
3790
+ setActionNotice({ tone: "success", text: result?.content ?? result?.message ?? `${label}\u5DF2\u6267\u884C\u3002` });
3791
+ } catch (caught) {
3792
+ setActionNotice({ tone: "error", text: caught instanceof Error ? caught.message : String(caught) });
3793
+ } finally {
3794
+ setBusyAction(null);
3795
+ }
3796
+ }
3797
+ const issueId = data?.issueId ?? context.entityId;
3798
+ if (loading) return /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u6B63\u5728\u8BFB\u53D6\u98DE\u4E66\u6765\u6E90..." });
3799
+ if (error) return /* @__PURE__ */ jsxs("div", { style: { ...subtleBoxStyle, color: "var(--destructive)" }, children: [
3800
+ "\u98DE\u4E66\u6765\u6E90\u8BFB\u53D6\u5931\u8D25\uFF1A",
3801
+ error.message
3802
+ ] });
3803
+ if (!data?.found) {
3804
+ return /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3805
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800 }, children: "\u8FD9\u4E2A Issue \u4E0D\u662F\u7531\u98DE\u4E66\u8FDE\u63A5\u5668\u521B\u5EFA\u7684\u3002" }, "title"),
3806
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: "\u5982\u679C\u5B83\u786E\u5B9E\u6765\u81EA\u98DE\u4E66\uFF0C\u5237\u65B0\u540E\u4ECD\u672A\u663E\u793A\u6765\u6E90\uFF0C\u901A\u5E38\u662F\u5386\u53F2\u4EFB\u52A1\u8FD8\u6CA1\u6709\u5199\u5165\u98DE\u4E66\u6D88\u606F\u6620\u5C04\u3002" }, "detail")
3807
+ ] });
3808
+ }
3809
+ const conversationDisplay = issueSourceValue(
3810
+ issueSourceDisplayName(data.conversationName) ?? issueSourceDisplayName(data.conversationLabel) ?? (data.chatId ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null)
3811
+ );
3812
+ const requesterDisplay = issueSourceValue(
3813
+ issueSourceDisplayName(data.requesterName) ?? (data.requesterOpenId ? "\u5DF2\u8BB0\u5F55\uFF0C\u540D\u79F0\u5F85\u540C\u6B65" : null)
3814
+ );
3815
+ const originalMessageDisplay = issueSourceValue(
3816
+ data.messageId ? "\u5DF2\u8BB0\u5F55\uFF0C\u53EF\u56DE\u539F\u7EBF\u7A0B" : null
3817
+ );
3818
+ const hasDebugInfo = Boolean(data.chatId || data.rootMessageId || data.threadId || data.lastRunId || data.updatedAt);
3819
+ const detailRows = [
3820
+ ["\u5165\u53E3", issueSourceValue(data.entryName)],
3821
+ ["\u673A\u5668\u4EBA", issueSourceValue(data.botName)],
3822
+ ["\u4F1A\u8BDD", conversationDisplay],
3823
+ ["\u63D0\u51FA\u4EBA", requesterDisplay],
3824
+ ["\u539F\u6D88\u606F", originalMessageDisplay],
3825
+ ["\u9644\u4EF6", `${data.attachmentCount ?? data.attachments?.length ?? 0} \u4E2A`],
3826
+ ["\u56DE\u590D\u65B9\u5F0F", issueReplyModeLabel(data.replyMode)]
3827
+ ];
3828
+ const recentComments = data.recentComments ?? [];
3829
+ return /* @__PURE__ */ jsxs("div", { style: { ...productSectionStyle, maxWidth: "920px" }, children: [
3830
+ /* @__PURE__ */ jsxs("div", { style: sectionHeaderStyle, children: [
3831
+ /* @__PURE__ */ jsxs("div", { children: [
3832
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900, fontSize: "18px" }, children: "\u98DE\u4E66\u6765\u6E90" }, "title"),
3833
+ /* @__PURE__ */ jsxs("div", { style: helpStyle, children: [
3834
+ issueSourceValue(data.issueIdentifier, "\u5F53\u524D\u4EFB\u52A1"),
3835
+ " \u6765\u81EA\u98DE\u4E66\uFF0C\u4F1A\u6309\u5165\u53E3\u914D\u7F6E\u56DE\u5230\u539F\u4F1A\u8BDD\u3002"
3836
+ ] }, "subtitle")
3837
+ ] }, "copy"),
3838
+ /* @__PURE__ */ jsx("button", { type: "button", style: buttonStyle, onClick: refresh, children: "\u5237\u65B0" }, "refresh")
3839
+ ] }, "header"),
3840
+ /* @__PURE__ */ jsxs("div", { style: successBoxStyle, children: [
3841
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 900 }, children: "\u6765\u6E90\uFF1A\u98DE\u4E66" }, "headline"),
3842
+ /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, marginTop: "4px" }, children: [
3843
+ issueSourceValue(data.entryName),
3844
+ " \xB7 ",
3845
+ issueSourceValue(data.botName),
3846
+ " \xB7 ",
3847
+ issueReplyModeLabel(data.replyMode)
3848
+ ] }, "meta")
3849
+ ] }, "summary"),
3850
+ /* @__PURE__ */ jsx("div", { style: gridTwoStyle, children: detailRows.map(([label, value]) => /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3851
+ /* @__PURE__ */ jsx("div", { style: helpStyle, children: label }, "label"),
3852
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginTop: "4px", overflowWrap: "anywhere" }, children: value }, "value")
3853
+ ] }, label)) }, "details"),
3854
+ /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3855
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u98DE\u4E66\u64CD\u4F5C\u533A" }, "title"),
3856
+ /* @__PURE__ */ jsx(
3857
+ "textarea",
3858
+ {
3859
+ style: {
3860
+ ...inputStyle,
3861
+ height: "96px",
3862
+ padding: "10px 12px",
3863
+ resize: "vertical",
3864
+ lineHeight: 1.45
3865
+ },
3866
+ value: replyText,
3867
+ placeholder: "\u628A\u8981\u53D1\u56DE\u98DE\u4E66\u7684\u5185\u5BB9\u5199\u5728\u8FD9\u91CC",
3868
+ onChange: (event) => setReplyText(event.target.value)
3869
+ },
3870
+ "reply-text"
3871
+ ),
3872
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, marginTop: "10px" }, children: [
3873
+ /* @__PURE__ */ jsx(
3874
+ "button",
3875
+ {
3876
+ type: "button",
3877
+ style: primaryButtonStyle,
3878
+ disabled: busyAction !== null || replyText.trim().length === 0,
3879
+ onClick: () => void runIssueAction("\u56DE\u590D\u539F\u98DE\u4E66\u7EBF\u7A0B", async () => {
3880
+ const result = await replyIssueSourceThread({ issueId, text: replyText.trim() });
3881
+ setReplyText("");
3882
+ return result;
3883
+ }),
3884
+ children: busyAction === "\u56DE\u590D\u539F\u98DE\u4E66\u7EBF\u7A0B" ? "\u56DE\u590D\u4E2D..." : "\u56DE\u590D\u539F\u98DE\u4E66\u7EBF\u7A0B"
3885
+ },
3886
+ "reply"
3887
+ ),
3888
+ /* @__PURE__ */ jsx(
3889
+ "button",
3890
+ {
3891
+ type: "button",
3892
+ style: buttonStyle,
3893
+ disabled: busyAction !== null || replyText.trim().length === 0 || !data.chatId,
3894
+ onClick: () => void runIssueAction("\u8F6C\u53D1\u5230\u98DE\u4E66", async () => {
3895
+ const result = await sendMessage({
3896
+ connectionId: data.connectionId,
3897
+ chatId: data.chatId,
3898
+ text: replyText.trim()
3899
+ });
3900
+ setReplyText("");
3901
+ return { content: result && typeof result === "object" && "dryRun" in result ? "\u98DE\u4E66\u6D88\u606F\u5DF2\u63D0\u4EA4\u53D1\u9001\u3002" : "\u98DE\u4E66\u6D88\u606F\u5DF2\u63D0\u4EA4\u53D1\u9001\u3002" };
3902
+ }),
3903
+ children: busyAction === "\u8F6C\u53D1\u5230\u98DE\u4E66" ? "\u53D1\u9001\u4E2D..." : `\u7528${issueSourceValue(data.botName, "\u673A\u5668\u4EBA")}\u53D1\u9001`
3904
+ },
3905
+ "send"
3906
+ ),
3907
+ /* @__PURE__ */ jsx(
3908
+ "button",
3909
+ {
3910
+ type: "button",
3911
+ style: buttonStyle,
3912
+ disabled: busyAction !== null,
3913
+ onClick: () => void runIssueAction("\u4E0B\u8F7D\u539F\u6D88\u606F\u9644\u4EF6", () => downloadIssueAttachments({ issueId })),
3914
+ children: busyAction === "\u4E0B\u8F7D\u539F\u6D88\u606F\u9644\u4EF6" ? "\u4E0B\u8F7D\u4E2D..." : "\u4E0B\u8F7D\u539F\u6D88\u606F\u9644\u4EF6"
3915
+ },
3916
+ "download"
3917
+ ),
3918
+ /* @__PURE__ */ jsx(
3919
+ "button",
3920
+ {
3921
+ type: "button",
3922
+ style: buttonStyle,
3923
+ disabled: busyAction !== null,
3924
+ onClick: () => void runIssueAction("\u5199\u5165\u591A\u7EF4\u8868\u683C", () => writeIssueBaseRecord({ issueId, record: { "\u5904\u7406\u72B6\u6001": "\u5DF2\u4ECE Issue \u64CD\u4F5C\u533A\u540C\u6B65" } })),
3925
+ children: busyAction === "\u5199\u5165\u591A\u7EF4\u8868\u683C" ? "\u5199\u5165\u4E2D..." : "\u5199\u5165\u591A\u7EF4\u8868\u683C"
3926
+ },
3927
+ "base"
3928
+ ),
3929
+ /* @__PURE__ */ jsx(
3930
+ "button",
3931
+ {
3932
+ type: "button",
3933
+ style: buttonStyle,
3934
+ disabled: busyAction !== null,
3935
+ onClick: () => void runIssueAction("\u67E5\u8BE2\u63D0\u51FA\u4EBA", () => lookupIssueRequester({ issueId })),
3936
+ children: busyAction === "\u67E5\u8BE2\u63D0\u51FA\u4EBA" ? "\u67E5\u8BE2\u4E2D..." : "\u67E5\u8BE2\u63D0\u51FA\u4EBA"
3937
+ },
3938
+ "lookup"
3939
+ )
3940
+ ] }, "actions"),
3941
+ actionNotice ? /* @__PURE__ */ jsx(
3942
+ "div",
3943
+ {
3944
+ style: {
3945
+ ...actionNotice.tone === "success" ? successBoxStyle : subtleBoxStyle,
3946
+ marginTop: "10px",
3947
+ color: actionNotice.tone === "error" ? "var(--destructive)" : void 0
3948
+ },
3949
+ children: actionNotice.text
3950
+ },
3951
+ "action-notice"
3952
+ ) : null,
3953
+ /* @__PURE__ */ jsx("div", { style: { ...helpStyle, marginTop: "8px" }, children: "\u8FD9\u4E9B\u64CD\u4F5C\u4F1A\u8D70\u63D2\u4EF6\u53D7\u63A7\u52A8\u4F5C\u548C\u80FD\u529B\u4E2D\u5FC3\u5F00\u5173\uFF1B\u5F53\u524D\u4E3A\u6D4B\u8BD5\u6A21\u5F0F\u65F6\u53EA\u751F\u6210\u547D\u4EE4\uFF0C\u4E0D\u4F1A\u771F\u5B9E\u53D1\u98DE\u4E66\u3002" }, "detail")
3954
+ ] }, "technical"),
3955
+ data.attachments?.length ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3956
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u539F\u6D88\u606F\u9644\u4EF6" }, "title"),
3957
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "6px" }, children: data.attachments.map((attachment) => /* @__PURE__ */ jsxs("div", { style: { ...helpStyle, overflowWrap: "anywhere" }, children: [
3958
+ issueSourceDisplayName(attachment.filename) ?? "\u672A\u547D\u540D\u98DE\u4E66\u9644\u4EF6",
3959
+ "\uFF08",
3960
+ attachment.resourceType,
3961
+ "\uFF09"
3962
+ ] }, `${attachment.resourceType}:${attachment.resourceKey}`)) }, "list")
3963
+ ] }, "attachments") : null,
3964
+ recentComments.length > 0 ? /* @__PURE__ */ jsxs("div", { style: subtleBoxStyle, children: [
3965
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 800, marginBottom: "8px" }, children: "\u8BC4\u8BBA\u5FEB\u6377\u64CD\u4F5C" }, "title"),
3966
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "10px" }, children: recentComments.map((comment, index) => /* @__PURE__ */ jsxs(
3967
+ "div",
3968
+ {
3969
+ style: {
3970
+ display: "grid",
3971
+ gap: "8px",
3972
+ paddingTop: index === 0 ? 0 : "10px",
3973
+ borderTop: index === 0 ? "0" : "1px solid var(--border)"
3974
+ },
3975
+ children: [
3976
+ /* @__PURE__ */ jsx(
3977
+ "div",
3978
+ {
3979
+ style: {
3980
+ color: "var(--foreground)",
3981
+ lineHeight: 1.5,
3982
+ overflowWrap: "anywhere",
3983
+ whiteSpace: "pre-wrap"
3984
+ },
3985
+ children: comment.body
3986
+ },
3987
+ "body"
3988
+ ),
3989
+ /* @__PURE__ */ jsxs("div", { style: { ...rowStyle, justifyContent: "space-between" }, children: [
3990
+ /* @__PURE__ */ jsx("span", { style: helpStyle, children: comment.createdAt ? `\u8BC4\u8BBA\u65F6\u95F4\uFF1A${comment.createdAt}` : "Paperclip \u8BC4\u8BBA" }, "time"),
3991
+ /* @__PURE__ */ jsx(
3992
+ "button",
3993
+ {
3994
+ type: "button",
3995
+ style: buttonStyle,
3996
+ disabled: busyAction !== null,
3997
+ onClick: () => void runIssueAction("\u56DE\u590D\u8BC4\u8BBA\u5230\u98DE\u4E66", () => replyIssueCommentToFeishu({ issueId, commentId: comment.id })),
3998
+ children: busyAction === "\u56DE\u590D\u8BC4\u8BBA\u5230\u98DE\u4E66" ? "\u56DE\u590D\u4E2D..." : "\u56DE\u590D\u8FD9\u6761\u8BC4\u8BBA\u5230\u98DE\u4E66"
3999
+ },
4000
+ "reply"
4001
+ )
4002
+ ] }, "meta")
4003
+ ]
4004
+ },
4005
+ comment.id
4006
+ )) }, "list")
4007
+ ] }, "comment-actions") : null,
4008
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "8px" }, children: [
4009
+ data.issueUrl ? /* @__PURE__ */ jsx("a", { href: data.issueUrl, target: "_blank", rel: "noreferrer", style: linkButtonStyle, children: "\u6253\u5F00 Paperclip \u4EFB\u52A1\u94FE\u63A5" }, "issue-url") : null,
4010
+ hasDebugInfo ? /* @__PURE__ */ jsxs("details", { style: helpStyle, children: [
4011
+ /* @__PURE__ */ jsx("summary", { style: { cursor: "pointer", fontWeight: 700 }, children: "\u6392\u969C\u4FE1\u606F\uFF08\u5DE5\u7A0B\u5E08\uFF09" }),
4012
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "4px", marginTop: "8px", overflowWrap: "anywhere" }, children: [
4013
+ data.chatId ? /* @__PURE__ */ jsxs("span", { children: [
4014
+ "\u4F1A\u8BDD ID\uFF1A",
4015
+ data.chatId
4016
+ ] }, "chat") : null,
4017
+ data.rootMessageId ? /* @__PURE__ */ jsxs("span", { children: [
4018
+ "\u6839\u6D88\u606F\uFF1A",
4019
+ data.rootMessageId
4020
+ ] }, "root") : null,
4021
+ data.threadId ? /* @__PURE__ */ jsxs("span", { children: [
4022
+ "\u7EBF\u7A0B\uFF1A",
4023
+ data.threadId
4024
+ ] }, "thread") : null,
4025
+ data.lastRunId ? /* @__PURE__ */ jsxs("span", { children: [
4026
+ "\u6700\u8FD1\u6267\u884C\uFF1A",
4027
+ data.lastRunId,
4028
+ data.lastRunStatus ? `\uFF08${data.lastRunStatus}\uFF09` : ""
4029
+ ] }, "run") : null,
4030
+ data.updatedAt ? /* @__PURE__ */ jsxs("span", { children: [
4031
+ "\u6700\u8FD1\u66F4\u65B0\uFF1A",
4032
+ data.updatedAt
4033
+ ] }, "updated") : null
4034
+ ] }, "debug-items")
4035
+ ] }, "debug") : null
4036
+ ] }, "issue-links")
4037
+ ] });
4038
+ }
4039
+ export {
4040
+ DashboardWidget,
4041
+ FeishuCommentReplyAction,
4042
+ FeishuIssueTab,
4043
+ FeishuSettingsPage,
4044
+ FeishuSidebarLink,
4045
+ FeishuSidebarPanel
4046
+ };
4047
+ //# sourceMappingURL=index.js.map