@nextclaw/ui 0.11.15 → 0.11.17

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +16 -2
  2. package/dist/assets/ChannelsList-askIl_uW.js +8 -0
  3. package/dist/assets/ChatPage-C47h6sfA.js +36 -0
  4. package/dist/assets/DocBrowser-C_C7daBv.js +1 -0
  5. package/dist/assets/DocBrowser-Cf7uSIoM.js +1 -0
  6. package/dist/assets/DocBrowserContext-CJ-YKtWh.js +1 -0
  7. package/dist/assets/LogoBadge-DRDmIa7o.js +1 -0
  8. package/dist/assets/MarketplacePage-DaSRsFUA.js +49 -0
  9. package/dist/assets/MarketplacePage-q12sRrvZ.js +1 -0
  10. package/dist/assets/McpMarketplacePage-B7HZn8zG.js +40 -0
  11. package/dist/assets/ModelConfig-MSi8VF9p.js +1 -0
  12. package/dist/assets/ProvidersList-_NBpSQWn.js +1 -0
  13. package/dist/assets/RemoteAccessPage-DSmdSsCJ.js +1 -0
  14. package/dist/assets/RuntimeConfig-msA8NZOj.js +1 -0
  15. package/dist/assets/SearchConfig-BBtxHIN_.js +1 -0
  16. package/dist/assets/SecretsConfig-BMAqj52o.js +3 -0
  17. package/dist/assets/SessionsConfig-CEJqgz8F.js +2 -0
  18. package/dist/assets/book-open-1agbn9dT.js +1 -0
  19. package/dist/assets/chat-session-display-DBBUJOYN.js +1 -0
  20. package/dist/assets/chunk-JZWAC4HX-BUooP92l.js +3 -0
  21. package/dist/assets/config-hints-fGnUjDe9.js +1 -0
  22. package/dist/assets/config-jOAXZWun.js +1 -0
  23. package/dist/assets/config-layout-B-7erZRN.js +1 -0
  24. package/dist/assets/createLucideIcon-B8FV3fzy.js +1 -0
  25. package/dist/assets/dist-Cy668qFZ.js +15 -0
  26. package/dist/assets/dist-D3OJg9V0.js +1 -0
  27. package/dist/assets/external-link-DI4ZmR3r.js +1 -0
  28. package/dist/assets/hash-DoXBhX9w.js +1 -0
  29. package/dist/assets/i18n-Cn8SErDV.js +1 -0
  30. package/dist/assets/index-B2VeWxfm.css +1 -0
  31. package/dist/assets/index-bAeWRAyo.js +6 -0
  32. package/dist/assets/label-Cz0q8fx4.js +1 -0
  33. package/dist/assets/loader-circle-d_mzMi2S.js +1 -0
  34. package/dist/assets/logos-DjrINZ7P.js +1 -0
  35. package/dist/assets/marketplace-localization-CXeGRf6E.js +1 -0
  36. package/dist/assets/page-layout-Hr-Dvq4o.js +1 -0
  37. package/dist/assets/plus-BnGg0mB-.js +1 -0
  38. package/dist/assets/popover-_nEUAtWY.js +1 -0
  39. package/dist/assets/provider-models-C8JQUd1E.js +1 -0
  40. package/dist/assets/react-Bsr_GLhi.js +1 -0
  41. package/dist/assets/save-Caodcm4q.js +1 -0
  42. package/dist/assets/search-CQCQaN4Z.js +1 -0
  43. package/dist/assets/security-config-Zf1RBeS1.js +1 -0
  44. package/dist/assets/select-D60QRHg9.js +41 -0
  45. package/dist/assets/skeleton-BvV_2nf3.js +1 -0
  46. package/dist/assets/status-dot-D43lBF1a.js +1 -0
  47. package/dist/assets/switch-CcBS0F3U.js +1 -0
  48. package/dist/assets/tabs-custom-UTbefkqB.js +1 -0
  49. package/dist/assets/trash-2-DvPrU1xO.js +1 -0
  50. package/dist/assets/useConfirmDialog-B89bxcd6.js +1 -0
  51. package/dist/assets/useMutation-BpXHE2OV.js +1 -0
  52. package/dist/assets/x-C8AWDn7c.js +1 -0
  53. package/dist/index.html +18 -3
  54. package/package.json +8 -8
  55. package/src/api/ncp-session-query-cache.test.ts +64 -0
  56. package/src/api/ncp-session-query-cache.ts +72 -2
  57. package/src/api/types.ts +3 -0
  58. package/src/components/chat/ChatSidebar.tsx +3 -21
  59. package/src/components/chat/chat-session-display.test.ts +33 -0
  60. package/src/components/chat/chat-session-display.ts +15 -0
  61. package/src/components/chat/chat-sidebar-session-item.tsx +13 -4
  62. package/src/components/chat/containers/chat-message-list.container.tsx +2 -0
  63. package/src/components/chat/ncp/NcpChatPage.tsx +5 -5
  64. package/src/components/chat/ncp/ncp-chat-page-data.ts +2 -5
  65. package/src/components/chat/ncp/ncp-session-adapter.ts +21 -0
  66. package/src/components/chat/ncp/use-ncp-session-list-view.ts +2 -6
  67. package/src/components/common/session-context-icon.tsx +30 -0
  68. package/src/components/config/SessionsConfig.tsx +2 -6
  69. package/src/hooks/use-realtime-query-bridge.ts +5 -1
  70. package/src/lib/i18n.chat.ts +6 -0
  71. package/src/lib/session-context.utils.ts +95 -0
  72. package/src/transport/remote.transport.test.ts +1 -1
  73. package/vite.config.ts +2 -2
  74. package/dist/assets/ChannelsList-WmCqjuMG.js +0 -8
  75. package/dist/assets/ChatPage-vfnUvEdN.js +0 -37
  76. package/dist/assets/DocBrowser-Cuds8S4N.js +0 -1
  77. package/dist/assets/LogoBadge-CiukNh5R.js +0 -1
  78. package/dist/assets/MarketplacePage--cCya2vU.js +0 -49
  79. package/dist/assets/McpMarketplacePage-SYy23E4x.js +0 -40
  80. package/dist/assets/ModelConfig-D4Nd4HWX.js +0 -1
  81. package/dist/assets/ProvidersList-k95kUPqD.js +0 -1
  82. package/dist/assets/RemoteAccessPage-XjDtIQV4.js +0 -1
  83. package/dist/assets/RuntimeConfig-BR4oBxQ-.js +0 -1
  84. package/dist/assets/SearchConfig-fJjFykmH.js +0 -1
  85. package/dist/assets/SecretsConfig-D7CxxH1q.js +0 -3
  86. package/dist/assets/SessionsConfig-2hYobMkj.js +0 -2
  87. package/dist/assets/chat-session-display-BeoRHq9x.js +0 -1
  88. package/dist/assets/config-hints-CApS3K_7.js +0 -1
  89. package/dist/assets/config-layout-BHnOoweL.js +0 -1
  90. package/dist/assets/index-CfVmBgkf.css +0 -1
  91. package/dist/assets/index-DWrpxFk0.js +0 -8
  92. package/dist/assets/label-C2uGecRa.js +0 -1
  93. package/dist/assets/marketplace-localization-Dk31LJJJ.js +0 -1
  94. package/dist/assets/page-layout-DICppNFk.js +0 -1
  95. package/dist/assets/popover-DoacXI3f.js +0 -1
  96. package/dist/assets/provider-models-BOeNnjk9.js +0 -1
  97. package/dist/assets/security-config-54LcQtst.js +0 -1
  98. package/dist/assets/skeleton-DjjQR4NY.js +0 -1
  99. package/dist/assets/status-dot-OjV8JCSV.js +0 -1
  100. package/dist/assets/switch-Dvd2FqUB.js +0 -1
  101. package/dist/assets/tabs-custom-DlwuO0Gw.js +0 -1
  102. package/dist/assets/useConfirmDialog-BuB9l_2r.js +0 -1
  103. package/dist/assets/vendor-MCpnpiKt.js +0 -461
@@ -7,6 +7,7 @@ import { Input } from '@/components/ui/input';
7
7
  import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
8
8
  import { SelectItem } from '@/components/ui/select';
9
9
  import { ChatSidebarSessionItem } from '@/components/chat/chat-sidebar-session-item';
10
+ import { resolveSessionContextView } from '@/lib/session-context.utils';
10
11
  import { useChatSessionLabelService } from '@/components/chat/chat-session-label.service';
11
12
  import { useNcpSessionListView, type NcpSessionListItemView } from '@/components/chat/ncp/use-ncp-session-list-view';
12
13
  import { usePresenter } from '@/components/chat/presenter/chat-presenter-context';
@@ -79,25 +80,6 @@ function sessionTitle(session: SessionEntryView): string {
79
80
  return chunks[chunks.length - 1] || session.key;
80
81
  }
81
82
 
82
- function resolveSessionTypeLabel(
83
- sessionType: string,
84
- options: Array<{ value: string; label: string }>
85
- ): string | null {
86
- const normalized = sessionType.trim().toLowerCase();
87
- if (!normalized || normalized === 'native') {
88
- return null;
89
- }
90
- const matchedOption = options.find((option) => option.value.trim().toLowerCase() === normalized);
91
- if (matchedOption?.label.trim()) {
92
- return matchedOption.label.trim();
93
- }
94
- return normalized
95
- .split(/[-_]+/g)
96
- .filter(Boolean)
97
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
98
- .join(' ');
99
- }
100
-
101
83
  function resolveSessionTypeStatusText(option: {
102
84
  ready?: boolean;
103
85
  reasonMessage?: string | null;
@@ -300,7 +282,7 @@ export function ChatSidebar() {
300
282
  <div className="space-y-0.5">
301
283
  {group.items.map(({ session, runStatus }) => {
302
284
  const active = listSnapshot.selectedSessionKey === session.key;
303
- const sessionTypeLabel = resolveSessionTypeLabel(session.sessionType, inputSnapshot.sessionTypeOptions);
285
+ const context = resolveSessionContextView(session, inputSnapshot.sessionTypeOptions);
304
286
  const isEditing = editingSessionKey === session.key;
305
287
  const isSaving = savingSessionKey === session.key;
306
288
  return (
@@ -309,7 +291,7 @@ export function ChatSidebar() {
309
291
  session={session}
310
292
  active={active}
311
293
  runStatus={runStatus}
312
- sessionTypeLabel={sessionTypeLabel}
294
+ context={context}
313
295
  title={sessionTitle(session)}
314
296
  isEditing={isEditing}
315
297
  draftLabel={draftLabel}
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { SessionEntryView } from '@/api/types';
3
+ import { sessionDisplayName, sessionMatchesQuery } from '@/components/chat/chat-session-display';
4
+
5
+ function createSession(overrides: Partial<SessionEntryView> = {}): SessionEntryView {
6
+ return {
7
+ key: 'agent:demo:feishu:default',
8
+ createdAt: '2026-03-31T10:00:00.000Z',
9
+ updatedAt: '2026-03-31T10:00:00.000Z',
10
+ sessionType: 'native',
11
+ sessionTypeMutable: false,
12
+ messageCount: 3,
13
+ ...overrides
14
+ };
15
+ }
16
+
17
+ describe('chat-session-display', () => {
18
+ it('prefers the trimmed label as the display name', () => {
19
+ expect(sessionDisplayName(createSession({ label: ' Important customer ' }))).toBe('Important customer');
20
+ });
21
+
22
+ it('matches the search query against the session key', () => {
23
+ expect(sessionMatchesQuery(createSession(), 'feishu')).toBe(true);
24
+ });
25
+
26
+ it('matches the search query against the visible session label', () => {
27
+ expect(sessionMatchesQuery(createSession({ label: 'VIP Alpha Thread' }), 'alpha')).toBe(true);
28
+ });
29
+
30
+ it('treats an empty query as a match', () => {
31
+ expect(sessionMatchesQuery(createSession({ label: 'Anything' }), ' ')).toBe(true);
32
+ });
33
+ });
@@ -7,3 +7,18 @@ export function sessionDisplayName(session: SessionEntryView): string {
7
7
  const chunks = session.key.split(':');
8
8
  return chunks[chunks.length - 1] || session.key;
9
9
  }
10
+
11
+ function normalizeSessionSearchValue(value: string): string {
12
+ return value.trim().toLowerCase();
13
+ }
14
+
15
+ export function sessionMatchesQuery(session: SessionEntryView, query: string): boolean {
16
+ const normalizedQuery = normalizeSessionSearchValue(query);
17
+ if (!normalizedQuery) {
18
+ return true;
19
+ }
20
+
21
+ return [session.key, sessionDisplayName(session)]
22
+ .map(normalizeSessionSearchValue)
23
+ .some((value) => value.includes(normalizedQuery));
24
+ }
@@ -1,7 +1,9 @@
1
1
  import type { SessionEntryView } from '@/api/types';
2
+ import { SessionContextIconNode } from '@/components/common/session-context-icon';
2
3
  import { SessionRunBadge } from '@/components/common/SessionRunBadge';
3
4
  import { Button } from '@/components/ui/button';
4
5
  import { Input } from '@/components/ui/input';
6
+ import { type SessionContextView } from '@/lib/session-context.utils';
5
7
  import type { SessionRunStatus } from '@/lib/session-run-status';
6
8
  import { cn } from '@/lib/utils';
7
9
  import { formatDateTime, t } from '@/lib/i18n';
@@ -11,7 +13,7 @@ type ChatSidebarSessionItemProps = {
11
13
  session: SessionEntryView;
12
14
  active: boolean;
13
15
  runStatus?: SessionRunStatus;
14
- sessionTypeLabel: string | null;
16
+ context: SessionContextView;
15
17
  title: string;
16
18
  isEditing: boolean;
17
19
  draftLabel: string;
@@ -28,7 +30,7 @@ export function ChatSidebarSessionItem(props: ChatSidebarSessionItemProps) {
28
30
  session,
29
31
  active,
30
32
  runStatus,
31
- sessionTypeLabel,
33
+ context,
32
34
  title,
33
35
  isEditing,
34
36
  draftLabel,
@@ -40,6 +42,8 @@ export function ChatSidebarSessionItem(props: ChatSidebarSessionItemProps) {
40
42
  onCancel
41
43
  } = props;
42
44
 
45
+ const iconTone = active ? 'text-gray-700' : 'text-gray-500';
46
+
43
47
  return (
44
48
  <div
45
49
  className={cn(
@@ -102,7 +106,7 @@ export function ChatSidebarSessionItem(props: ChatSidebarSessionItemProps) {
102
106
  <div className="grid grid-cols-[minmax(0,1fr)_0.875rem] items-center gap-1.5 pr-8">
103
107
  <span className="flex min-w-0 items-center gap-1.5">
104
108
  <span className="truncate font-medium">{title}</span>
105
- {sessionTypeLabel ? (
109
+ {context.label ? (
106
110
  <span
107
111
  className={cn(
108
112
  'shrink-0 rounded-full border px-1.5 py-0.5 text-[10px] font-semibold leading-none',
@@ -111,7 +115,12 @@ export function ChatSidebarSessionItem(props: ChatSidebarSessionItemProps) {
111
115
  : 'border-gray-200 bg-gray-100 text-gray-500'
112
116
  )}
113
117
  >
114
- {sessionTypeLabel}
118
+ {context.label}
119
+ </span>
120
+ ) : null}
121
+ {context.icon ? (
122
+ <span className="inline-flex h-[1.125rem] w-[1.125rem] shrink-0 items-center justify-center">
123
+ <SessionContextIconNode icon={context.icon} className={iconTone} />
115
124
  </span>
116
125
  ) : null}
117
126
  </span>
@@ -57,6 +57,8 @@ function buildChatMessageTexts(language: string) {
57
57
  return {
58
58
  copyCodeLabel: t("chatCodeCopy"),
59
59
  copiedCodeLabel: t("chatCodeCopied"),
60
+ copyMessageLabel: t("chatMessageCopy"),
61
+ copiedMessageLabel: t("chatMessageCopied"),
60
62
  typingLabel: t("chatTyping"),
61
63
  };
62
64
  }
@@ -175,11 +175,11 @@ export function NcpChatPage({ view }: ChatPageProps) {
175
175
  };
176
176
 
177
177
  return appClient.subscribe((event) => {
178
- if (event.type === 'session.updated' && event.payload.sessionKey === activeSessionId) {
179
- attachRealtimeSessionStream();
180
- return;
181
- }
182
- if (event.type === 'session.summary.upsert' && event.payload.summary.sessionId === activeSessionId) {
178
+ if (
179
+ event.type === 'session.run-status' &&
180
+ event.payload.sessionKey === activeSessionId &&
181
+ event.payload.status === 'running'
182
+ ) {
183
183
  attachRealtimeSessionStream();
184
184
  }
185
185
  });
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
2
2
  import type { Dispatch, SetStateAction } from 'react';
3
3
  import type { SessionEntryView, ThinkingLevel } from '@/api/types';
4
4
  import type { ChatModelOption } from '@/components/chat/chat-input.types';
5
+ import { sessionMatchesQuery } from '@/components/chat/chat-session-display';
5
6
  import { adaptNcpSessionSummaries } from '@/components/chat/ncp/ncp-session-adapter';
6
7
  import { useChatSessionTypeState } from '@/components/chat/useChatSessionTypeState';
7
8
  import {
@@ -30,11 +31,7 @@ type UseNcpChatPageDataParams = {
30
31
  };
31
32
 
32
33
  function filterSessionsByQuery(sessions: SessionEntryView[], query: string): SessionEntryView[] {
33
- const normalizedQuery = query.trim().toLowerCase();
34
- if (!normalizedQuery) {
35
- return sessions;
36
- }
37
- return sessions.filter((session) => session.key.toLowerCase().includes(normalizedQuery));
34
+ return sessions.filter((session) => sessionMatchesQuery(session, query));
38
35
  }
39
36
 
40
37
  export function filterModelOptionsBySessionType(params: {
@@ -76,6 +76,25 @@ function readNcpSessionType(summary: NcpSessionSummaryView): string {
76
76
  return readOptionalString(metadata.session_type) ?? readOptionalString(metadata.sessionType) ?? 'native';
77
77
  }
78
78
 
79
+ function parseSessionContext(sessionKey: string): { channel?: string; type?: string } {
80
+ if (sessionKey === 'heartbeat') {
81
+ return { type: 'heartbeat' };
82
+ }
83
+ if (sessionKey.startsWith('cron:')) {
84
+ return { type: 'cron' };
85
+ }
86
+ if (sessionKey.startsWith('agent:')) {
87
+ const parts = sessionKey.split(':');
88
+ if (parts.length >= 3) {
89
+ const channel = parts[2];
90
+ if (channel && channel !== 'main' && channel !== 'direct') {
91
+ return { channel };
92
+ }
93
+ }
94
+ }
95
+ return {};
96
+ }
97
+
79
98
  function mapToolStatus(part: Extract<NcpMessagePart, { type: 'tool-invocation' }>): ToolInvocationStatus {
80
99
  if (part.state === 'result') {
81
100
  return ToolInvocationStatus.RESULT;
@@ -188,11 +207,13 @@ export function adaptNcpSessionSummary(summary: NcpSessionSummaryView): SessionE
188
207
  const label = readNcpSessionLabel(summary);
189
208
  const preferredModel = readNcpSessionPreferredModel(summary);
190
209
  const preferredThinking = readNcpSessionPreferredThinking(summary);
210
+ const context = parseSessionContext(summary.sessionId);
191
211
  return {
192
212
  key: summary.sessionId,
193
213
  createdAt: summary.updatedAt,
194
214
  updatedAt: summary.updatedAt,
195
215
  ...(label ? { label } : {}),
216
+ ...context,
196
217
  ...(preferredModel ? { preferredModel } : {}),
197
218
  ...(preferredThinking ? { preferredThinking } : {}),
198
219
  sessionType: readNcpSessionType(summary),
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from 'react';
2
2
  import type { SessionEntryView } from '@/api/types';
3
3
  import { adaptNcpSessionSummaries } from '@/components/chat/ncp/ncp-session-adapter';
4
+ import { sessionMatchesQuery } from '@/components/chat/chat-session-display';
4
5
  import { useChatSessionListStore } from '@/components/chat/stores/chat-session-list.store';
5
6
  import { useNcpSessions } from '@/hooks/useConfig';
6
7
  import type { SessionRunStatus } from '@/lib/session-run-status';
@@ -11,12 +12,7 @@ export type NcpSessionListItemView = {
11
12
  };
12
13
 
13
14
  function filterSessionsByQuery(sessions: readonly SessionEntryView[], query: string): SessionEntryView[] {
14
- const normalizedQuery = query.trim().toLowerCase();
15
- if (!normalizedQuery) {
16
- return [...sessions];
17
- }
18
-
19
- return sessions.filter((session) => session.key.toLowerCase().includes(normalizedQuery));
15
+ return sessions.filter((session) => sessionMatchesQuery(session, query));
20
16
  }
21
17
 
22
18
  export function useNcpSessionListView(params: { limit?: number } = {}) {
@@ -0,0 +1,30 @@
1
+ import { type SessionContextIcon } from '@/lib/session-context.utils';
2
+ import { LogoBadge } from '@/components/common/LogoBadge';
3
+ import { getChannelLogo } from '@/lib/logos';
4
+ import { cn } from '@/lib/utils';
5
+ import { AlarmClock, Bot, HeartPulse } from 'lucide-react';
6
+
7
+ export function SessionContextIconNode({ icon, className }: { icon: SessionContextIcon; className?: string }) {
8
+ if (icon.kind === 'channel-logo') {
9
+ return <ChannelLogoIcon channel={icon.channel} className={className} />;
10
+ }
11
+ if (icon.icon === 'heartbeat') {
12
+ return <HeartPulse className={cn('h-3.5 w-3.5', className)} />;
13
+ }
14
+ return <AlarmClock className={cn('h-3.5 w-3.5', className)} />;
15
+ }
16
+
17
+ function ChannelLogoIcon(
18
+ { channel, className }: { channel: string; className?: string }
19
+ ) {
20
+ const logoSrc = getChannelLogo(channel);
21
+ return (
22
+ <LogoBadge
23
+ name={channel}
24
+ src={logoSrc}
25
+ className={cn('h-4 w-4 rounded-[4px] border border-gray-200/80 bg-white', className)}
26
+ imgClassName="h-3 w-3 object-contain"
27
+ fallback={<Bot className="h-3 w-3 text-gray-500" />}
28
+ />
29
+ );
30
+ }
@@ -7,7 +7,7 @@ import { Input } from '@/components/ui/input';
7
7
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
8
8
  import { SessionRunBadge } from '@/components/common/SessionRunBadge';
9
9
  import { adaptNcpSessionSummaries } from '@/components/chat/ncp/ncp-session-adapter';
10
- import { sessionDisplayName } from '@/components/chat/chat-session-display';
10
+ import { sessionDisplayName, sessionMatchesQuery } from '@/components/chat/chat-session-display';
11
11
  import { cn } from '@/lib/utils';
12
12
  import { formatDateShort, formatDateTime, t } from '@/lib/i18n';
13
13
  import { PageLayout, PageHeader } from '@/components/layout/page-layout';
@@ -167,15 +167,11 @@ export function SessionsConfig() {
167
167
  const sessionEntries = useMemo(() => adaptNcpSessionSummaries(sessionSummaries), [sessionSummaries]);
168
168
  const sessionSummaryById = useMemo(() => new Map(sessionSummaries.map((session) => [session.sessionId, session])), [sessionSummaries]);
169
169
  const filteredSessions = useMemo(() => {
170
- const normalizedQuery = query.trim().toLowerCase();
171
170
  return sessionEntries.filter((session) => {
172
171
  if (selectedChannel !== 'all' && resolveChannelFromSessionKey(session.key) !== selectedChannel) {
173
172
  return false;
174
173
  }
175
- if (!normalizedQuery) {
176
- return true;
177
- }
178
- return session.key.toLowerCase().includes(normalizedQuery) || sessionDisplayName(session).toLowerCase().includes(normalizedQuery);
174
+ return sessionMatchesQuery(session, query);
179
175
  });
180
176
  }, [query, selectedChannel, sessionEntries]);
181
177
  const selectedSession = useMemo(
@@ -62,7 +62,11 @@ function handleRealtimeEvent(
62
62
  handleConfigUpdatedEvent(queryClient, configPath);
63
63
  return;
64
64
  }
65
- if (event.type === 'session.summary.upsert' || event.type === 'session.summary.delete') {
65
+ if (
66
+ event.type === 'session.run-status' ||
67
+ event.type === 'session.summary.upsert' ||
68
+ event.type === 'session.summary.delete'
69
+ ) {
66
70
  applyNcpSessionRealtimeEvent(queryClient, event);
67
71
  return;
68
72
  }
@@ -22,6 +22,10 @@ export const CHAT_LABELS: Record<string, { zh: string; en: string }> = {
22
22
  chatSessionTypeNative: { zh: '原生', en: 'Native' },
23
23
  chatSessionTypeCodex: { zh: 'Codex', en: 'Codex' },
24
24
  chatSessionTypeClaude: { zh: 'Claude Code', en: 'Claude Code' },
25
+ chatSessionTypeWeixin: { zh: '微信', en: 'WeChat' },
26
+ chatSessionTypeFeishu: { zh: '飞书', en: 'Feishu' },
27
+ chatSessionTypeHeartbeat: { zh: '心跳', en: 'Heartbeat' },
28
+ chatSessionTypeCron: { zh: '定时任务', en: 'Cron' },
25
29
  chatSessionTypeUnavailableSuffix: {
26
30
  zh: '当前不可用,请启用对应插件或新建 Native 会话。',
27
31
  en: 'is unavailable now. Re-enable the plugin or create a native session.'
@@ -85,6 +89,8 @@ export const CHAT_LABELS: Record<string, { zh: string; en: string }> = {
85
89
  chatUnknownPart: { zh: '未知消息片段', en: 'Unknown message part' },
86
90
  chatCodeCopy: { zh: '复制代码', en: 'Copy' },
87
91
  chatCodeCopied: { zh: '已复制', en: 'Copied' },
92
+ chatMessageCopy: { zh: '复制', en: 'Copy' },
93
+ chatMessageCopied: { zh: '已复制', en: 'Copied' },
88
94
  chatSidebarNewTask: { zh: '新任务', en: 'New Task' },
89
95
  chatSidebarSearchPlaceholder: { zh: '搜索对话...', en: 'Search conversations...' },
90
96
  chatSidebarScheduledTasks: { zh: '定时任务', en: 'Scheduled Tasks' },
@@ -0,0 +1,95 @@
1
+ import type { SessionEntryView } from '@/api/types';
2
+ import { t } from '@/lib/i18n';
3
+ import { getChannelLogo } from '@/lib/logos';
4
+
5
+ type SessionContextSymbolIcon = 'heartbeat' | 'cron';
6
+
7
+ export type SessionContextIcon =
8
+ | { kind: 'channel-logo'; channel: string }
9
+ | { kind: 'symbol'; icon: SessionContextSymbolIcon };
10
+
11
+ export type SessionContextView = {
12
+ icon: SessionContextIcon | null;
13
+ label: string | null;
14
+ };
15
+
16
+ const CHANNEL_ALIAS_REGISTRY: Record<string, string> = {
17
+ wx: 'weixin',
18
+ lark: 'feishu',
19
+ };
20
+
21
+ const TYPE_CONTEXT_REGISTRY: Record<string, { icon: SessionContextSymbolIcon }> = {
22
+ heartbeat: { icon: 'heartbeat' },
23
+ cron: { icon: 'cron' },
24
+ };
25
+
26
+ const SESSION_TYPE_LABEL_REGISTRY: Record<string, string> = {
27
+ codex: 'chatSessionTypeCodex',
28
+ claude: 'chatSessionTypeClaude',
29
+ };
30
+
31
+ function normalize(value: string | null | undefined): string {
32
+ return value?.trim().toLowerCase() ?? '';
33
+ }
34
+
35
+ function toTitleCaseByDelimiter(value: string): string {
36
+ return value
37
+ .split(/[-_]+/g)
38
+ .filter(Boolean)
39
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
40
+ .join(' ');
41
+ }
42
+
43
+ function resolveSessionTypeLabel(
44
+ sessionType: string,
45
+ options: Array<{ value: string; label: string }>
46
+ ): string | null {
47
+ const normalized = normalize(sessionType);
48
+ if (!normalized || normalized === 'native') {
49
+ return null;
50
+ }
51
+ const matchedOption = options.find((option) => normalize(option.value) === normalized);
52
+ if (matchedOption?.label.trim()) {
53
+ return matchedOption.label.trim();
54
+ }
55
+ return toTitleCaseByDelimiter(normalized);
56
+ }
57
+
58
+ function resolveChannelLogoName(channel: string): string | null {
59
+ const normalized = normalize(channel);
60
+ if (!normalized) {
61
+ return null;
62
+ }
63
+ const withAlias = CHANNEL_ALIAS_REGISTRY[normalized] ?? normalized;
64
+ return getChannelLogo(withAlias) ? withAlias : null;
65
+ }
66
+
67
+ export function resolveSessionContextView(
68
+ session: SessionEntryView,
69
+ options: Array<{ value: string; label: string }>
70
+ ): SessionContextView {
71
+ const logoChannel = resolveChannelLogoName(session.channel ?? '');
72
+ if (logoChannel) {
73
+ return {
74
+ icon: { kind: 'channel-logo', channel: logoChannel },
75
+ label: null,
76
+ };
77
+ }
78
+
79
+ const ncpType = normalize(session.type);
80
+ const typeView = TYPE_CONTEXT_REGISTRY[ncpType];
81
+ if (typeView) {
82
+ return { icon: { kind: 'symbol', icon: typeView.icon }, label: null };
83
+ }
84
+
85
+ const sessionType = normalize(session.sessionType);
86
+ const labelKey = SESSION_TYPE_LABEL_REGISTRY[sessionType];
87
+ if (labelKey) {
88
+ return { icon: null, label: t(labelKey) };
89
+ }
90
+
91
+ return {
92
+ icon: null,
93
+ label: resolveSessionTypeLabel(session.sessionType, options),
94
+ };
95
+ }
@@ -45,7 +45,7 @@ class MockWebSocket {
45
45
  }
46
46
 
47
47
  function lastSentRequestFrame(socket: MockWebSocket): { type: 'request'; id: string } {
48
- const raw = socket.sent.at(-1);
48
+ const raw = socket.sent[socket.sent.length - 1];
49
49
  if (!raw) {
50
50
  throw new Error('Expected a sent request frame.');
51
51
  }
package/vite.config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { defineConfig, splitVendorChunkPlugin } from 'vite';
1
+ import { defineConfig } from 'vite';
2
2
  import react from '@vitejs/plugin-react';
3
3
  import path from 'path';
4
4
 
@@ -6,7 +6,7 @@ const devProxyApiBase = process.env.VITE_DEV_PROXY_API_BASE ?? 'http://127.0.0.1
6
6
  const devProxyWsBase = devProxyApiBase.replace(/^http/i, 'ws');
7
7
 
8
8
  export default defineConfig({
9
- plugins: [react(), splitVendorChunkPlugin()],
9
+ plugins: [react()],
10
10
  resolve: {
11
11
  alias: {
12
12
  '@': path.resolve(__dirname, './src'),
@@ -1,8 +0,0 @@
1
- import{r as L,j as u,X as It,K as Pt,aw as Bt,b0 as Tt,b1 as Mt,b2 as Rt,a0 as Lt,g as ut,f as kt,b3 as Me,ae as Re,b4 as Dt,aj as dt,e as q,a3 as Ft,i as Ut,G as qt,H as _t}from"./vendor-MCpnpiKt.js";import{W as zt,t as c,c as K,I as Q,S as Ot,e as Ht,f as Kt,g as Jt,h as Vt,Y as ft,B as je,i as Gt,u as gt,a as ht,b as mt,Z as Yt,_ as Qt}from"./index-DWrpxFk0.js";import{S as pt}from"./status-dot-OjV8JCSV.js";import{L as yt}from"./LogoBadge-CiukNh5R.js";import{h as Se}from"./config-hints-CApS3K_7.js";import{c as Wt,b as Zt,a as Xt,C as $t}from"./config-layout-BHnOoweL.js";import{L as en}from"./label-C2uGecRa.js";import{S as tn}from"./switch-Dvd2FqUB.js";import{T as nn}from"./tabs-custom-DlwuO0Gw.js";import{P as rn,a as sn}from"./page-layout-DICppNFk.js";function bt(e){var n,t;const s=zt();return((n=e.tutorialUrls)==null?void 0:n[s])||((t=e.tutorialUrls)==null?void 0:t.default)||e.tutorialUrl}const an={telegram:"telegram.svg",slack:"slack.svg",discord:"discord.svg",whatsapp:"whatsapp.svg",qq:"qq.svg",feishu:"feishu.svg",dingtalk:"dingtalk.svg",wecom:"wecom.svg",weixin:"weixin.svg",mochat:"mochat.svg",email:"email.svg"};function on(e,s){const a=s.toLowerCase(),n=e[a];return n?`/logos/${n}`:null}function wt(e){return on(an,e)}function ln({value:e,onChange:s,className:a,placeholder:n=""}){const[t,r]=L.useState(""),i=l=>{l.key==="Enter"&&t.trim()?(l.preventDefault(),s([...e,t.trim()]),r("")):l.key==="Backspace"&&!t&&e.length>0&&s(e.slice(0,-1))},o=l=>{s(e.filter((d,h)=>h!==l))};return u.jsxs("div",{className:K("flex flex-wrap gap-2 p-2 border rounded-md min-h-[42px]",a),children:[e.map((l,d)=>u.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded text-sm",children:[l,u.jsx("button",{type:"button",onClick:()=>o(d),className:"hover:text-red-300 transition-colors",children:u.jsx(It,{className:"h-3 w-3"})})]},d)),u.jsx("input",{type:"text",value:t,onChange:l=>r(l.target.value),onKeyDown:i,className:"flex-1 outline-none min-w-[100px] bg-transparent text-sm",placeholder:n||c("enterTag")})]})}function cn(e){return e.includes("token")||e.includes("secret")||e.includes("password")?u.jsx(Pt,{className:"h-3.5 w-3.5 text-gray-500"}):e.includes("url")||e.includes("host")?u.jsx(Bt,{className:"h-3.5 w-3.5 text-gray-500"}):e.includes("email")||e.includes("mail")?u.jsx(Tt,{className:"h-3.5 w-3.5 text-gray-500"}):e.includes("id")||e.includes("from")?u.jsx(Mt,{className:"h-3.5 w-3.5 text-gray-500"}):e==="enabled"||e==="consentGranted"?u.jsx(Rt,{className:"h-3.5 w-3.5 text-gray-500"}):u.jsx(Lt,{className:"h-3.5 w-3.5 text-gray-500"})}function Le({channelName:e,fields:s,formData:a,jsonDrafts:n,setJsonDrafts:t,updateField:r,uiHints:i}){return u.jsx(u.Fragment,{children:s.map(o=>{const l=Se(`channels.${e}.${o.name}`,i),d=(l==null?void 0:l.label)??o.label,h=l==null?void 0:l.placeholder;return u.jsxs("div",{className:"space-y-2.5",children:[u.jsxs(en,{htmlFor:o.name,className:"flex items-center gap-2 text-sm font-medium text-gray-900",children:[cn(o.name),d]}),o.type==="boolean"&&u.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-3",children:[u.jsx("span",{className:"text-sm text-gray-500",children:a[o.name]?c("enabled"):c("disabled")}),u.jsx(tn,{id:o.name,checked:a[o.name]||!1,onCheckedChange:f=>r(o.name,f),className:"data-[state=checked]:bg-emerald-500"})]}),(o.type==="text"||o.type==="email")&&u.jsx(Q,{id:o.name,type:o.type,value:a[o.name]||"",onChange:f=>r(o.name,f.target.value),placeholder:h,className:"rounded-xl"}),o.type==="password"&&u.jsx(Q,{id:o.name,type:"password",value:a[o.name]||"",onChange:f=>r(o.name,f.target.value),placeholder:h??c("leaveBlankToKeepUnchanged"),className:"rounded-xl"}),o.type==="number"&&u.jsx(Q,{id:o.name,type:"number",value:a[o.name]||0,onChange:f=>r(o.name,parseInt(f.target.value,10)||0),placeholder:h,className:"rounded-xl"}),o.type==="tags"&&u.jsx(ln,{value:a[o.name]||[],onChange:f=>r(o.name,f)}),o.type==="select"&&u.jsxs(Ot,{value:a[o.name]||"",onValueChange:f=>r(o.name,f),children:[u.jsx(Ht,{className:"rounded-xl",children:u.jsx(Kt,{})}),u.jsx(Jt,{children:(o.options??[]).map(f=>u.jsx(Vt,{value:f.value,children:f.label},f.value))})]}),o.type==="json"&&u.jsx("textarea",{id:o.name,value:n[o.name]??"{}",onChange:f=>t(x=>({...x,[o.name]:f.target.value})),className:"min-h-[120px] w-full resize-none rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-mono"})]},o.name)})})}const te=[{value:"pairing",label:"pairing"},{value:"allowlist",label:"allowlist"},{value:"open",label:"open"},{value:"disabled",label:"disabled"}],ne=[{value:"open",label:"open"},{value:"allowlist",label:"allowlist"},{value:"disabled",label:"disabled"}],un=[{value:"off",label:"off"},{value:"partial",label:"partial"},{value:"block",label:"block"},{value:"progress",label:"progress"}];function ke(){return{telegram:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"token",type:"password",label:c("botToken")},{name:"allowFrom",type:"tags",label:c("allowFrom")},{name:"proxy",type:"text",label:c("proxy")},{name:"accountId",type:"text",label:c("accountId")},{name:"dmPolicy",type:"select",label:c("dmPolicy"),options:te},{name:"groupPolicy",type:"select",label:c("groupPolicy"),options:ne},{name:"groupAllowFrom",type:"tags",label:c("groupAllowFrom")},{name:"requireMention",type:"boolean",label:c("requireMention")},{name:"mentionPatterns",type:"tags",label:c("mentionPatterns")},{name:"groups",type:"json",label:c("groupRulesJson")}],discord:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"token",type:"password",label:c("botToken")},{name:"allowBots",type:"boolean",label:c("allowBotMessages")},{name:"allowFrom",type:"tags",label:c("allowFrom")},{name:"gatewayUrl",type:"text",label:c("gatewayUrl")},{name:"intents",type:"number",label:c("intents")},{name:"proxy",type:"text",label:c("proxy")},{name:"mediaMaxMb",type:"number",label:c("attachmentMaxSizeMb")},{name:"streaming",type:"select",label:c("streamingMode"),options:un},{name:"draftChunk",type:"json",label:c("draftChunkingJson")},{name:"textChunkLimit",type:"number",label:c("textChunkLimit")},{name:"accountId",type:"text",label:c("accountId")},{name:"dmPolicy",type:"select",label:c("dmPolicy"),options:te},{name:"groupPolicy",type:"select",label:c("groupPolicy"),options:ne},{name:"groupAllowFrom",type:"tags",label:c("groupAllowFrom")},{name:"requireMention",type:"boolean",label:c("requireMention")},{name:"mentionPatterns",type:"tags",label:c("mentionPatterns")},{name:"groups",type:"json",label:c("groupRulesJson")}],whatsapp:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"bridgeUrl",type:"text",label:c("bridgeUrl")},{name:"allowFrom",type:"tags",label:c("allowFrom")}],feishu:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"appId",type:"text",label:c("appId")},{name:"appSecret",type:"password",label:c("appSecret")},{name:"encryptKey",type:"password",label:c("encryptKey")},{name:"verificationToken",type:"password",label:c("verificationToken")},{name:"domain",type:"text",label:"Domain"},{name:"allowFrom",type:"tags",label:c("allowFrom")},{name:"dmPolicy",type:"select",label:c("dmPolicy"),options:te},{name:"groupPolicy",type:"select",label:c("groupPolicy"),options:ne},{name:"groupAllowFrom",type:"tags",label:c("groupAllowFrom")},{name:"requireMention",type:"boolean",label:c("requireMention")},{name:"mentionPatterns",type:"tags",label:c("mentionPatterns")},{name:"groups",type:"json",label:c("groupRulesJson")},{name:"accounts",type:"json",label:c("accountsJson")}],dingtalk:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"clientId",type:"text",label:c("clientId")},{name:"clientSecret",type:"password",label:c("clientSecret")},{name:"allowFrom",type:"tags",label:c("allowFrom")}],wecom:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"corpId",type:"text",label:c("corpId")},{name:"agentId",type:"text",label:c("agentId")},{name:"secret",type:"password",label:c("secret")},{name:"token",type:"password",label:c("token")},{name:"callbackPort",type:"number",label:c("callbackPort")},{name:"callbackPath",type:"text",label:c("callbackPath")},{name:"allowFrom",type:"tags",label:c("allowFrom")}],weixin:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"defaultAccountId",type:"text",label:c("defaultAccountId")},{name:"baseUrl",type:"text",label:c("baseUrl")},{name:"pollTimeoutMs",type:"number",label:c("pollTimeoutMs")},{name:"allowFrom",type:"tags",label:c("allowFrom")},{name:"accounts",type:"json",label:c("accountsJson")}],slack:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"mode",type:"text",label:c("mode")},{name:"webhookPath",type:"text",label:c("webhookPath")},{name:"allowBots",type:"boolean",label:c("allowBotMessages")},{name:"botToken",type:"password",label:c("botToken")},{name:"appToken",type:"password",label:c("appToken")}],email:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"consentGranted",type:"boolean",label:c("consentGranted")},{name:"imapHost",type:"text",label:c("imapHost")},{name:"imapPort",type:"number",label:c("imapPort")},{name:"imapUsername",type:"text",label:c("imapUsername")},{name:"imapPassword",type:"password",label:c("imapPassword")},{name:"fromAddress",type:"email",label:c("fromAddress")}],mochat:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"baseUrl",type:"text",label:c("baseUrl")},{name:"clawToken",type:"password",label:c("clawToken")},{name:"agentUserId",type:"text",label:c("agentUserId")},{name:"allowFrom",type:"tags",label:c("allowFrom")}],qq:[{name:"enabled",type:"boolean",label:c("enabled")},{name:"appId",type:"text",label:c("appId")},{name:"secret",type:"password",label:c("appSecret")},{name:"markdownSupport",type:"boolean",label:c("markdownSupport")},{name:"allowFrom",type:"tags",label:c("allowFrom")}]}}var H={},re,De;function dn(){return De||(De=1,re=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}),re}var se={},U={},Fe;function _(){if(Fe)return U;Fe=1;let e;const s=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];return U.getSymbolSize=function(n){if(!n)throw new Error('"version" cannot be null or undefined');if(n<1||n>40)throw new Error('"version" should be in range from 1 to 40');return n*4+17},U.getSymbolTotalCodewords=function(n){return s[n]},U.getBCHDigit=function(a){let n=0;for(;a!==0;)n++,a>>>=1;return n},U.setToSJISFunction=function(n){if(typeof n!="function")throw new Error('"toSJISFunc" is not a valid function.');e=n},U.isKanjiModeEnabled=function(){return typeof e<"u"},U.toSJIS=function(n){return e(n)},U}var ae={},Ue;function Ie(){return Ue||(Ue=1,(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function s(a){if(typeof a!="string")throw new Error("Param is not a string");switch(a.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+a)}}e.isValid=function(n){return n&&typeof n.bit<"u"&&n.bit>=0&&n.bit<4},e.from=function(n,t){if(e.isValid(n))return n;try{return s(n)}catch{return t}}})(ae)),ae}var oe,qe;function fn(){if(qe)return oe;qe=1;function e(){this.buffer=[],this.length=0}return e.prototype={get:function(s){const a=Math.floor(s/8);return(this.buffer[a]>>>7-s%8&1)===1},put:function(s,a){for(let n=0;n<a;n++)this.putBit((s>>>a-n-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(s){const a=Math.floor(this.length/8);this.buffer.length<=a&&this.buffer.push(0),s&&(this.buffer[a]|=128>>>this.length%8),this.length++}},oe=e,oe}var ie,_e;function gn(){if(_e)return ie;_e=1;function e(s){if(!s||s<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=s,this.data=new Uint8Array(s*s),this.reservedBit=new Uint8Array(s*s)}return e.prototype.set=function(s,a,n,t){const r=s*this.size+a;this.data[r]=n,t&&(this.reservedBit[r]=!0)},e.prototype.get=function(s,a){return this.data[s*this.size+a]},e.prototype.xor=function(s,a,n){this.data[s*this.size+a]^=n},e.prototype.isReserved=function(s,a){return this.reservedBit[s*this.size+a]},ie=e,ie}var le={},ze;function hn(){return ze||(ze=1,(function(e){const s=_().getSymbolSize;e.getRowColCoords=function(n){if(n===1)return[];const t=Math.floor(n/7)+2,r=s(n),i=r===145?26:Math.ceil((r-13)/(2*t-2))*2,o=[r-7];for(let l=1;l<t-1;l++)o[l]=o[l-1]-i;return o.push(6),o.reverse()},e.getPositions=function(n){const t=[],r=e.getRowColCoords(n),i=r.length;for(let o=0;o<i;o++)for(let l=0;l<i;l++)o===0&&l===0||o===0&&l===i-1||o===i-1&&l===0||t.push([r[o],r[l]]);return t}})(le)),le}var ce={},Oe;function mn(){if(Oe)return ce;Oe=1;const e=_().getSymbolSize,s=7;return ce.getPositions=function(n){const t=e(n);return[[0,0],[t-s,0],[0,t-s]]},ce}var ue={},He;function pn(){return He||(He=1,(function(e){e.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};const s={N1:3,N2:3,N3:40,N4:10};e.isValid=function(t){return t!=null&&t!==""&&!isNaN(t)&&t>=0&&t<=7},e.from=function(t){return e.isValid(t)?parseInt(t,10):void 0},e.getPenaltyN1=function(t){const r=t.size;let i=0,o=0,l=0,d=null,h=null;for(let f=0;f<r;f++){o=l=0,d=h=null;for(let x=0;x<r;x++){let g=t.get(f,x);g===d?o++:(o>=5&&(i+=s.N1+(o-5)),d=g,o=1),g=t.get(x,f),g===h?l++:(l>=5&&(i+=s.N1+(l-5)),h=g,l=1)}o>=5&&(i+=s.N1+(o-5)),l>=5&&(i+=s.N1+(l-5))}return i},e.getPenaltyN2=function(t){const r=t.size;let i=0;for(let o=0;o<r-1;o++)for(let l=0;l<r-1;l++){const d=t.get(o,l)+t.get(o,l+1)+t.get(o+1,l)+t.get(o+1,l+1);(d===4||d===0)&&i++}return i*s.N2},e.getPenaltyN3=function(t){const r=t.size;let i=0,o=0,l=0;for(let d=0;d<r;d++){o=l=0;for(let h=0;h<r;h++)o=o<<1&2047|t.get(d,h),h>=10&&(o===1488||o===93)&&i++,l=l<<1&2047|t.get(h,d),h>=10&&(l===1488||l===93)&&i++}return i*s.N3},e.getPenaltyN4=function(t){let r=0;const i=t.data.length;for(let l=0;l<i;l++)r+=t.data[l];return Math.abs(Math.ceil(r*100/i/5)-10)*s.N4};function a(n,t,r){switch(n){case e.Patterns.PATTERN000:return(t+r)%2===0;case e.Patterns.PATTERN001:return t%2===0;case e.Patterns.PATTERN010:return r%3===0;case e.Patterns.PATTERN011:return(t+r)%3===0;case e.Patterns.PATTERN100:return(Math.floor(t/2)+Math.floor(r/3))%2===0;case e.Patterns.PATTERN101:return t*r%2+t*r%3===0;case e.Patterns.PATTERN110:return(t*r%2+t*r%3)%2===0;case e.Patterns.PATTERN111:return(t*r%3+(t+r)%2)%2===0;default:throw new Error("bad maskPattern:"+n)}}e.applyMask=function(t,r){const i=r.size;for(let o=0;o<i;o++)for(let l=0;l<i;l++)r.isReserved(l,o)||r.xor(l,o,a(t,l,o))},e.getBestMask=function(t,r){const i=Object.keys(e.Patterns).length;let o=0,l=1/0;for(let d=0;d<i;d++){r(d),e.applyMask(d,t);const h=e.getPenaltyN1(t)+e.getPenaltyN2(t)+e.getPenaltyN3(t)+e.getPenaltyN4(t);e.applyMask(d,t),h<l&&(l=h,o=d)}return o}})(ue)),ue}var Y={},Ke;function xt(){if(Ke)return Y;Ke=1;const e=Ie(),s=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],a=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];return Y.getBlocksCount=function(t,r){switch(r){case e.L:return s[(t-1)*4+0];case e.M:return s[(t-1)*4+1];case e.Q:return s[(t-1)*4+2];case e.H:return s[(t-1)*4+3];default:return}},Y.getTotalCodewordsCount=function(t,r){switch(r){case e.L:return a[(t-1)*4+0];case e.M:return a[(t-1)*4+1];case e.Q:return a[(t-1)*4+2];case e.H:return a[(t-1)*4+3];default:return}},Y}var de={},V={},Je;function yn(){if(Je)return V;Je=1;const e=new Uint8Array(512),s=new Uint8Array(256);return(function(){let n=1;for(let t=0;t<255;t++)e[t]=n,s[n]=t,n<<=1,n&256&&(n^=285);for(let t=255;t<512;t++)e[t]=e[t-255]})(),V.log=function(n){if(n<1)throw new Error("log("+n+")");return s[n]},V.exp=function(n){return e[n]},V.mul=function(n,t){return n===0||t===0?0:e[s[n]+s[t]]},V}var Ve;function bn(){return Ve||(Ve=1,(function(e){const s=yn();e.mul=function(n,t){const r=new Uint8Array(n.length+t.length-1);for(let i=0;i<n.length;i++)for(let o=0;o<t.length;o++)r[i+o]^=s.mul(n[i],t[o]);return r},e.mod=function(n,t){let r=new Uint8Array(n);for(;r.length-t.length>=0;){const i=r[0];for(let l=0;l<t.length;l++)r[l]^=s.mul(t[l],i);let o=0;for(;o<r.length&&r[o]===0;)o++;r=r.slice(o)}return r},e.generateECPolynomial=function(n){let t=new Uint8Array([1]);for(let r=0;r<n;r++)t=e.mul(t,new Uint8Array([1,s.exp(r)]));return t}})(de)),de}var fe,Ge;function wn(){if(Ge)return fe;Ge=1;const e=bn();function s(a){this.genPoly=void 0,this.degree=a,this.degree&&this.initialize(this.degree)}return s.prototype.initialize=function(n){this.degree=n,this.genPoly=e.generateECPolynomial(this.degree)},s.prototype.encode=function(n){if(!this.genPoly)throw new Error("Encoder not initialized");const t=new Uint8Array(n.length+this.degree);t.set(n);const r=e.mod(t,this.genPoly),i=this.degree-r.length;if(i>0){const o=new Uint8Array(this.degree);return o.set(r,i),o}return r},fe=s,fe}var ge={},he={},me={},Ye;function Ct(){return Ye||(Ye=1,me.isValid=function(s){return!isNaN(s)&&s>=1&&s<=40}),me}var k={},Qe;function At(){if(Qe)return k;Qe=1;const e="[0-9]+",s="[A-Z $%*+\\-./:]+";let a="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";a=a.replace(/u/g,"\\u");const n="(?:(?![A-Z0-9 $%*+\\-./:]|"+a+`)(?:.|[\r
2
- ]))+`;k.KANJI=new RegExp(a,"g"),k.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),k.BYTE=new RegExp(n,"g"),k.NUMERIC=new RegExp(e,"g"),k.ALPHANUMERIC=new RegExp(s,"g");const t=new RegExp("^"+a+"$"),r=new RegExp("^"+e+"$"),i=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");return k.testKanji=function(l){return t.test(l)},k.testNumeric=function(l){return r.test(l)},k.testAlphanumeric=function(l){return i.test(l)},k}var We;function z(){return We||(We=1,(function(e){const s=Ct(),a=At();e.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(r,i){if(!r.ccBits)throw new Error("Invalid mode: "+r);if(!s.isValid(i))throw new Error("Invalid version: "+i);return i>=1&&i<10?r.ccBits[0]:i<27?r.ccBits[1]:r.ccBits[2]},e.getBestModeForData=function(r){return a.testNumeric(r)?e.NUMERIC:a.testAlphanumeric(r)?e.ALPHANUMERIC:a.testKanji(r)?e.KANJI:e.BYTE},e.toString=function(r){if(r&&r.id)return r.id;throw new Error("Invalid mode")},e.isValid=function(r){return r&&r.bit&&r.ccBits};function n(t){if(typeof t!="string")throw new Error("Param is not a string");switch(t.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+t)}}e.from=function(r,i){if(e.isValid(r))return r;try{return n(r)}catch{return i}}})(he)),he}var Ze;function xn(){return Ze||(Ze=1,(function(e){const s=_(),a=xt(),n=Ie(),t=z(),r=Ct(),i=7973,o=s.getBCHDigit(i);function l(x,g,y){for(let A=1;A<=40;A++)if(g<=e.getCapacity(A,y,x))return A}function d(x,g){return t.getCharCountIndicator(x,g)+4}function h(x,g){let y=0;return x.forEach(function(A){const T=d(A.mode,g);y+=T+A.getBitsLength()}),y}function f(x,g){for(let y=1;y<=40;y++)if(h(x,y)<=e.getCapacity(y,g,t.MIXED))return y}e.from=function(g,y){return r.isValid(g)?parseInt(g,10):y},e.getCapacity=function(g,y,A){if(!r.isValid(g))throw new Error("Invalid QR Code version");typeof A>"u"&&(A=t.BYTE);const T=s.getSymbolTotalCodewords(g),E=a.getTotalCodewordsCount(g,y),B=(T-E)*8;if(A===t.MIXED)return B;const b=B-d(A,g);switch(A){case t.NUMERIC:return Math.floor(b/10*3);case t.ALPHANUMERIC:return Math.floor(b/11*2);case t.KANJI:return Math.floor(b/13);case t.BYTE:default:return Math.floor(b/8)}},e.getBestVersionForData=function(g,y){let A;const T=n.from(y,n.M);if(Array.isArray(g)){if(g.length>1)return f(g,T);if(g.length===0)return 1;A=g[0]}else A=g;return l(A.mode,A.getLength(),T)},e.getEncodedBits=function(g){if(!r.isValid(g)||g<7)throw new Error("Invalid QR Code version");let y=g<<12;for(;s.getBCHDigit(y)-o>=0;)y^=i<<s.getBCHDigit(y)-o;return g<<12|y}})(ge)),ge}var pe={},Xe;function Cn(){if(Xe)return pe;Xe=1;const e=_(),s=1335,a=21522,n=e.getBCHDigit(s);return pe.getEncodedBits=function(r,i){const o=r.bit<<3|i;let l=o<<10;for(;e.getBCHDigit(l)-n>=0;)l^=s<<e.getBCHDigit(l)-n;return(o<<10|l)^a},pe}var ye={},be,$e;function An(){if($e)return be;$e=1;const e=z();function s(a){this.mode=e.NUMERIC,this.data=a.toString()}return s.getBitsLength=function(n){return 10*Math.floor(n/3)+(n%3?n%3*3+1:0)},s.prototype.getLength=function(){return this.data.length},s.prototype.getBitsLength=function(){return s.getBitsLength(this.data.length)},s.prototype.write=function(n){let t,r,i;for(t=0;t+3<=this.data.length;t+=3)r=this.data.substr(t,3),i=parseInt(r,10),n.put(i,10);const o=this.data.length-t;o>0&&(r=this.data.substr(t),i=parseInt(r,10),n.put(i,o*3+1))},be=s,be}var we,et;function vn(){if(et)return we;et=1;const e=z(),s=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function a(n){this.mode=e.ALPHANUMERIC,this.data=n}return a.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)},a.prototype.getLength=function(){return this.data.length},a.prototype.getBitsLength=function(){return a.getBitsLength(this.data.length)},a.prototype.write=function(t){let r;for(r=0;r+2<=this.data.length;r+=2){let i=s.indexOf(this.data[r])*45;i+=s.indexOf(this.data[r+1]),t.put(i,11)}this.data.length%2&&t.put(s.indexOf(this.data[r]),6)},we=a,we}var xe,tt;function Nn(){if(tt)return xe;tt=1;const e=z();function s(a){this.mode=e.BYTE,typeof a=="string"?this.data=new TextEncoder().encode(a):this.data=new Uint8Array(a)}return s.getBitsLength=function(n){return n*8},s.prototype.getLength=function(){return this.data.length},s.prototype.getBitsLength=function(){return s.getBitsLength(this.data.length)},s.prototype.write=function(a){for(let n=0,t=this.data.length;n<t;n++)a.put(this.data[n],8)},xe=s,xe}var Ce,nt;function En(){if(nt)return Ce;nt=1;const e=z(),s=_();function a(n){this.mode=e.KANJI,this.data=n}return a.getBitsLength=function(t){return t*13},a.prototype.getLength=function(){return this.data.length},a.prototype.getBitsLength=function(){return a.getBitsLength(this.data.length)},a.prototype.write=function(n){let t;for(t=0;t<this.data.length;t++){let r=s.toSJIS(this.data[t]);if(r>=33088&&r<=40956)r-=33088;else if(r>=57408&&r<=60351)r-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+`
3
- Make sure your charset is UTF-8`);r=(r>>>8&255)*192+(r&255),n.put(r,13)}},Ce=a,Ce}var Ae={exports:{}},rt;function jn(){return rt||(rt=1,(function(e){var s={single_source_shortest_paths:function(a,n,t){var r={},i={};i[n]=0;var o=s.PriorityQueue.make();o.push(n,0);for(var l,d,h,f,x,g,y,A,T;!o.empty();){l=o.pop(),d=l.value,f=l.cost,x=a[d]||{};for(h in x)x.hasOwnProperty(h)&&(g=x[h],y=f+g,A=i[h],T=typeof i[h]>"u",(T||A>y)&&(i[h]=y,o.push(h,y),r[h]=d))}if(typeof t<"u"&&typeof i[t]>"u"){var E=["Could not find a path from ",n," to ",t,"."].join("");throw new Error(E)}return r},extract_shortest_path_from_predecessor_list:function(a,n){for(var t=[],r=n;r;)t.push(r),a[r],r=a[r];return t.reverse(),t},find_path:function(a,n,t){var r=s.single_source_shortest_paths(a,n,t);return s.extract_shortest_path_from_predecessor_list(r,t)},PriorityQueue:{make:function(a){var n=s.PriorityQueue,t={},r;a=a||{};for(r in n)n.hasOwnProperty(r)&&(t[r]=n[r]);return t.queue=[],t.sorter=a.sorter||n.default_sorter,t},default_sorter:function(a,n){return a.cost-n.cost},push:function(a,n){var t={value:a,cost:n};this.queue.push(t),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=s})(Ae)),Ae.exports}var st;function Sn(){return st||(st=1,(function(e){const s=z(),a=An(),n=vn(),t=Nn(),r=En(),i=At(),o=_(),l=jn();function d(E){return unescape(encodeURIComponent(E)).length}function h(E,B,b){const N=[];let M;for(;(M=E.exec(b))!==null;)N.push({data:M[0],index:M.index,mode:B,length:M[0].length});return N}function f(E){const B=h(i.NUMERIC,s.NUMERIC,E),b=h(i.ALPHANUMERIC,s.ALPHANUMERIC,E);let N,M;return o.isKanjiModeEnabled()?(N=h(i.BYTE,s.BYTE,E),M=h(i.KANJI,s.KANJI,E)):(N=h(i.BYTE_KANJI,s.BYTE,E),M=[]),B.concat(b,N,M).sort(function(S,I){return S.index-I.index}).map(function(S){return{data:S.data,mode:S.mode,length:S.length}})}function x(E,B){switch(B){case s.NUMERIC:return a.getBitsLength(E);case s.ALPHANUMERIC:return n.getBitsLength(E);case s.KANJI:return r.getBitsLength(E);case s.BYTE:return t.getBitsLength(E)}}function g(E){return E.reduce(function(B,b){const N=B.length-1>=0?B[B.length-1]:null;return N&&N.mode===b.mode?(B[B.length-1].data+=b.data,B):(B.push(b),B)},[])}function y(E){const B=[];for(let b=0;b<E.length;b++){const N=E[b];switch(N.mode){case s.NUMERIC:B.push([N,{data:N.data,mode:s.ALPHANUMERIC,length:N.length},{data:N.data,mode:s.BYTE,length:N.length}]);break;case s.ALPHANUMERIC:B.push([N,{data:N.data,mode:s.BYTE,length:N.length}]);break;case s.KANJI:B.push([N,{data:N.data,mode:s.BYTE,length:d(N.data)}]);break;case s.BYTE:B.push([{data:N.data,mode:s.BYTE,length:d(N.data)}])}}return B}function A(E,B){const b={},N={start:{}};let M=["start"];for(let w=0;w<E.length;w++){const S=E[w],I=[];for(let v=0;v<S.length;v++){const P=S[v],j=""+w+v;I.push(j),b[j]={node:P,lastCount:0},N[j]={};for(let m=0;m<M.length;m++){const p=M[m];b[p]&&b[p].node.mode===P.mode?(N[p][j]=x(b[p].lastCount+P.length,P.mode)-x(b[p].lastCount,P.mode),b[p].lastCount+=P.length):(b[p]&&(b[p].lastCount=P.length),N[p][j]=x(P.length,P.mode)+4+s.getCharCountIndicator(P.mode,B))}}M=I}for(let w=0;w<M.length;w++)N[M[w]].end=0;return{map:N,table:b}}function T(E,B){let b;const N=s.getBestModeForData(E);if(b=s.from(B,N),b!==s.BYTE&&b.bit<N.bit)throw new Error('"'+E+'" cannot be encoded with mode '+s.toString(b)+`.
4
- Suggested mode is: `+s.toString(N));switch(b===s.KANJI&&!o.isKanjiModeEnabled()&&(b=s.BYTE),b){case s.NUMERIC:return new a(E);case s.ALPHANUMERIC:return new n(E);case s.KANJI:return new r(E);case s.BYTE:return new t(E)}}e.fromArray=function(B){return B.reduce(function(b,N){return typeof N=="string"?b.push(T(N,null)):N.data&&b.push(T(N.data,N.mode)),b},[])},e.fromString=function(B,b){const N=f(B,o.isKanjiModeEnabled()),M=y(N),w=A(M,b),S=l.find_path(w.map,"start","end"),I=[];for(let v=1;v<S.length-1;v++)I.push(w.table[S[v]].node);return e.fromArray(g(I))},e.rawSplit=function(B){return e.fromArray(f(B,o.isKanjiModeEnabled()))}})(ye)),ye}var at;function In(){if(at)return se;at=1;const e=_(),s=Ie(),a=fn(),n=gn(),t=hn(),r=mn(),i=pn(),o=xt(),l=wn(),d=xn(),h=Cn(),f=z(),x=Sn();function g(w,S){const I=w.size,v=r.getPositions(S);for(let P=0;P<v.length;P++){const j=v[P][0],m=v[P][1];for(let p=-1;p<=7;p++)if(!(j+p<=-1||I<=j+p))for(let C=-1;C<=7;C++)m+C<=-1||I<=m+C||(p>=0&&p<=6&&(C===0||C===6)||C>=0&&C<=6&&(p===0||p===6)||p>=2&&p<=4&&C>=2&&C<=4?w.set(j+p,m+C,!0,!0):w.set(j+p,m+C,!1,!0))}}function y(w){const S=w.size;for(let I=8;I<S-8;I++){const v=I%2===0;w.set(I,6,v,!0),w.set(6,I,v,!0)}}function A(w,S){const I=t.getPositions(S);for(let v=0;v<I.length;v++){const P=I[v][0],j=I[v][1];for(let m=-2;m<=2;m++)for(let p=-2;p<=2;p++)m===-2||m===2||p===-2||p===2||m===0&&p===0?w.set(P+m,j+p,!0,!0):w.set(P+m,j+p,!1,!0)}}function T(w,S){const I=w.size,v=d.getEncodedBits(S);let P,j,m;for(let p=0;p<18;p++)P=Math.floor(p/3),j=p%3+I-8-3,m=(v>>p&1)===1,w.set(P,j,m,!0),w.set(j,P,m,!0)}function E(w,S,I){const v=w.size,P=h.getEncodedBits(S,I);let j,m;for(j=0;j<15;j++)m=(P>>j&1)===1,j<6?w.set(j,8,m,!0):j<8?w.set(j+1,8,m,!0):w.set(v-15+j,8,m,!0),j<8?w.set(8,v-j-1,m,!0):j<9?w.set(8,15-j-1+1,m,!0):w.set(8,15-j-1,m,!0);w.set(v-8,8,1,!0)}function B(w,S){const I=w.size;let v=-1,P=I-1,j=7,m=0;for(let p=I-1;p>0;p-=2)for(p===6&&p--;;){for(let C=0;C<2;C++)if(!w.isReserved(P,p-C)){let R=!1;m<S.length&&(R=(S[m]>>>j&1)===1),w.set(P,p-C,R),j--,j===-1&&(m++,j=7)}if(P+=v,P<0||I<=P){P-=v,v=-v;break}}}function b(w,S,I){const v=new a;I.forEach(function(C){v.put(C.mode.bit,4),v.put(C.getLength(),f.getCharCountIndicator(C.mode,w)),C.write(v)});const P=e.getSymbolTotalCodewords(w),j=o.getTotalCodewordsCount(w,S),m=(P-j)*8;for(v.getLengthInBits()+4<=m&&v.put(0,4);v.getLengthInBits()%8!==0;)v.putBit(0);const p=(m-v.getLengthInBits())/8;for(let C=0;C<p;C++)v.put(C%2?17:236,8);return N(v,w,S)}function N(w,S,I){const v=e.getSymbolTotalCodewords(S),P=o.getTotalCodewordsCount(S,I),j=v-P,m=o.getBlocksCount(S,I),p=v%m,C=m-p,R=Math.floor(v/m),J=Math.floor(j/m),Et=J+1,Pe=R-J,jt=new l(Pe);let Z=0;const G=new Array(m),Be=new Array(m);let X=0;const St=new Uint8Array(w.buffer);for(let O=0;O<m;O++){const ee=O<C?J:Et;G[O]=St.slice(Z,Z+ee),Be[O]=jt.encode(G[O]),Z+=ee,X=Math.max(X,ee)}const $=new Uint8Array(v);let Te=0,D,F;for(D=0;D<X;D++)for(F=0;F<m;F++)D<G[F].length&&($[Te++]=G[F][D]);for(D=0;D<Pe;D++)for(F=0;F<m;F++)$[Te++]=Be[F][D];return $}function M(w,S,I,v){let P;if(Array.isArray(w))P=x.fromArray(w);else if(typeof w=="string"){let R=S;if(!R){const J=x.rawSplit(w);R=d.getBestVersionForData(J,I)}P=x.fromString(w,R||40)}else throw new Error("Invalid data");const j=d.getBestVersionForData(P,I);if(!j)throw new Error("The amount of data is too big to be stored in a QR Code");if(!S)S=j;else if(S<j)throw new Error(`
5
- The chosen QR Code version cannot contain this amount of data.
6
- Minimum version required to store current data is: `+j+`.
7
- `);const m=b(S,I,P),p=e.getSymbolSize(S),C=new n(p);return g(C,S),y(C),A(C,S),E(C,I,0),S>=7&&T(C,S),B(C,m),isNaN(v)&&(v=i.getBestMask(C,E.bind(null,C,I))),i.applyMask(v,C),E(C,I,v),{modules:C,version:S,errorCorrectionLevel:I,maskPattern:v,segments:P}}return se.create=function(S,I){if(typeof S>"u"||S==="")throw new Error("No input text");let v=s.M,P,j;return typeof I<"u"&&(v=s.from(I.errorCorrectionLevel,s.M),P=d.from(I.version),j=i.from(I.maskPattern),I.toSJISFunc&&e.setToSJISFunction(I.toSJISFunc)),M(S,P,v,j)},se}var ve={},Ne={},ot;function vt(){return ot||(ot=1,(function(e){function s(a){if(typeof a=="number"&&(a=a.toString()),typeof a!="string")throw new Error("Color should be defined as hex string");let n=a.slice().replace("#","").split("");if(n.length<3||n.length===5||n.length>8)throw new Error("Invalid hex color: "+a);(n.length===3||n.length===4)&&(n=Array.prototype.concat.apply([],n.map(function(r){return[r,r]}))),n.length===6&&n.push("F","F");const t=parseInt(n.join(""),16);return{r:t>>24&255,g:t>>16&255,b:t>>8&255,a:t&255,hex:"#"+n.slice(0,6).join("")}}e.getOptions=function(n){n||(n={}),n.color||(n.color={});const t=typeof n.margin>"u"||n.margin===null||n.margin<0?4:n.margin,r=n.width&&n.width>=21?n.width:void 0,i=n.scale||4;return{width:r,scale:r?4:i,margin:t,color:{dark:s(n.color.dark||"#000000ff"),light:s(n.color.light||"#ffffffff")},type:n.type,rendererOpts:n.rendererOpts||{}}},e.getScale=function(n,t){return t.width&&t.width>=n+t.margin*2?t.width/(n+t.margin*2):t.scale},e.getImageWidth=function(n,t){const r=e.getScale(n,t);return Math.floor((n+t.margin*2)*r)},e.qrToImageData=function(n,t,r){const i=t.modules.size,o=t.modules.data,l=e.getScale(i,r),d=Math.floor((i+r.margin*2)*l),h=r.margin*l,f=[r.color.light,r.color.dark];for(let x=0;x<d;x++)for(let g=0;g<d;g++){let y=(x*d+g)*4,A=r.color.light;if(x>=h&&g>=h&&x<d-h&&g<d-h){const T=Math.floor((x-h)/l),E=Math.floor((g-h)/l);A=f[o[T*i+E]?1:0]}n[y++]=A.r,n[y++]=A.g,n[y++]=A.b,n[y]=A.a}}})(Ne)),Ne}var it;function Pn(){return it||(it=1,(function(e){const s=vt();function a(t,r,i){t.clearRect(0,0,r.width,r.height),r.style||(r.style={}),r.height=i,r.width=i,r.style.height=i+"px",r.style.width=i+"px"}function n(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}e.render=function(r,i,o){let l=o,d=i;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),i||(d=n()),l=s.getOptions(l);const h=s.getImageWidth(r.modules.size,l),f=d.getContext("2d"),x=f.createImageData(h,h);return s.qrToImageData(x.data,r,l),a(f,d,h),f.putImageData(x,0,0),d},e.renderToDataURL=function(r,i,o){let l=o;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),l||(l={});const d=e.render(r,i,l),h=l.type||"image/png",f=l.rendererOpts||{};return d.toDataURL(h,f.quality)}})(ve)),ve}var Ee={},lt;function Bn(){if(lt)return Ee;lt=1;const e=vt();function s(t,r){const i=t.a/255,o=r+'="'+t.hex+'"';return i<1?o+" "+r+'-opacity="'+i.toFixed(2).slice(1)+'"':o}function a(t,r,i){let o=t+r;return typeof i<"u"&&(o+=" "+i),o}function n(t,r,i){let o="",l=0,d=!1,h=0;for(let f=0;f<t.length;f++){const x=Math.floor(f%r),g=Math.floor(f/r);!x&&!d&&(d=!0),t[f]?(h++,f>0&&x>0&&t[f-1]||(o+=d?a("M",x+i,.5+g+i):a("m",l,0),l=0,d=!1),x+1<r&&t[f+1]||(o+=a("h",h),h=0)):l++}return o}return Ee.render=function(r,i,o){const l=e.getOptions(i),d=r.modules.size,h=r.modules.data,f=d+l.margin*2,x=l.color.light.a?"<path "+s(l.color.light,"fill")+' d="M0 0h'+f+"v"+f+'H0z"/>':"",g="<path "+s(l.color.dark,"stroke")+' d="'+n(h,d,l.margin)+'"/>',y='viewBox="0 0 '+f+" "+f+'"',T='<svg xmlns="http://www.w3.org/2000/svg" '+(l.width?'width="'+l.width+'" height="'+l.width+'" ':"")+y+' shape-rendering="crispEdges">'+x+g+`</svg>
8
- `;return typeof o=="function"&&o(null,T),T},Ee}var ct;function Tn(){if(ct)return H;ct=1;const e=dn(),s=In(),a=Pn(),n=Bn();function t(r,i,o,l,d){const h=[].slice.call(arguments,1),f=h.length,x=typeof h[f-1]=="function";if(!x&&!e())throw new Error("Callback required as last argument");if(x){if(f<2)throw new Error("Too few arguments provided");f===2?(d=o,o=i,i=l=void 0):f===3&&(i.getContext&&typeof d>"u"?(d=l,l=void 0):(d=l,l=o,o=i,i=void 0))}else{if(f<1)throw new Error("Too few arguments provided");return f===1?(o=i,i=l=void 0):f===2&&!i.getContext&&(l=o,o=i,i=void 0),new Promise(function(g,y){try{const A=s.create(o,l);g(r(A,i,l))}catch(A){y(A)}})}try{const g=s.create(o,l);d(null,r(g,i,l))}catch(g){d(g)}}return H.create=s.create,H.toCanvas=t.bind(null,a.render),H.toDataURL=t.bind(null,a.renderToDataURL),H.toString=t.bind(null,function(r,i,o){return n.render(r,o)}),H}var Mn=Tn();async function Rn(e,s={}){const a=await ft.post(`/api/config/channels/${e}/auth/start`,s);if(!a.ok)throw new Error(a.error.message);return a.data}async function Ln(e,s){const a=await ft.post(`/api/config/channels/${e}/auth/poll`,s);if(!a.ok)throw new Error(a.error.message);return a.data}function kn(){return ut({mutationFn:({channel:e,data:s})=>Rn(e,s)})}function Dn(){return ut({mutationFn:({channel:e,data:s})=>Ln(e,s)})}function Fn(e){const s=e.accounts,a=new Set;if(typeof e.defaultAccountId=="string"&&e.defaultAccountId.trim()&&a.add(e.defaultAccountId.trim()),s&&typeof s=="object"&&!Array.isArray(s))for(const n of Object.keys(s)){const t=n.trim();t&&a.add(t)}return[...a]}function Un(e,s){if(typeof e.baseUrl=="string"&&e.baseUrl.trim())return e.baseUrl.trim();if(typeof s.baseUrl=="string"&&s.baseUrl.trim())return s.baseUrl.trim()}function qn({channelConfig:e,formData:s,disabled:a=!1}){const n=kt(),t=kn(),r=Dn(),[i,o]=L.useState(null),[l,d]=L.useState(null),[h,f]=L.useState(null),x=L.useMemo(()=>Fn(e),[e]),g=x[0],y=Un(s,e),A=x.length>0;L.useEffect(()=>{A&&(o(null),d(b=>(b==null?void 0:b.status)==="authorized"?b:{channel:"weixin",status:"authorized",message:c("weixinAuthAuthorized"),accountId:g??null}))},[A,g]),L.useEffect(()=>{if(!i){f(null);return}let b=!1;return Mn.toDataURL(i.qrCodeUrl,{errorCorrectionLevel:"M",margin:1,width:480}).then(N=>{b||f(N)}).catch(()=>{b||f(null)}),()=>{b=!0}},[i]),L.useEffect(()=>{if(!i)return;let b=!1,N=null;const M=async()=>{try{const w=await r.mutateAsync({channel:"weixin",data:{sessionId:i.sessionId}});if(b)return;if(d(w),w.status==="authorized"){await n.invalidateQueries({queryKey:["config"]}),await n.invalidateQueries({queryKey:["config-meta"]}),q.success(w.message||c("weixinAuthAuthorized")),o(null);return}if(w.status==="expired"||w.status==="error"){q.error(w.message||c("weixinAuthRetryRequired")),o(null);return}N=setTimeout(M,w.nextPollMs??i.intervalMs)}catch(w){if(b)return;const S=w instanceof Error?w.message:String(w);q.error(`${c("error")}: ${S}`),o(null)}};return N=setTimeout(M,i.intervalMs),()=>{b=!0,N&&clearTimeout(N)}},[i,r,n]);const T=async()=>{try{const b=await t.mutateAsync({channel:"weixin",data:{baseUrl:y,accountId:typeof s.defaultAccountId=="string"&&s.defaultAccountId.trim()?s.defaultAccountId.trim():void 0}});o(b),d({channel:"weixin",status:"pending",message:b.note,nextPollMs:b.intervalMs})}catch(b){const N=b instanceof Error?b.message:String(b);q.error(`${c("error")}: ${N}`)}},E=i?(l==null?void 0:l.status)==="scanned"?c("weixinAuthScanned"):c("weixinAuthWaiting"):A?c("weixinAuthAuthorized"):c("weixinAuthNotConnected"),B=t.isPending?c("weixinAuthStarting"):i?c("weixinAuthWaiting"):A?c("weixinAuthReconnect"):c("weixinAuthConnect");return u.jsx("section",{className:"rounded-2xl border border-primary/20 bg-gradient-to-br from-primary-50/70 via-white to-emerald-50/60 p-5",children:u.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[u.jsxs("div",{className:"space-y-3",children:[u.jsxs("div",{className:"inline-flex items-center gap-2 rounded-full bg-white/90 px-3 py-1 text-xs font-medium text-primary shadow-sm",children:[u.jsx(Me,{className:"h-3.5 w-3.5"}),c("weixinAuthTitle")]}),u.jsxs("div",{children:[u.jsx("h4",{className:"text-base font-semibold text-gray-900",children:c("weixinAuthDescription")}),u.jsx("p",{className:"mt-1 text-sm text-gray-600",children:c("weixinAuthHint")})]}),u.jsxs("div",{className:K("inline-flex w-fit items-center gap-2 rounded-full px-3 py-1 text-xs font-medium",i?"bg-amber-50 text-amber-700":A?"bg-emerald-50 text-emerald-700":"bg-gray-100 text-gray-600"),children:[i?u.jsx(Re,{className:"h-3.5 w-3.5 animate-spin"}):u.jsx(Dt,{className:"h-3.5 w-3.5"}),E]}),u.jsxs("div",{className:"space-y-1 text-sm text-gray-600",children:[u.jsx("p",{children:c("weixinAuthCapabilityHint")}),g?u.jsxs("p",{children:[c("weixinAuthPrimaryAccount"),": ",u.jsx("span",{className:"font-mono text-xs text-gray-900",children:g})]}):null,x.length>1?u.jsxs("p",{children:[c("weixinAuthConnectedAccounts"),": ",u.jsx("span",{className:"font-mono text-xs text-gray-900",children:x.join(", ")})]}):null,y?u.jsxs("p",{children:[c("weixinAuthBaseUrl"),": ",u.jsx("span",{className:"font-mono text-xs text-gray-900",children:y})]}):null]}),u.jsx(je,{type:"button",onClick:T,disabled:a||t.isPending||!!i,className:"rounded-xl",children:B})]}),u.jsx("div",{className:"w-full max-w-sm rounded-2xl border border-dashed border-primary/25 bg-white/85 p-4 shadow-sm",children:i?u.jsxs("div",{className:"space-y-3",children:[u.jsx("div",{className:"overflow-hidden rounded-2xl border border-gray-100 bg-white p-3",children:h?u.jsx("img",{src:h,alt:c("weixinAuthQrAlt"),className:"mx-auto aspect-square w-full max-w-[240px] object-contain"}):u.jsx("div",{className:"flex aspect-square w-full items-center justify-center rounded-xl bg-gray-50 text-gray-500",children:u.jsxs("div",{className:"flex flex-col items-center gap-2 text-center",children:[u.jsx(Re,{className:"h-5 w-5 animate-spin"}),u.jsx("p",{className:"text-xs",children:c("weixinAuthStarting")})]})})}),u.jsxs("div",{className:"space-y-1 text-xs text-gray-500",children:[u.jsx("p",{children:(l==null?void 0:l.message)||i.note||c("weixinAuthScanPrompt")}),u.jsxs("p",{children:[c("weixinAuthExpiresAt"),": ",Gt(i.expiresAt)]})]}),u.jsxs("a",{href:i.qrCodeUrl,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[u.jsx(dt,{className:"h-3.5 w-3.5"}),c("weixinAuthOpenQr")]})]}):u.jsxs("div",{className:"flex min-h-[280px] flex-col items-center justify-center rounded-2xl bg-gray-50/80 px-6 text-center",children:[u.jsx(Me,{className:"h-9 w-9 text-gray-300"}),u.jsx("p",{className:"mt-3 text-sm font-medium text-gray-700",children:c("weixinAuthReadyTitle")}),u.jsx("p",{className:"mt-1 text-xs leading-5 text-gray-500",children:c("weixinAuthReadyDescription")})]})})]})})}function W(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Nt(e,s){const a={...e};for(const[n,t]of Object.entries(s)){const r=a[n];if(W(r)&&W(t)){a[n]=Nt(r,t);continue}a[n]=t}return a}function _n(e,s){const a=e.split("."),n={};let t=n;for(let r=0;r<a.length-1;r+=1){const i=a[r];t[i]={},t=t[i]}return t[a[a.length-1]]=s,n}function zn({channelName:e}){var P,j;const{data:s}=gt(),{data:a}=ht(),{data:n}=mt(),t=Yt(),r=Qt(),[i,o]=L.useState({}),[l,d]=L.useState({}),[h,f]=L.useState(null),x=e?s==null?void 0:s.channels[e]:null,g=e?ke()[e]??[]:[],y=n==null?void 0:n.uiHints,A=e?`channels.${e}`:null,T=((P=n==null?void 0:n.actions)==null?void 0:P.filter(m=>m.scope===A))??[],E=e&&(((j=Se(`channels.${e}`,y))==null?void 0:j.label)??e),B=a==null?void 0:a.channels.find(m=>m.name===e),b=B?bt(B):void 0,N=e==="weixin";L.useEffect(()=>{if(x){o({...x});const m={};(e?ke()[e]??[]:[]).filter(C=>C.type==="json").forEach(C=>{const R=x[C.name];m[C.name]=JSON.stringify(R??{},null,2)}),d(m)}else o({}),d({})},[x,e]);const M=(m,p)=>{o(C=>({...C,[m]:p}))},w=m=>{if(m.preventDefault(),!e)return;const p={...i};for(const C of g){if(C.type!=="password")continue;const R=p[C.name];(typeof R!="string"||R.length===0)&&delete p[C.name]}for(const C of g){if(C.type!=="json")continue;const R=l[C.name]??"";try{p[C.name]=R.trim()?JSON.parse(R):{}}catch{q.error(`${c("invalidJson")}: ${C.name}`);return}}t.mutate({channel:e,data:p})},S=m=>{if(!m||!e)return;const p=m.channels;if(!W(p))return;const C=p[e];W(C)&&o(R=>Nt(R,C))},I=async m=>{if(!(!e||!A)){f(m.id);try{let p={...i};m.saveBeforeRun&&(p={...p,...m.savePatch??{}},o(p),await t.mutateAsync({channel:e,data:p}));const C=await r.mutateAsync({actionId:m.id,data:{scope:A,draftConfig:_n(A,p)}});S(C.patch),C.ok?q.success(C.message||c("success")):q.error(C.message||c("error"))}catch(p){const C=p instanceof Error?p.message:String(p);q.error(`${c("error")}: ${C}`)}finally{f(null)}}};if(!e||!B||!x)return u.jsx("div",{className:Wt,children:u.jsxs("div",{children:[u.jsx("h3",{className:"text-base font-semibold text-gray-900",children:c("channelsSelectTitle")}),u.jsx("p",{className:"mt-2 text-sm text-gray-500",children:c("channelsSelectDescription")})]})});const v=!!x.enabled;return u.jsxs("div",{className:Zt,children:[u.jsx("div",{className:"border-b border-gray-100 px-6 py-5",children:u.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[u.jsxs("div",{className:"min-w-0",children:[u.jsxs("div",{className:"flex items-center gap-3",children:[u.jsx(yt,{name:e,src:wt(e),className:K("h-9 w-9 rounded-lg border",v?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:u.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:e[0]})}),u.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900 capitalize",children:E})]}),u.jsx("p",{className:"mt-2 text-sm text-gray-500",children:c("channelsFormDescription")}),b&&u.jsxs("a",{href:b,className:"mt-2 inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[u.jsx(Ft,{className:"h-3.5 w-3.5"}),c("channelsGuideTitle")]})]}),u.jsx(pt,{status:v?"active":"inactive",label:v?c("statusActive"):c("statusInactive")})]})}),u.jsxs("form",{onSubmit:w,className:"flex min-h-0 flex-1 flex-col",children:[u.jsx("div",{className:"min-h-0 flex-1 space-y-6 overflow-y-auto overscroll-contain px-6 py-5",children:N?u.jsxs(u.Fragment,{children:[u.jsx(qn,{channelConfig:x,formData:i,disabled:t.isPending||!!h}),u.jsxs("details",{className:"group rounded-2xl border border-gray-200/80 bg-white",children:[u.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-3 px-5 py-4 text-sm font-medium text-gray-900",children:[u.jsxs("div",{children:[u.jsx("p",{children:c("weixinAuthAdvancedTitle")}),u.jsx("p",{className:"mt-1 text-xs font-normal text-gray-500",children:c("weixinAuthAdvancedDescription")})]}),u.jsx(Ut,{className:"h-4 w-4 text-gray-400 transition-transform group-open:rotate-180"})]}),u.jsx("div",{className:"space-y-6 border-t border-gray-100 px-5 py-5",children:u.jsx(Le,{channelName:e,fields:g,formData:i,jsonDrafts:l,setJsonDrafts:d,updateField:M,uiHints:y})})]})]}):u.jsx(Le,{channelName:e,fields:g,formData:i,jsonDrafts:l,setJsonDrafts:d,updateField:M,uiHints:y})}),u.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t border-gray-100 px-6 py-4",children:[u.jsx("div",{className:"flex flex-wrap items-center gap-2",children:T.filter(m=>m.trigger==="manual").map(m=>u.jsx(je,{type:"button",onClick:()=>I(m),disabled:t.isPending||!!h,variant:"secondary",children:h===m.id?c("connecting"):m.title},m.id))}),u.jsx(je,{type:"submit",disabled:t.isPending||!!h,children:t.isPending?c("saving"):c("save")})]})]})]})}const On={telegram:"channelDescTelegram",slack:"channelDescSlack",email:"channelDescEmail",webhook:"channelDescWebhook",discord:"channelDescDiscord",feishu:"channelDescFeishu",weixin:"channelDescWeixin"};function $n(){const{data:e}=gt(),{data:s}=ht(),{data:a}=mt(),[n,t]=L.useState("enabled"),[r,i]=L.useState(),[o,l]=L.useState(""),d=a==null?void 0:a.uiHints,h=s==null?void 0:s.channels,f=e==null?void 0:e.channels,x=[{id:"enabled",label:c("channelsTabEnabled"),count:(h??[]).filter(y=>{var A;return(A=f==null?void 0:f[y.name])==null?void 0:A.enabled}).length},{id:"all",label:c("channelsTabAll"),count:(h??[]).length}],g=L.useMemo(()=>{const y=o.trim().toLowerCase();return(h??[]).filter(A=>{var E;const T=((E=f==null?void 0:f[A.name])==null?void 0:E.enabled)||!1;return n==="enabled"?T:!0}).filter(A=>y?(A.displayName||A.name).toLowerCase().includes(y)||A.name.toLowerCase().includes(y):!0)},[n,f,h,o]);return L.useEffect(()=>{if(g.length===0){i(void 0);return}g.some(A=>A.name===r)||i(g[0].name)},[g,r]),!e||!s?u.jsx("div",{className:"p-8 text-gray-400",children:c("channelsLoading")}):u.jsxs(rn,{className:"xl:flex xl:h-full xl:min-h-0 xl:flex-col xl:pb-0",children:[u.jsx(sn,{title:c("channelsPageTitle"),description:c("channelsPageDescription")}),u.jsxs("div",{className:K($t,"xl:min-h-0 xl:flex-1"),children:[u.jsxs("section",{className:Xt,children:[u.jsx("div",{className:"border-b border-gray-100 px-4 pt-4",children:u.jsx(nn,{tabs:x,activeTab:n,onChange:t,className:"mb-0"})}),u.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:u.jsxs("div",{className:"relative",children:[u.jsx(qt,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),u.jsx(Q,{value:o,onChange:y=>l(y.target.value),placeholder:c("channelsFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),u.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3",children:[g.map(y=>{const A=e.channels[y.name],T=(A==null?void 0:A.enabled)||!1,E=Se(`channels.${y.name}`,d),B=bt(y),b=(E==null?void 0:E.help)||c(On[y.name]||"channelDescriptionDefault"),N=r===y.name;return u.jsx("button",{type:"button",onClick:()=>i(y.name),className:K("w-full rounded-xl border p-2.5 text-left transition-all",N?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:u.jsxs("div",{className:"flex items-start justify-between gap-3",children:[u.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[u.jsx(yt,{name:y.name,src:wt(y.name),className:K("h-10 w-10 rounded-lg border",T?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:u.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:y.name[0]})}),u.jsxs("div",{className:"min-w-0",children:[u.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:y.displayName||y.name}),u.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:b})]})]}),u.jsxs("div",{className:"flex items-center gap-2",children:[B&&u.jsx("a",{href:B,onClick:M=>M.stopPropagation(),className:"inline-flex h-7 w-7 items-center justify-center rounded-md text-gray-300 transition-colors hover:bg-gray-100/70 hover:text-gray-500",title:c("channelsGuideTitle"),children:u.jsx(dt,{className:"h-3.5 w-3.5"})}),u.jsx(pt,{status:T?"active":"inactive",label:T?c("statusActive"):c("statusInactive"),className:"min-w-[56px] justify-center"})]})]})},y.name)}),g.length===0&&u.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[u.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:u.jsx(_t,{className:"h-5 w-5 text-gray-300"})}),u.jsx("p",{className:"text-sm font-medium text-gray-700",children:c("channelsNoMatch")})]})]})]}),u.jsx(zn,{channelName:r})]})]})}export{$n as ChannelsList};