@xopcai/xopc 0.0.43 → 0.0.45

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 (173) hide show
  1. package/README.md +138 -102
  2. package/README.zh-CN.md +155 -67
  3. package/dist/extensions/dingtalk/src/plugin.js +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/telegram/src/plugin.js +1 -1
  6. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/extensions/weixin/src/api/api.js +2 -2
  9. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  10. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  11. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  12. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  13. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  14. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  15. package/dist/extensions/weixin/src/plugin.js +1 -1
  16. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  17. package/dist/gateway/static/root/assets/agents-Bk2uuFvC.js +216 -0
  18. package/dist/gateway/static/root/assets/agents-Bk2uuFvC.js.map +1 -0
  19. package/dist/gateway/static/root/assets/{apps-page-Bco3oZzd.js → apps-page-CbSr8cvX.js} +2 -2
  20. package/dist/gateway/static/root/assets/{apps-page-Bco3oZzd.js.map → apps-page-CbSr8cvX.js.map} +1 -1
  21. package/dist/gateway/static/root/assets/channels-settings-Dn-hIRl1.js +2 -0
  22. package/dist/gateway/static/root/assets/{channels-settings-CpTZxCKG.js.map → channels-settings-Dn-hIRl1.js.map} +1 -1
  23. package/dist/gateway/static/root/assets/{cron-api-YLqLzMDN.js → cron-dreaming-jobs-D460WnXB.js} +3 -3
  24. package/dist/gateway/static/root/assets/cron-dreaming-jobs-D460WnXB.js.map +1 -0
  25. package/dist/gateway/static/root/assets/cron-page-Df6AyXfn.js +2 -0
  26. package/dist/gateway/static/root/assets/cron-page-Df6AyXfn.js.map +1 -0
  27. package/dist/gateway/static/root/assets/dist-DN37Fw0E.js +2 -0
  28. package/dist/gateway/static/root/assets/{dist-4ClCuR-G.js.map → dist-DN37Fw0E.js.map} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-debug-page-yNO3rwBQ.js → extension-debug-page-CqdKfBv_.js} +2 -2
  30. package/dist/gateway/static/root/assets/{extension-debug-page-yNO3rwBQ.js.map → extension-debug-page-CqdKfBv_.js.map} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-page-D0vOu9eC.js → extension-page-DhxjnfDf.js} +2 -2
  32. package/dist/gateway/static/root/assets/{extension-page-D0vOu9eC.js.map → extension-page-DhxjnfDf.js.map} +1 -1
  33. package/dist/gateway/static/root/assets/extension-settings-page-B3uhrA_f.js +2 -0
  34. package/dist/gateway/static/root/assets/{extension-settings-page-DqaNWoo7.js.map → extension-settings-page-B3uhrA_f.js.map} +1 -1
  35. package/dist/gateway/static/root/assets/heartbeat-config-api-z1kl5_rE.js +2 -0
  36. package/dist/gateway/static/root/assets/heartbeat-config-api-z1kl5_rE.js.map +1 -0
  37. package/dist/gateway/static/root/assets/{index-K0ZDwzeJ.css → index-B8G4Y9YY.css} +1 -1
  38. package/dist/gateway/static/root/assets/{index-KxjI2fjF.js → index-BUYGk2UT.js} +93 -93
  39. package/dist/gateway/static/root/assets/{index-KxjI2fjF.js.map → index-BUYGk2UT.js.map} +1 -1
  40. package/dist/gateway/static/root/assets/logs-page-Z9KRHWeO.js +2 -0
  41. package/dist/gateway/static/root/assets/{logs-page-DSdKuyeD.js.map → logs-page-Z9KRHWeO.js.map} +1 -1
  42. package/dist/gateway/static/root/assets/sessions-page-TlMYZxuv.js +2 -0
  43. package/dist/gateway/static/root/assets/{sessions-page-Bfb-hZJb.js.map → sessions-page-TlMYZxuv.js.map} +1 -1
  44. package/dist/gateway/static/root/assets/settings-page-X8vVcB8e.js +2 -0
  45. package/dist/gateway/static/root/assets/settings-page-X8vVcB8e.js.map +1 -0
  46. package/dist/gateway/static/root/assets/skills-page-B-tO9-I7.js +3 -0
  47. package/dist/gateway/static/root/assets/skills-page-B-tO9-I7.js.map +1 -0
  48. package/dist/gateway/static/root/assets/{use-image-provider-credentials-Cu5zeVdn.js → use-image-provider-credentials-DsYECmye.js} +2 -2
  49. package/dist/gateway/static/root/assets/{use-image-provider-credentials-Cu5zeVdn.js.map → use-image-provider-credentials-DsYECmye.js.map} +1 -1
  50. package/dist/gateway/static/root/index.html +2 -2
  51. package/dist/package.js +1 -1
  52. package/dist/src/agent/agent-manager.js +6 -6
  53. package/dist/src/agent/context/workspace-seed.js +2 -2
  54. package/dist/src/agent/goals/post-turn.js +1 -1
  55. package/dist/src/agent/image/load-image-media.js +1 -1
  56. package/dist/src/agent/ipc/bus.js +1 -1
  57. package/dist/src/agent/ipc/inbox.js +2 -2
  58. package/dist/src/agent/ipc/socket.js +1 -1
  59. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  60. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  61. package/dist/src/agent/memory/dreaming/events.js +1 -1
  62. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  63. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  64. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  65. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  66. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  67. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  68. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  69. package/dist/src/agent/models/manager.js +1 -1
  70. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  71. package/dist/src/agent/service.js +5 -5
  72. package/dist/src/agent/skills/config.js +1 -1
  73. package/dist/src/agent/skills/hub-hash.js +2 -2
  74. package/dist/src/agent/skills/hub-lock.js +1 -1
  75. package/dist/src/agent/skills/hub-pull.js +1 -1
  76. package/dist/src/agent/skills/index.js +1 -1
  77. package/dist/src/agent/skills/managed-store.js +1 -1
  78. package/dist/src/agent/skills/scanner.js +1 -1
  79. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  80. package/dist/src/agent/skills/skill-manager.js +1 -1
  81. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  82. package/dist/src/agent/tools/factory.js +1 -1
  83. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  84. package/dist/src/agent/tools/send-media.js +1 -1
  85. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  86. package/dist/src/agent/tools/write.js +1 -1
  87. package/dist/src/auth/credentials.js +3 -3
  88. package/dist/src/auth/profiles/store.js +1 -1
  89. package/dist/src/auth/sync-provider-auth.js +1 -1
  90. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  91. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  92. package/dist/src/channels/outbound/persist-store.js +1 -1
  93. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  94. package/dist/src/channels/pairing/pairing-store.js +2 -2
  95. package/dist/src/chat-commands/builtins/config.js +2 -2
  96. package/dist/src/chat-commands/context.js +1 -1
  97. package/dist/src/cli/commands/agent.js +1 -1
  98. package/dist/src/cli/commands/agents.js +1 -1
  99. package/dist/src/cli/commands/config.js +1 -1
  100. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  101. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  102. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  103. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  104. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  105. package/dist/src/cli/commands/extension-dev.js +1 -1
  106. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  107. package/dist/src/cli/commands/extension-pack.js +1 -1
  108. package/dist/src/cli/commands/image.js +1 -1
  109. package/dist/src/cli/commands/init.js +4 -4
  110. package/dist/src/cli/utils/init-workspace.js +2 -2
  111. package/dist/src/config/index.js +2 -2
  112. package/dist/src/config/loader.js +2 -2
  113. package/dist/src/config/models-json.js +2 -2
  114. package/dist/src/config/profile.js +2 -2
  115. package/dist/src/cron/executor.js +2 -2
  116. package/dist/src/cron/persistence.js +1 -1
  117. package/dist/src/cron/run-log-store.js +1 -1
  118. package/dist/src/daemon/launchd.js +2 -2
  119. package/dist/src/daemon/systemd.js +2 -2
  120. package/dist/src/extensions/health.js +1 -1
  121. package/dist/src/extensions/loader.js +1 -1
  122. package/dist/src/extensions/lockfile.js +2 -2
  123. package/dist/src/gateway/agents-admin.js +2 -2
  124. package/dist/src/gateway/hono/lib/extension-store.js +1 -1
  125. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  126. package/dist/src/gateway/hono/oauth.js +1 -1
  127. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  128. package/dist/src/gateway/hono/routes/config.js +1 -1
  129. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  130. package/dist/src/gateway/hono/routes/host-fs.js +1 -1
  131. package/dist/src/gateway/hono/routes/models.js +1 -1
  132. package/dist/src/gateway/hono/routes/workspace.js +3 -3
  133. package/dist/src/gateway/hono/sse.js +2 -2
  134. package/dist/src/gateway/lock.js +2 -2
  135. package/dist/src/gateway/service/run-gateway-agent.js +2 -2
  136. package/dist/src/gateway/service.js +5 -5
  137. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  138. package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
  139. package/dist/src/infra/update-check.js +1 -1
  140. package/dist/src/infra/update-lock.js +3 -3
  141. package/dist/src/infra/update-runner.js +1 -1
  142. package/dist/src/infra/update-startup.js +2 -2
  143. package/dist/src/infra/write-file-atomic.js +2 -2
  144. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  145. package/dist/src/providers/index.js +2 -2
  146. package/dist/src/providers/model-registry.js +1 -1
  147. package/dist/src/session/config-store.js +2 -2
  148. package/dist/src/session/search-index-cache.js +1 -1
  149. package/dist/src/session/search-index.js +1 -1
  150. package/dist/src/session/session-title.js +1 -1
  151. package/dist/src/session/store.js +5 -5
  152. package/dist/src/tui/backends/embedded-backend.js +1 -1
  153. package/dist/src/tui/tui.js +1 -1
  154. package/dist/src/utils/logger/audit.js +1 -1
  155. package/dist/src/utils/logger/log-store.js +1 -1
  156. package/dist/src/utils/logger/rotation.js +1 -1
  157. package/dist/src/voice/tts/audio.js +1 -1
  158. package/dist/src/voice/tts/providers/edge-speech.js +1 -1
  159. package/package.json +2 -2
  160. package/dist/gateway/static/root/assets/agents-BDhkkT2o.js +0 -216
  161. package/dist/gateway/static/root/assets/agents-BDhkkT2o.js.map +0 -1
  162. package/dist/gateway/static/root/assets/channels-settings-CpTZxCKG.js +0 -2
  163. package/dist/gateway/static/root/assets/cron-api-YLqLzMDN.js.map +0 -1
  164. package/dist/gateway/static/root/assets/cron-page-aiDeJtJ-.js +0 -2
  165. package/dist/gateway/static/root/assets/cron-page-aiDeJtJ-.js.map +0 -1
  166. package/dist/gateway/static/root/assets/dist-4ClCuR-G.js +0 -2
  167. package/dist/gateway/static/root/assets/extension-settings-page-DqaNWoo7.js +0 -2
  168. package/dist/gateway/static/root/assets/logs-page-DSdKuyeD.js +0 -2
  169. package/dist/gateway/static/root/assets/sessions-page-Bfb-hZJb.js +0 -2
  170. package/dist/gateway/static/root/assets/settings-page-B7NZPSpO.js +0 -2
  171. package/dist/gateway/static/root/assets/settings-page-B7NZPSpO.js.map +0 -1
  172. package/dist/gateway/static/root/assets/skills-page-D-AJTEVx.js +0 -3
  173. package/dist/gateway/static/root/assets/skills-page-D-AJTEVx.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"channels-settings-CpTZxCKG.js","names":[],"sources":["../../../../../web/src/features/settings/channels/channel-im-hub-card.tsx","../../../../../web/src/features/settings/channels/channels-remove-channel-dialog.tsx","../../../../../web/src/features/settings/channel-bindings-merge.ts","../../../../../web/src/features/settings/channels/utils.ts","../../../../../web/src/features/settings/channels/field-primitives.tsx","../../../../../web/src/features/settings/channels/channel-agent-routing-block.tsx","../../../../../web/src/features/settings/channels/dingtalk-more-settings-section.tsx","../../../../../web/src/features/settings/channels-config-api.ts","../../../../../web/src/features/settings/channels/dingtalk-qr-setup-dialog.tsx","../../../../../web/src/features/settings/channels/feishu-more-settings-section.tsx","../../../../../web/src/features/settings/channels/feishu-qr-setup-dialog.tsx","../../../../../web/src/features/settings/channels/telegram-advanced.tsx","../../../../../web/src/features/settings/channels/telegram-channel-settings-dialog.tsx","../../../../../web/src/features/settings/channels/use-channels-settings-panel.ts","../../../../../web/src/features/settings/channels/weixin-qr-login-dialog.tsx","../../../../../web/src/features/settings/channels/weixin-advanced.tsx","../../../../../web/src/features/settings/channels/weixin-more-settings-section.tsx","../../../../../web/src/features/settings/channels/channels-settings-panel.tsx"],"sourcesContent":["import * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport { MoreHorizontal, Pencil, Trash2 } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_POPOVER_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport type ChannelImHubCardProps = {\n icon: ReactNode;\n title: string;\n subtitle: string;\n configured: boolean;\n enabled: boolean;\n onToggle: (next: boolean) => void | Promise<void>;\n toggleDisabled: boolean;\n onConfigure: () => void;\n onEdit: () => void;\n onRemove: () => void;\n ch: ChannelsSettingsMessages;\n};\n\nexport function ChannelImHubCard({\n icon,\n title,\n subtitle,\n configured,\n enabled,\n onToggle,\n toggleDisabled,\n onConfigure,\n onEdit,\n onRemove,\n ch,\n}: ChannelImHubCardProps) {\n return (\n <div className=\"flex flex-col gap-3 rounded-2xl border border-edge bg-surface-base px-4 py-4 dark:border-edge sm:flex-row sm:items-center sm:gap-4\">\n <div className=\"flex min-w-0 flex-1 items-start gap-4\">\n <div className=\"flex size-12 shrink-0 items-center justify-center rounded-xl bg-surface-hover\" aria-hidden>\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-sm font-semibold text-fg\">{title}</h2>\n {configured ? (\n <span className=\"inline-flex items-center rounded-full bg-success-soft px-2 py-0.5 text-xs font-medium text-success\">\n {ch.hubConnectedBadge}\n </span>\n ) : null}\n </div>\n <p className=\"mt-1 text-xs text-fg-muted\">{subtitle}</p>\n </div>\n </div>\n\n {!configured ? (\n <div className=\"flex shrink-0 justify-end sm:justify-end\">\n <Button type=\"button\" variant=\"primary\" className=\"shrink-0\" onClick={onConfigure}>\n {ch.hubConfigureButton}\n </Button>\n </div>\n ) : (\n <div className=\"flex shrink-0 flex-wrap items-center justify-end gap-2 sm:gap-3\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"size-9 shrink-0 p-0\" aria-label={ch.menuMoreAria}>\n <MoreHorizontal className=\"size-5 text-fg-muted\" strokeWidth={1.75} />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className={cn(\n 'min-w-[11rem] rounded-xl border border-edge bg-surface-panel p-1 shadow-popover dark:border-edge',\n SETTINGS_SHELL_POPOVER_Z,\n )}\n sideOffset={6}\n align=\"end\"\n >\n <DropdownMenu.Item\n className=\"cursor-pointer rounded-lg px-3 py-2 text-sm text-fg outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover\"\n onSelect={() => onEdit()}\n >\n <span className=\"flex items-center gap-2\">\n <Pencil className=\"size-4 shrink-0 text-fg-muted\" strokeWidth={1.75} />\n {ch.menuEditConfig}\n </span>\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"cursor-pointer rounded-lg px-3 py-2 text-sm text-danger outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover\"\n onSelect={() => onRemove()}\n >\n <span className=\"flex items-center gap-2\">\n <Trash2 className=\"size-4 shrink-0\" strokeWidth={1.75} />\n {ch.menuRemoveConfig}\n </span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={enabled}\n aria-label={`${title} — ${ch.enableChannelAria}`}\n disabled={toggleDisabled}\n className={cn(\n 'inline-flex h-6 w-10 shrink-0 items-center rounded-full border border-edge p-0.5 transition-colors',\n enabled ? 'justify-end bg-accent' : 'justify-start bg-surface-hover',\n toggleDisabled && 'cursor-not-allowed opacity-50',\n )}\n onClick={() => void onToggle(!enabled)}\n >\n <span className=\"size-4 rounded-full bg-surface-panel shadow-surface ring-1 ring-edge/40 dark:ring-edge/55\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function ChannelsRemoveChannelDialog({\n open,\n onOpenChange,\n ch,\n removeTarget,\n onCancel,\n saving,\n onConfirmRemove,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n removeTarget: 'weixin' | 'telegram' | 'feishu' | 'dingtalk' | null;\n onCancel: () => void;\n saving: boolean;\n onConfirmRemove: () => void;\n}) {\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 w-[min(100%-2rem,28rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Title className=\"text-base font-semibold text-fg\">{ch.removeChannelTitle}</Dialog.Title>\n <Dialog.Description className=\"mt-2 text-sm text-fg-muted\">\n {removeTarget\n ? ch.removeChannelConfirm.replace(\n '{{name}}',\n removeTarget === 'weixin'\n ? ch.weixinTitle\n : removeTarget === 'telegram'\n ? ch.telegramTitle\n : removeTarget === 'feishu'\n ? ch.feishuTitle\n : ch.dingtalkTitle,\n )\n : '\\u00a0'}\n </Dialog.Description>\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"secondary\" onClick={onCancel}>\n {ch.modalCancel}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"border-danger/40 bg-danger text-white hover:bg-danger/90 dark:border-danger/40\"\n disabled={saving}\n onClick={onConfirmRemove}\n >\n {saving ? ch.saving : ch.removeChannelAction}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","/**\n * Merge UI channel account → agent routes into `config.bindings`.\n * Managed rules use ids `ui:route:account:<channel>:<accountId>`.\n */\n\nimport type { BindingRuleWire, ChannelAgentRoutesState } from './types/channel-bindings';\n\nexport type { BindingRuleWire, ChannelAgentRoutesState } from './types/channel-bindings';\n\nfunction normAcc(s: string | undefined): string {\n return (s ?? '').trim().toLowerCase();\n}\n\nexport function isSimpleAccountOnlyRule(r: BindingRuleWire): boolean {\n const m = r.match;\n if (!m?.channel || !m.accountId) return false;\n if (m.peerId || m.peerKind || m.guildId || m.teamId) return false;\n if (m.memberRoleIds && m.memberRoleIds.length > 0) return false;\n return true;\n}\n\n/** Telegram: `accounts` keys (token lives per account, typically `default`). */\nexport function telegramRoutingAccountIds(tg: { accounts?: Record<string, unknown> }): string[] {\n return Object.keys(tg.accounts ?? {}).sort();\n}\n\nexport function weixinRoutingAccountIds(wx: { accounts?: Record<string, unknown> }): string[] {\n return Object.keys(wx.accounts ?? {}).sort();\n}\n\nexport function feishuRoutingAccountIds(fs: { appId?: string; appSecret?: string; accounts?: Record<string, unknown> }): string[] {\n const keys = Object.keys(fs.accounts ?? {});\n if (keys.length > 0) return [...keys].sort();\n if (typeof fs.appId === 'string' && fs.appId.trim() && typeof fs.appSecret === 'string' && fs.appSecret.trim()) {\n return ['default'];\n }\n return [];\n}\n\nexport function dingtalkRoutingAccountIds(dt: {\n clientId?: string;\n clientSecret?: string;\n accounts?: Record<string, unknown>;\n}): string[] {\n const keys = Object.keys(dt.accounts ?? {});\n if (keys.length > 0) return [...keys].sort();\n if (typeof dt.clientId === 'string' && dt.clientId.trim() && typeof dt.clientSecret === 'string' && dt.clientSecret.trim()) {\n return ['default'];\n }\n return [];\n}\n\nexport function extractChannelAgentRoutes(\n bindings: BindingRuleWire[],\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: string[],\n dingtalkAccountIds: string[],\n defaultAgentId: string,\n): ChannelAgentRoutesState {\n const telegram: Record<string, string> = {};\n const weixin: Record<string, string> = {};\n const feishu: Record<string, string> = {};\n const dingtalk: Record<string, string> = {};\n\n for (const id of telegramAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'telegram' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n telegram[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n for (const id of weixinAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'weixin' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n weixin[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n for (const id of feishuAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'feishu' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n feishu[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n for (const id of dingtalkAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'dingtalk' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n dingtalk[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n return { telegram, weixin, feishu, dingtalk };\n}\n\nexport function mergeChannelAgentBindings(\n previous: BindingRuleWire[],\n routes: ChannelAgentRoutesState,\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: string[],\n dingtalkAccountIds: string[],\n defaultAgentId: string,\n): BindingRuleWire[] {\n const tgAcc = new Set(telegramAccountIds.map(normAcc));\n const wxAcc = new Set(weixinAccountIds.map(normAcc));\n const fsAcc = new Set(feishuAccountIds.map(normAcc));\n const dtAcc = new Set(dingtalkAccountIds.map(normAcc));\n\n const filtered = previous.filter((r) => {\n if (r.id?.startsWith('ui:route:account:')) return false;\n if (!isSimpleAccountOnlyRule(r)) return true;\n const ch = normAcc(r.match.channel);\n const acc = normAcc(r.match.accountId);\n if (!acc || acc === '*') return true;\n if (ch === 'telegram' && tgAcc.has(acc)) return false;\n if (ch === 'weixin' && wxAcc.has(acc)) return false;\n if (ch === 'feishu' && fsAcc.has(acc)) return false;\n if (ch === 'dingtalk' && dtAcc.has(acc)) return false;\n return true;\n });\n\n const added: BindingRuleWire[] = [];\n\n for (const acc of telegramAccountIds) {\n const agentId = (routes.telegram[acc] ?? routes.telegram[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:telegram:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'telegram', accountId: acc },\n });\n }\n\n for (const acc of weixinAccountIds) {\n const agentId = (routes.weixin[acc] ?? routes.weixin[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:weixin:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'weixin', accountId: acc },\n });\n }\n\n for (const acc of feishuAccountIds) {\n const agentId = (routes.feishu[acc] ?? routes.feishu[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:feishu:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'feishu', accountId: acc },\n });\n }\n\n for (const acc of dingtalkAccountIds) {\n const agentId = (routes.dingtalk[acc] ?? routes.dingtalk[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:dingtalk:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'dingtalk', accountId: acc },\n });\n }\n\n return [...filtered, ...added];\n}\n","import type { ChannelsSettingsState } from '@/features/settings/channels-config-api';\nimport { cn } from '@/lib/cn';\nimport { nativeSelectMaxWidthClass, selectControlBaseClass, settingsInputFocusClass } from '@/lib/form-field-width';\n\nexport function channelsInputClassName(): string {\n return cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n 'dark:border-edge',\n );\n}\n\nexport function channelsSelectClassName(): string {\n return cn(selectControlBaseClass, nativeSelectMaxWidthClass);\n}\n\nexport function parseIdList(raw: string): (string | number)[] {\n return raw\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s) => (/^-?\\d+$/.test(s) ? Number(s) : s));\n}\n\nexport function joinAllowFrom(ids: (string | number)[]): string {\n return ids.map(String).join(', ');\n}\n\nexport function telegramDefaultBotToken(tg: ChannelsSettingsState['telegram']): string {\n const t = tg.accounts?.default?.botToken;\n return typeof t === 'string' ? t : '';\n}\n\nexport function isTelegramConfigured(tg: ChannelsSettingsState['telegram']): boolean {\n return Object.values(tg.accounts ?? {}).some(\n (a) => typeof a.botToken === 'string' && a.botToken.trim().length > 0,\n );\n}\n\nexport function isWeixinConfigured(wx: ChannelsSettingsState['weixin']): boolean {\n return Object.keys(wx.accounts ?? {}).length > 0 || wx.allowFrom.length > 0;\n}\n\nexport function isFeishuConfigured(fs: ChannelsSettingsState['feishu']): boolean {\n return Boolean(fs.appId?.trim() && fs.appSecret?.trim()) || Object.keys(fs.accounts ?? {}).length > 0;\n}\n\nexport function isDingtalkConfigured(dt: ChannelsSettingsState['dingtalk']): boolean {\n return Boolean(dt.clientId?.trim() && dt.clientSecret?.trim()) || Object.keys(dt.accounts ?? {}).length > 0;\n}\n","import type { ReactNode } from 'react';\n\nimport { channelsSelectClassName } from './utils';\n\nexport function FieldLabel({ children }: { children: ReactNode }) {\n return <div className=\"text-sm font-medium text-fg\">{children}</div>;\n}\n\nexport function FieldHint({ children }: { children: ReactNode }) {\n return <p className=\"text-xs leading-relaxed text-fg-subtle\">{children}</p>;\n}\n\ntype SelectFieldProps<T extends string> = {\n label: string;\n value: T;\n onChange: (v: T) => void;\n options: { value: T; label: string }[];\n};\n\nexport function SelectField<T extends string>({ label, value, onChange, options }: SelectFieldProps<T>) {\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{label}</FieldLabel>\n <select className={channelsSelectClassName()} value={value} onChange={(e) => onChange(e.target.value as T)}>\n {options.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import { agentListDisplayName } from '@/features/settings/agents/agent-display-names';\nimport { nativeSelectMaxWidthClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport { messages, type ChannelsSettingsMessages } from '@/i18n/messages';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName } from './utils';\n\nexport function ChannelAgentRoutingBlock({\n accountIds,\n routes,\n defaultAgentId,\n agentItems,\n disabled,\n onChange,\n ch,\n}: {\n accountIds: string[];\n routes: Record<string, string>;\n defaultAgentId: string;\n agentItems: { id: string; name?: string }[];\n disabled?: boolean;\n onChange: (accountId: string, agentId: string) => void;\n ch: ChannelsSettingsMessages;\n}) {\n const language = useLocaleStore((s) => s.language);\n const agentsMessages = messages(language).agentsSettings;\n if (accountIds.length === 0) return null;\n const opts = agentItems.length > 0 ? agentItems : [{ id: defaultAgentId }];\n return (\n <div className=\"space-y-3 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div>\n <FieldLabel>{ch.agentRoutingTitle}</FieldLabel>\n <FieldHint>{ch.agentRoutingHint}</FieldHint>\n </div>\n <div className=\"space-y-2\">\n {accountIds.map((acc) => (\n <div\n key={acc}\n className=\"grid grid-cols-1 items-start gap-2 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2.5 sm:grid-cols-2 sm:items-center dark:border-edge\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-fg-muted\">{ch.agentRoutingAccountLabel}</p>\n <p className=\"mt-0.5 truncate font-mono text-sm text-fg\" title={acc}>\n {acc}\n </p>\n </div>\n <div className=\"min-w-0\">\n <label className=\"sr-only\" htmlFor={`agent-route-${acc}`}>\n {ch.agentRoutingAgentLabel}\n </label>\n <select\n id={`agent-route-${acc}`}\n className={cn(channelsInputClassName(), nativeSelectMaxWidthClass)}\n disabled={disabled}\n value={(routes[acc] ?? defaultAgentId).toLowerCase()}\n onChange={(e) => onChange(acc, e.target.value)}\n >\n {opts.map((ag) => (\n <option key={ag.id} value={ag.id}>\n {`${agentListDisplayName(ag, agentsMessages)} (${ag.id})`}\n </option>\n ))}\n </select>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { Check, ChevronDown, Copy, Eye, EyeOff } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { dingtalkRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport type { ChannelsSettingsState, DmPolicy, GroupPolicy } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function DingtalkMoreSettingsSection({\n ch,\n form,\n baseline,\n showDingtalkSecret,\n setShowDingtalkSecret,\n dingtalkCopied,\n copyDingtalkSecret,\n updateDingtalk,\n updateChannelAgentRoute,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n showDingtalkSecret: boolean;\n setShowDingtalkSecret: (v: boolean | ((b: boolean) => boolean)) => void;\n dingtalkCopied: boolean;\n copyDingtalkSecret: () => Promise<void>;\n updateDingtalk: (patch: Partial<ChannelsSettingsState['dingtalk']>) => void;\n updateChannelAgentRoute: (\n channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk',\n accountId: string,\n agentId: string,\n ) => void;\n dingtalkAccountsDraft: string;\n setDingtalkAccountsDraft: (v: string) => void;\n dingtalkAccountsError: string;\n onDingtalkAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const dt = form.dingtalk;\n const dingtalkBaselineSecret = baseline?.dingtalk?.clientSecret ?? '';\n const dingtalkSecretDisplayLocked =\n !showDingtalkSecret &&\n Boolean(String(dingtalkBaselineSecret).trim()) &&\n dt.clientSecret === dingtalkBaselineSecret;\n\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.dingtalkAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={dt.enabled}\n onChange={(e) => updateDingtalk({ enabled: e.target.checked })}\n />\n <span>{ch.enableDingtalkAria}</span>\n </label>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.dingtalkClientId}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={dt.clientId}\n onChange={(e) => updateDingtalk({ clientId: e.target.value })}\n placeholder=\"dingxxx\"\n />\n <FieldHint>{ch.dingtalkClientIdDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.dingtalkClientSecret}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showDingtalkSecret ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={dingtalkSecretDisplayLocked}\n value={\n dingtalkSecretDisplayLocked\n ? '*'.repeat(Math.max(1, dt.clientSecret.length))\n : dt.clientSecret\n }\n onChange={(e) => {\n if (dingtalkSecretDisplayLocked) return;\n updateDingtalk({ clientSecret: e.target.value });\n }}\n placeholder=\"••••••••\"\n />\n {dt.clientSecret ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyDingtalkSecret()}\n >\n {dingtalkCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {dingtalkCopied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowDingtalkSecret((s) => !s)}\n >\n {showDingtalkSecret ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showDingtalkSecret ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.dingtalkClientSecretDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dingtalkEndpoint}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={dt.endpoint}\n onChange={(e) => updateDingtalk({ endpoint: e.target.value })}\n placeholder=\"https://api.dingtalk.com\"\n />\n <FieldHint>{ch.dingtalkEndpointDesc}</FieldHint>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={dt.debug}\n onChange={(e) => updateDingtalk({ debug: e.target.checked })}\n />\n {ch.dingtalkDebug}\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dmPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={dt.dmPolicy}\n onChange={(e) =>\n updateDingtalk({ dmPolicy: e.target.value as ChannelsSettingsState['dingtalk']['dmPolicy'] })\n }\n >\n {dmOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.groupPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={dt.groupPolicy}\n onChange={(e) =>\n updateDingtalk({\n groupPolicy: e.target.value as ChannelsSettingsState['dingtalk']['groupPolicy'],\n })\n }\n >\n {groupOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={dt.requireMention}\n onChange={(e) => updateDingtalk({ requireMention: e.target.checked })}\n />\n {ch.requireMention}\n </label>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"userId1, userId2\"\n value={joinAllowFrom(dt.allowFrom)}\n onChange={(e) => updateDingtalk({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"openConversationId1\"\n value={joinAllowFrom(dt.groupAllowFrom)}\n onChange={(e) => updateDingtalk({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromGroupsDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(dt.historyLimit)}\n onChange={(e) => updateDingtalk({ historyLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(dt.textChunkLimit)}\n onChange={(e) => updateDingtalk({ textChunkLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={dingtalkRoutingAccountIds(dt)}\n routes={form.channelAgentRoutes.dingtalk}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('dingtalk', acc, aid)}\n ch={ch}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={dingtalkAccountsDraft}\n onChange={(e) => setDingtalkAccountsDraft(e.target.value)}\n onBlur={onDingtalkAccountsBlur}\n placeholder='{ \"default\": { \"clientId\": \"...\", \"clientSecret\": \"...\", \"enabled\": true } }'\n />\n {dingtalkAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{dingtalkAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport {\n extractChannelAgentRoutes,\n mergeChannelAgentBindings,\n dingtalkRoutingAccountIds,\n feishuRoutingAccountIds,\n telegramRoutingAccountIds,\n weixinRoutingAccountIds,\n type BindingRuleWire,\n} from './channel-bindings-merge';\nimport type {\n ChannelsSettingsState,\n DmPolicy,\n GroupPolicy,\n ReplyToMode,\n StreamMode,\n TelegramAccount,\n WeixinAccount,\n} from './channels-settings.types';\n\nexport type {\n ChannelsSettingsState,\n TelegramConfig,\n WeixinConfig,\n} from './channels-settings.types';\n\nexport type { DmPolicy, GroupPolicy, ReplyToMode, StreamMode };\n\nexport function emptyTelegramAccount(accountId: string): TelegramAccount {\n return {\n accountId,\n name: '',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n replyToMode: 'off',\n apiRoot: '',\n proxy: '',\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial',\n };\n}\n\nexport function defaultChannelsState(): ChannelsSettingsState {\n return {\n bindingsFull: [],\n channelAgentRoutes: { telegram: {}, weixin: {}, feishu: {}, dingtalk: {} },\n defaultAgentId: 'main',\n telegram: {\n enabled: false,\n apiRoot: '',\n debug: false,\n allowFrom: [],\n groupAllowFrom: [],\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n replyToMode: 'off',\n streamMode: 'partial',\n historyLimit: 50,\n textChunkLimit: 4000,\n proxy: '',\n accounts: { default: emptyTelegramAccount('default') },\n },\n weixin: {\n enabled: false,\n dmPolicy: 'pairing',\n allowFrom: [],\n debug: false,\n streamMode: 'partial',\n historyLimit: 50,\n textChunkLimit: 4000,\n routeTag: '',\n accounts: {},\n },\n feishu: {\n enabled: false,\n defaultAccount: '',\n appId: '',\n appSecret: '',\n domain: 'feishu',\n connectionMode: 'websocket',\n verificationToken: '',\n encryptKey: '',\n webhookHost: '127.0.0.1',\n webhookPort: 3000,\n webhookPath: '/feishu/events',\n dmPolicy: 'pairing',\n groupPolicy: 'allowlist',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: true,\n historyLimit: 50,\n textChunkLimit: 4000,\n renderMode: 'auto',\n streaming: false,\n reactionNotifications: 'own',\n tools: { doc: true, wiki: true, drive: true, scopes: true, bitable: true, perm: false },\n actions: { reactions: true },\n accounts: {},\n },\n dingtalk: {\n enabled: false,\n defaultAccount: '',\n clientId: '',\n clientSecret: '',\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: false,\n debug: false,\n endpoint: 'https://api.dingtalk.com',\n historyLimit: 50,\n textChunkLimit: 4000,\n accounts: {},\n },\n };\n}\n\nexport function normalizeChannelsFromConfig(config: unknown): ChannelsSettingsState {\n const cfg = config && typeof config === 'object' ? (config as { channels?: unknown }).channels : undefined;\n const ch = cfg && typeof cfg === 'object' ? (cfg as Record<string, unknown>) : {};\n const tg = ch.telegram as Record<string, unknown> | undefined;\n const wx = ch.weixin as Record<string, unknown> | undefined;\n const fs = ch.feishu as Record<string, unknown> | undefined;\n const dt = ch.dingtalk as Record<string, unknown> | undefined;\n\n const telegramAccounts = tg?.accounts;\n let accounts: Record<string, TelegramAccount> =\n telegramAccounts && typeof telegramAccounts === 'object' && !Array.isArray(telegramAccounts)\n ? { ...(telegramAccounts as Record<string, TelegramAccount>) }\n : {};\n\n const legacyTopToken = typeof tg?.botToken === 'string' ? tg.botToken.trim() : '';\n const defaultTok = accounts.default?.botToken?.trim() ?? '';\n if (legacyTopToken && !defaultTok) {\n accounts = {\n ...accounts,\n default: {\n ...(accounts.default ?? emptyTelegramAccount('default')),\n accountId: 'default',\n botToken: legacyTopToken,\n },\n };\n }\n if (!accounts.default) {\n accounts = { ...accounts, default: emptyTelegramAccount('default') };\n }\n\n const weixinAccounts = wx?.accounts;\n const wxAcc: Record<string, WeixinAccount> =\n weixinAccounts && typeof weixinAccounts === 'object' && !Array.isArray(weixinAccounts)\n ? (weixinAccounts as Record<string, WeixinAccount>)\n : {};\n\n const bindingsRaw = (() => {\n const cfgObj = config && typeof config === 'object' ? (config as Record<string, unknown>) : {};\n const b = cfgObj.bindings;\n return Array.isArray(b) ? (b as BindingRuleWire[]) : [];\n })();\n\n const agents = (() => {\n const cfgObj = config && typeof config === 'object' ? (config as Record<string, unknown>) : {};\n const a = cfgObj.agents;\n return a && typeof a === 'object' ? (a as Record<string, unknown>) : {};\n })();\n const defaultAgentId =\n typeof agents.defaultId === 'string' && agents.defaultId.trim()\n ? agents.defaultId.trim().toLowerCase()\n : 'main';\n\n const base = {\n telegram: {\n enabled: Boolean(tg?.enabled),\n apiRoot: typeof tg?.apiRoot === 'string' ? tg.apiRoot : '',\n debug: Boolean(tg?.debug),\n allowFrom: Array.isArray(tg?.allowFrom) ? [...(tg.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(tg?.groupAllowFrom) ? [...(tg.groupAllowFrom as (string | number)[])] : [],\n dmPolicy: (tg?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (tg?.groupPolicy as GroupPolicy) || 'open',\n replyToMode: (tg?.replyToMode as ReplyToMode) || 'off',\n streamMode: (tg?.streamMode as StreamMode) ?? 'partial',\n historyLimit: typeof tg?.historyLimit === 'number' ? tg.historyLimit : 50,\n textChunkLimit: typeof tg?.textChunkLimit === 'number' ? tg.textChunkLimit : 4000,\n proxy: typeof tg?.proxy === 'string' ? tg.proxy : '',\n accounts: { ...accounts },\n },\n weixin: {\n enabled: Boolean(wx?.enabled),\n dmPolicy: (wx?.dmPolicy as DmPolicy) || 'pairing',\n allowFrom: Array.isArray(wx?.allowFrom) ? [...(wx.allowFrom as string[])] : [],\n debug: Boolean(wx?.debug),\n streamMode: (wx?.streamMode as StreamMode) ?? 'partial',\n historyLimit: typeof wx?.historyLimit === 'number' ? wx.historyLimit : 50,\n textChunkLimit: typeof wx?.textChunkLimit === 'number' ? wx.textChunkLimit : 4000,\n routeTag: wx?.routeTag != null ? String(wx.routeTag) : '',\n accounts: { ...wxAcc },\n },\n feishu: {\n enabled: Boolean(fs?.enabled),\n defaultAccount: typeof fs?.defaultAccount === 'string' ? fs.defaultAccount : '',\n appId: typeof fs?.appId === 'string' ? fs.appId : '',\n appSecret: typeof fs?.appSecret === 'string' ? fs.appSecret : '',\n domain: (typeof fs?.domain === 'string' && fs.domain) || 'feishu',\n connectionMode: (fs?.connectionMode as any) || 'websocket',\n verificationToken: typeof fs?.verificationToken === 'string' ? fs.verificationToken : '',\n encryptKey: typeof fs?.encryptKey === 'string' ? fs.encryptKey : '',\n webhookHost: typeof fs?.webhookHost === 'string' ? fs.webhookHost : '127.0.0.1',\n webhookPort: typeof fs?.webhookPort === 'number' ? fs.webhookPort : 3000,\n webhookPath: typeof fs?.webhookPath === 'string' ? fs.webhookPath : '/feishu/events',\n dmPolicy: (fs?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (fs?.groupPolicy as GroupPolicy) || 'allowlist',\n allowFrom: Array.isArray(fs?.allowFrom) ? [...(fs.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(fs?.groupAllowFrom) ? [...(fs.groupAllowFrom as (string | number)[])] : [],\n requireMention: fs?.requireMention === undefined ? true : Boolean(fs.requireMention),\n historyLimit: typeof fs?.historyLimit === 'number' ? fs.historyLimit : 50,\n textChunkLimit: typeof fs?.textChunkLimit === 'number' ? fs.textChunkLimit : 4000,\n renderMode: (fs?.renderMode as any) || 'auto',\n streaming: fs?.streaming === undefined ? false : Boolean(fs.streaming),\n reactionNotifications: (fs?.reactionNotifications as any) || 'own',\n tools:\n fs?.tools && typeof fs.tools === 'object' && !Array.isArray(fs.tools)\n ? ({ ...(fs.tools as Record<string, boolean>) } as any)\n : undefined,\n actions:\n fs?.actions && typeof fs.actions === 'object' && !Array.isArray(fs.actions)\n ? ({ ...(fs.actions as Record<string, boolean>) } as any)\n : undefined,\n accounts:\n fs?.accounts && typeof fs.accounts === 'object' && !Array.isArray(fs.accounts)\n ? ({ ...(fs.accounts as Record<string, any>) } as any)\n : {},\n },\n dingtalk: {\n enabled: Boolean(dt?.enabled),\n defaultAccount: typeof dt?.defaultAccount === 'string' ? dt.defaultAccount : '',\n clientId: typeof dt?.clientId === 'string' ? dt.clientId : '',\n clientSecret: typeof dt?.clientSecret === 'string' ? dt.clientSecret : '',\n dmPolicy: (dt?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (dt?.groupPolicy as GroupPolicy) || 'open',\n allowFrom: Array.isArray(dt?.allowFrom) ? [...(dt.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(dt?.groupAllowFrom) ? [...(dt.groupAllowFrom as (string | number)[])] : [],\n requireMention: dt?.requireMention === true,\n debug: Boolean(dt?.debug),\n endpoint: typeof dt?.endpoint === 'string' && dt.endpoint.trim() ? dt.endpoint.trim() : 'https://api.dingtalk.com',\n historyLimit: typeof dt?.historyLimit === 'number' ? dt.historyLimit : 50,\n textChunkLimit: typeof dt?.textChunkLimit === 'number' ? dt.textChunkLimit : 4000,\n accounts:\n dt?.accounts && typeof dt.accounts === 'object' && !Array.isArray(dt.accounts)\n ? ({ ...(dt.accounts as Record<string, unknown>) } as ChannelsSettingsState['dingtalk']['accounts'])\n : {},\n },\n };\n\n const tgIds = telegramRoutingAccountIds(base.telegram);\n const wxIds = weixinRoutingAccountIds(base.weixin);\n const fsIds = feishuRoutingAccountIds(base.feishu);\n const dtIds = dingtalkRoutingAccountIds(base.dingtalk);\n const channelAgentRoutes = extractChannelAgentRoutes(bindingsRaw, tgIds, wxIds, fsIds, dtIds, defaultAgentId);\n\n return {\n ...base,\n bindingsFull: bindingsRaw.map((r) => ({ ...r })),\n channelAgentRoutes,\n defaultAgentId,\n };\n}\n\nexport async function fetchChannelsSettings(): Promise<ChannelsSettingsState> {\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'));\n const c = res.payload?.config;\n return normalizeChannelsFromConfig(c ?? {});\n}\n\nexport type WeixinGatewayQrLoginStatusPayload =\n | { phase: 'polling'; qrcodeUrl: string; qrStatus?: string }\n | { phase: 'done'; ok: true; accountId: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchWeixinGatewayQrLoginStart(body?: {\n account?: string;\n timeoutMs?: number;\n}): Promise<{ sessionKey: string; qrcodeUrl: string }> {\n const res = await fetchJson<{ ok: boolean; payload: { sessionKey: string; qrcodeUrl: string } }>(\n apiUrl('/api/channels/weixin/login/start'),\n { method: 'POST', body: JSON.stringify(body ?? {}) },\n );\n return res.payload;\n}\n\nexport async function fetchWeixinGatewayQrLoginStatus(\n sessionKey: string,\n): Promise<WeixinGatewayQrLoginStatusPayload> {\n const res = await fetchJson<{ ok: boolean; payload: { status: WeixinGatewayQrLoginStatusPayload } }>(\n apiUrl(`/api/channels/weixin/login/${encodeURIComponent(sessionKey)}`),\n );\n return res.payload.status;\n}\n\nexport async function patchChannelsSettings(state: ChannelsSettingsState): Promise<ChannelsSettingsState> {\n const tg = state.telegram;\n const wx = state.weixin;\n const fs = state.feishu;\n const dt = state.dingtalk;\n const mergedBindings = mergeChannelAgentBindings(\n state.bindingsFull,\n state.channelAgentRoutes,\n telegramRoutingAccountIds(tg),\n weixinRoutingAccountIds(wx),\n feishuRoutingAccountIds(fs),\n dingtalkRoutingAccountIds(dt),\n state.defaultAgentId,\n );\n const weixinRouteTag: string | number | null = (() => {\n const raw = wx.routeTag.trim();\n if (!raw) return null;\n return /^\\d+$/.test(raw) ? Number(raw) : raw;\n })();\n\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({\n bindings: mergedBindings,\n channels: {\n telegram: {\n enabled: tg.enabled,\n apiRoot: tg.apiRoot || undefined,\n debug: tg.debug,\n allowFrom: tg.allowFrom,\n groupAllowFrom: tg.groupAllowFrom.length ? tg.groupAllowFrom : undefined,\n dmPolicy: tg.dmPolicy,\n groupPolicy: tg.groupPolicy,\n replyToMode: tg.replyToMode,\n streamMode: tg.streamMode,\n historyLimit: tg.historyLimit,\n textChunkLimit: tg.textChunkLimit,\n proxy: tg.proxy || undefined,\n // Always send `accounts` (including `{}`) so PATCH clears stale entries instead of omitting the field.\n accounts: tg.accounts,\n },\n weixin: {\n enabled: wx.enabled,\n dmPolicy: wx.dmPolicy,\n allowFrom: wx.allowFrom,\n debug: wx.debug,\n streamMode: wx.streamMode,\n historyLimit: wx.historyLimit,\n textChunkLimit: wx.textChunkLimit,\n routeTag: weixinRouteTag,\n accounts: wx.accounts,\n },\n feishu: {\n enabled: fs.enabled,\n defaultAccount: fs.defaultAccount || undefined,\n appId: fs.appId,\n appSecret: fs.appSecret || undefined,\n domain: fs.domain || undefined,\n connectionMode: fs.connectionMode,\n verificationToken: (fs as any).verificationToken?.trim() ? (fs as any).verificationToken : undefined,\n encryptKey: (fs as any).encryptKey?.trim() ? (fs as any).encryptKey : undefined,\n webhookHost: (fs as any).webhookHost?.trim() ? (fs as any).webhookHost : undefined,\n webhookPort: typeof (fs as any).webhookPort === 'number' ? (fs as any).webhookPort : undefined,\n webhookPath: (fs as any).webhookPath?.trim() ? (fs as any).webhookPath : undefined,\n dmPolicy: fs.dmPolicy,\n groupPolicy: fs.groupPolicy,\n allowFrom: fs.allowFrom,\n groupAllowFrom: fs.groupAllowFrom.length ? fs.groupAllowFrom : undefined,\n requireMention: fs.requireMention,\n historyLimit: fs.historyLimit,\n textChunkLimit: fs.textChunkLimit,\n renderMode: fs.renderMode,\n streaming: fs.streaming,\n reactionNotifications: fs.reactionNotifications,\n tools: (fs as any).tools,\n actions: (fs as any).actions,\n accounts: fs.accounts,\n },\n dingtalk: {\n enabled: dt.enabled,\n defaultAccount: dt.defaultAccount || undefined,\n clientId: dt.clientId,\n clientSecret: dt.clientSecret || undefined,\n dmPolicy: dt.dmPolicy,\n groupPolicy: dt.groupPolicy,\n allowFrom: dt.allowFrom,\n groupAllowFrom: dt.groupAllowFrom.length ? dt.groupAllowFrom : undefined,\n requireMention: dt.requireMention,\n debug: dt.debug,\n endpoint: dt.endpoint?.trim() ? dt.endpoint : undefined,\n historyLimit: dt.historyLimit,\n textChunkLimit: dt.textChunkLimit,\n accounts: dt.accounts,\n },\n },\n }),\n });\n const c = res.payload?.config;\n void revalidateGatewayConfig();\n if (c) return normalizeChannelsFromConfig(c);\n return {\n ...state,\n bindingsFull: mergedBindings,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Feishu QR scan-to-create\n// ---------------------------------------------------------------------------\n\nexport type FeishuSetupStatusPayload =\n | { phase: 'polling' }\n | { phase: 'done'; ok: true; appId: string; domain: string; openId?: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchFeishuSetupStart(body?: {\n domain?: 'feishu' | 'lark';\n}): Promise<{ sessionKey: string; qrUrl: string }> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { sessionKey: string; qrUrl: string };\n }>(apiUrl('/api/channels/feishu/setup/start'), {\n method: 'POST',\n body: JSON.stringify(body ?? {}),\n });\n return res.payload;\n}\n\nexport async function fetchFeishuSetupStatus(sessionKey: string): Promise<FeishuSetupStatusPayload> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { status: FeishuSetupStatusPayload };\n }>(apiUrl(`/api/channels/feishu/setup/${encodeURIComponent(sessionKey)}`));\n return res.payload.status;\n}\n\n// ---------------------------------------------------------------------------\n// DingTalk QR app registration\n// ---------------------------------------------------------------------------\n\nexport type DingtalkSetupStatusPayload =\n | { phase: 'polling' }\n | { phase: 'done'; ok: true; clientId: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchDingtalkSetupStart(): Promise<{ sessionKey: string; qrUrl: string }> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { sessionKey: string; qrUrl: string };\n }>(apiUrl('/api/channels/dingtalk/setup/start'), {\n method: 'POST',\n body: JSON.stringify({}),\n });\n return res.payload;\n}\n\nexport async function fetchDingtalkSetupStatus(sessionKey: string): Promise<DingtalkSetupStatusPayload> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { status: DingtalkSetupStatusPayload };\n }>(apiUrl(`/api/channels/dingtalk/setup/${encodeURIComponent(sessionKey)}`));\n return res.payload.status;\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchDingtalkSetupStart,\n fetchDingtalkSetupStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function DingtalkQrSetupDialog({\n open,\n onOpenChange,\n ch,\n onSetupSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onSetupSuccess: (result: { clientId: string }) => void;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const startScan = useCallback(async () => {\n setError(null);\n setSessionKey(null);\n setQrUrl(null);\n setBusy(true);\n try {\n const result = await fetchDingtalkSetupStart();\n setQrUrl(result.qrUrl);\n setSessionKey(result.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setBusy(false);\n return;\n }\n void startScan();\n }, [open, startScan]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const status = await fetchDingtalkSetupStatus(sessionKey);\n if (cancelled) return;\n\n if (status.phase === 'polling') return;\n\n if (status.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (status.ok) {\n setQrUrl(null);\n onOpenChange(false);\n onSetupSuccess({ clientId: status.clientId });\n } else {\n setError(status.message);\n setQrUrl(null);\n }\n return;\n }\n\n if (status.phase === 'unknown') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(status.message);\n setSessionKey(null);\n setQrUrl(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 3000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, onOpenChange, onSetupSuccess]);\n\n useEffect(() => {\n if (!qrUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrUrl]);\n\n const showQr = Boolean(qrUrl && sessionKey);\n /** True while waiting for a new session (first open, regenerate, or after errors). Keeps modal height stable. */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.dingtalkQrCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.dingtalkQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.dingtalkQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.dingtalkQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.dingtalkQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p className=\"text-sm text-fg-muted\">\n {qrFrameLoading ? ch.dingtalkQrStarting : ch.dingtalkQrScanHint}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.dingtalkQrEncoding}</p>\n ) : null}\n {showQr && qrUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.dingtalkQrImageError}</p>\n <a\n href={qrUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.dingtalkQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void startScan()}\n >\n {busy ? ch.dingtalkQrStarting : ch.dingtalkQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import { Check, ChevronDown, Copy, Eye, EyeOff } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { feishuRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport type { ChannelsSettingsState, DmPolicy, GroupPolicy } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function FeishuMoreSettingsSection({\n ch,\n form,\n baseline,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n feishuCopied,\n feishuWebhookCopied,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n updateFeishu,\n updateChannelAgentRoute,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n onFeishuAccountsBlur,\n dmOpts,\n groupOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n showFeishuSecret: boolean;\n setShowFeishuSecret: (v: boolean | ((b: boolean) => boolean)) => void;\n showFeishuWebhookSecrets: boolean;\n setShowFeishuWebhookSecrets: (v: boolean | ((b: boolean) => boolean)) => void;\n feishuCopied: boolean;\n feishuWebhookCopied: boolean;\n copyFeishuSecret: () => Promise<void>;\n copyFeishuWebhookConfig: () => Promise<void>;\n updateFeishu: (patch: Partial<ChannelsSettingsState['feishu']>) => void;\n updateChannelAgentRoute: (\n channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk',\n accountId: string,\n agentId: string,\n ) => void;\n feishuAccountsDraft: string;\n setFeishuAccountsDraft: (v: string) => void;\n feishuAccountsError: string;\n onFeishuAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const fs = form.feishu;\n const feishuBaselineSecret = baseline?.feishu?.appSecret ?? '';\n const feishuSecretDisplayLocked =\n !showFeishuSecret &&\n Boolean(String(feishuBaselineSecret).trim()) &&\n fs.appSecret === feishuBaselineSecret;\n\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.feishuAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={fs.enabled}\n onChange={(e) => updateFeishu({ enabled: e.target.checked })}\n />\n <span>{ch.enableFeishuAria}</span>\n </label>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.feishuAppId}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.appId}\n onChange={(e) => updateFeishu({ appId: e.target.value })}\n placeholder=\"cli_xxx\"\n />\n <FieldHint>{ch.feishuAppIdDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.feishuAppSecret}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuSecret ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={feishuSecretDisplayLocked}\n value={\n feishuSecretDisplayLocked\n ? '*'.repeat(Math.max(1, fs.appSecret.length))\n : fs.appSecret\n }\n onChange={(e) => {\n if (feishuSecretDisplayLocked) return;\n updateFeishu({ appSecret: e.target.value });\n }}\n placeholder=\"••••••••\"\n />\n {fs.appSecret ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyFeishuSecret()}\n >\n {feishuCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {feishuCopied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowFeishuSecret((s) => !s)}\n >\n {showFeishuSecret ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showFeishuSecret ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.feishuAppSecretDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.feishuDomain}</FieldLabel>\n <select\n className={inputClassName()}\n value={String(fs.domain || 'feishu')}\n onChange={(e) => updateFeishu({ domain: e.target.value })}\n >\n <option value=\"feishu\">feishu</option>\n <option value=\"lark\">lark</option>\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.connectionMode}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.connectionMode}\n onChange={(e) =>\n updateFeishu({ connectionMode: e.target.value as ChannelsSettingsState['feishu']['connectionMode'] })\n }\n >\n <option value=\"websocket\">websocket</option>\n <option value=\"webhook\">webhook</option>\n </select>\n <FieldHint>{ch.connectionModeDesc}</FieldHint>\n </div>\n </div>\n\n {fs.connectionMode === 'webhook' ? (\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"text-sm font-medium text-fg\">{ch.webhookTitle}</div>\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowFeishuWebhookSecrets((s) => !s)}\n >\n {showFeishuWebhookSecrets ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showFeishuWebhookSecrets ? ch.hide : ch.show}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyFeishuWebhookConfig()}\n >\n {feishuWebhookCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {feishuWebhookCopied ? ch.copied : ch.copy}\n </Button>\n </div>\n </div>\n\n <div className=\"mt-3 grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.verificationToken}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuWebhookSecrets ? 'text' : 'password'}\n autoComplete=\"off\"\n value={fs.verificationToken ?? ''}\n onChange={(e) => updateFeishu({ verificationToken: e.target.value })}\n />\n <FieldHint>{ch.verificationTokenDesc}</FieldHint>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.encryptKey}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuWebhookSecrets ? 'text' : 'password'}\n autoComplete=\"off\"\n value={fs.encryptKey ?? ''}\n onChange={(e) => updateFeishu({ encryptKey: e.target.value })}\n />\n <FieldHint>{ch.encryptKeyDesc}</FieldHint>\n </div>\n </div>\n\n <div className=\"mt-3 grid gap-3 sm:grid-cols-3\">\n <div className=\"flex flex-col gap-1.5 sm:col-span-2\">\n <FieldLabel>{ch.webhookHost}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.webhookHost ?? ''}\n onChange={(e) => updateFeishu({ webhookHost: e.target.value })}\n placeholder=\"127.0.0.1\"\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.webhookPort}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.webhookPort ?? '')}\n onChange={(e) =>\n updateFeishu({ webhookPort: Number(e.target.value || '0') || 0 })\n }\n placeholder=\"3000\"\n />\n </div>\n </div>\n\n <div className=\"mt-3 flex flex-col gap-1.5\">\n <FieldLabel>{ch.webhookPath}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.webhookPath ?? ''}\n onChange={(e) => updateFeishu({ webhookPath: e.target.value })}\n placeholder=\"/feishu/events\"\n />\n <FieldHint>{ch.webhookPathDesc}</FieldHint>\n </div>\n </div>\n ) : null}\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.renderMode}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.renderMode}\n onChange={(e) =>\n updateFeishu({ renderMode: e.target.value as ChannelsSettingsState['feishu']['renderMode'] })\n }\n >\n <option value=\"auto\">auto</option>\n <option value=\"raw\">raw</option>\n <option value=\"card\">card</option>\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.reactionNotifications}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.reactionNotifications}\n onChange={(e) =>\n updateFeishu({\n reactionNotifications: e.target\n .value as ChannelsSettingsState['feishu']['reactionNotifications'],\n })\n }\n >\n <option value=\"off\">off</option>\n <option value=\"own\">own</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={fs.streaming}\n onChange={(e) => updateFeishu({ streaming: e.target.checked })}\n />\n {ch.enableStreaming}\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dmPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.dmPolicy}\n onChange={(e) =>\n updateFeishu({ dmPolicy: e.target.value as ChannelsSettingsState['feishu']['dmPolicy'] })\n }\n >\n {dmOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.groupPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.groupPolicy}\n onChange={(e) =>\n updateFeishu({ groupPolicy: e.target.value as ChannelsSettingsState['feishu']['groupPolicy'] })\n }\n >\n {groupOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={fs.requireMention}\n onChange={(e) => updateFeishu({ requireMention: e.target.checked })}\n />\n {ch.requireMention}\n </label>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"ou_xxx, on_xxx\"\n value={joinAllowFrom(fs.allowFrom)}\n onChange={(e) => updateFeishu({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"oc_xxx, oc_yyy\"\n value={joinAllowFrom(fs.groupAllowFrom)}\n onChange={(e) => updateFeishu({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromGroupsDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.historyLimit)}\n onChange={(e) => updateFeishu({ historyLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.textChunkLimit)}\n onChange={(e) => updateFeishu({ textChunkLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n </div>\n\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"text-sm font-medium text-fg\">{ch.feishuToolsTitle}</div>\n <div className=\"mt-2 grid gap-2 sm:grid-cols-2\">\n {(\n [\n ['doc', ch.feishuToolDoc],\n ['wiki', ch.feishuToolWiki],\n ['drive', ch.feishuToolDrive],\n ['perm', ch.feishuToolPerm],\n ['bitable', ch.feishuToolBitable],\n ['scopes', ch.feishuToolScopes],\n ] as const\n ).map(([key, label]) => (\n <label key={key} className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={Boolean(fs.tools?.[key])}\n onChange={(e) =>\n updateFeishu({\n tools: { ...fs.tools, [key]: e.target.checked },\n })\n }\n />\n {label}\n </label>\n ))}\n </div>\n <div className=\"mt-2\">\n <FieldHint>{ch.feishuToolsDesc}</FieldHint>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"text-sm font-medium text-fg\">{ch.feishuActionsTitle}</div>\n <label className=\"mt-2 flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={Boolean(fs.actions?.reactions)}\n onChange={(e) =>\n updateFeishu({\n actions: { ...fs.actions, reactions: e.target.checked },\n })\n }\n />\n {ch.feishuActionReactions}\n </label>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={feishuRoutingAccountIds(fs)}\n routes={form.channelAgentRoutes.feishu}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('feishu', acc, aid)}\n ch={ch}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={feishuAccountsDraft}\n onChange={(e) => setFeishuAccountsDraft(e.target.value)}\n onBlur={onFeishuAccountsBlur}\n placeholder='{ \"default\": { \"appId\": \"...\", \"appSecret\": \"...\", \"enabled\": true } }'\n />\n {feishuAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{feishuAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchFeishuSetupStart,\n fetchFeishuSetupStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\ntype FeishuDomain = 'feishu' | 'lark';\n\nexport function FeishuQrSetupDialog({\n open,\n onOpenChange,\n ch,\n onSetupSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onSetupSuccess: (result: { appId: string; domain: string; openId?: string }) => void;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [domain, setDomain] = useState<FeishuDomain>('feishu');\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const startScan = useCallback(async (d: FeishuDomain) => {\n setDomain(d);\n setError(null);\n setSessionKey(null);\n setQrUrl(null);\n setBusy(true);\n try {\n const result = await fetchFeishuSetupStart({ domain: d });\n setQrUrl(result.qrUrl);\n setSessionKey(result.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setDomain('feishu');\n setBusy(false);\n return;\n }\n void startScan('feishu');\n }, [open, startScan]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const status = await fetchFeishuSetupStatus(sessionKey);\n if (cancelled) return;\n\n if (status.phase === 'polling') return;\n\n if (status.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (status.ok) {\n setQrUrl(null);\n onOpenChange(false);\n onSetupSuccess({\n appId: status.appId,\n domain: status.domain,\n openId: status.openId,\n });\n } else {\n setError(status.message);\n setQrUrl(null);\n }\n return;\n }\n\n if (status.phase === 'unknown') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(status.message);\n setSessionKey(null);\n setQrUrl(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 3000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, onOpenChange, onSetupSuccess]);\n\n useEffect(() => {\n if (!qrUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrUrl]);\n\n const showQr = Boolean(qrUrl && sessionKey);\n /** Keep pill visible for the whole open session so region toggles do not collapse the modal. */\n const showRegionSwitch = open;\n /** True until the first QR session is ready (covers first paint before useEffect + region switches). */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.feishuQrCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.feishuQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.feishuQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.feishuQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.feishuQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? (\n <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p>\n ) : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p className=\"text-sm text-fg-muted\">\n {qrFrameLoading ? ch.feishuQrStarting : ch.feishuQrScanHint}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.feishuQrEncoding}</p>\n ) : null}\n {showQr && qrUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.feishuQrImageError}</p>\n <a\n href={qrUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.feishuQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n {showRegionSwitch ? (\n <div\n className=\"mx-auto mt-4 flex w-full max-w-[20rem] justify-center px-1\"\n role=\"group\"\n aria-label={ch.feishuRegionSwitchAria}\n >\n <div className=\"inline-flex w-full rounded-full border border-edge bg-surface-muted/60 p-1 dark:border-edge dark:bg-surface-base\">\n <button\n type=\"button\"\n disabled={busy}\n className={cn(\n 'min-w-0 flex-1 rounded-full px-3 py-2 text-center text-sm font-medium transition-colors',\n domain === 'feishu'\n ? 'bg-surface-panel text-fg shadow-sm dark:bg-surface-panel'\n : 'text-fg-muted hover:text-fg',\n )}\n onClick={() => void startScan('feishu')}\n >\n {ch.feishuRegionChina}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n className={cn(\n 'min-w-0 flex-1 rounded-full px-3 py-2 text-center text-sm font-medium transition-colors',\n domain === 'lark'\n ? 'bg-surface-panel text-fg shadow-sm dark:bg-surface-panel'\n : 'text-fg-muted hover:text-fg',\n )}\n onClick={() => void startScan('lark')}\n >\n {ch.feishuRegionInternational}\n </button>\n </div>\n </div>\n ) : null}\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void startScan(domain)}\n >\n {busy ? ch.feishuQrStarting : ch.feishuQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import type {\n ChannelsSettingsState,\n DmPolicy,\n GroupPolicy,\n ReplyToMode,\n StreamMode,\n} from '@/features/settings/channels-config-api';\nimport { cn } from '@/lib/cn';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { FieldHint, FieldLabel, SelectField } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function TelegramAdvanced({\n tg,\n updateTelegram,\n ch,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n onTgAccountsBlur,\n}: {\n tg: ChannelsSettingsState['telegram'];\n updateTelegram: (p: Partial<ChannelsSettingsState['telegram']>) => void;\n ch: ChannelsSettingsMessages;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n replyOpts: { value: ReplyToMode; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n tgAccountsDraft: string;\n setTgAccountsDraft: (s: string) => void;\n tgAccountsError: string;\n onTgAccountsBlur: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n return (\n <div className=\"space-y-4 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.apiRoot}</FieldLabel>\n <input\n className={inputClassName()}\n value={tg.apiRoot}\n onChange={(e) => updateTelegram({ apiRoot: e.target.value })}\n placeholder=\"https://api.telegram.org\"\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.proxy}</FieldLabel>\n <input\n className={inputClassName()}\n value={tg.proxy}\n onChange={(e) => updateTelegram({ proxy: e.target.value })}\n placeholder=\"http://proxy.example.com:8080\"\n />\n </div>\n <SelectField label={ch.dmPolicy} value={tg.dmPolicy} onChange={(v) => updateTelegram({ dmPolicy: v })} options={dmOpts} />\n <SelectField\n label={ch.groupPolicy}\n value={tg.groupPolicy}\n onChange={(v) => updateTelegram({ groupPolicy: v })}\n options={groupOpts}\n />\n <SelectField\n label={ch.replyToMode}\n value={tg.replyToMode}\n onChange={(v) => updateTelegram({ replyToMode: v })}\n options={replyOpts}\n />\n <SelectField\n label={ch.streamMode}\n value={tg.streamMode}\n onChange={(v) => updateTelegram({ streamMode: v })}\n options={streamOpts}\n />\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"-1001234567890\"\n value={joinAllowFrom(tg.groupAllowFrom)}\n onChange={(e) => updateTelegram({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n type=\"number\"\n min={10}\n max={200}\n className={inputClassName()}\n value={tg.historyLimit}\n onChange={(e) => updateTelegram({ historyLimit: parseInt(e.target.value, 10) || 50 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n type=\"number\"\n min={1000}\n max={10000}\n step={100}\n className={inputClassName()}\n value={tg.textChunkLimit}\n onChange={(e) => updateTelegram({ textChunkLimit: parseInt(e.target.value, 10) || 4000 })}\n />\n </div>\n </div>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={tg.debug}\n onChange={(e) => updateTelegram({ debug: e.target.checked })}\n />\n {ch.telegramDebug}\n </label>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={tgAccountsDraft}\n onChange={(e) => setTgAccountsDraft(e.target.value)}\n onBlur={onTgAccountsBlur}\n placeholder='{ \"personal\": { \"accountId\": \"personal\", \"botToken\": \"...\", ... } }'\n />\n {tgAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{tgAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { Check, ChevronDown, Copy, Eye, EyeOff, X } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { telegramRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport {\n emptyTelegramAccount,\n type ChannelsSettingsState,\n type DmPolicy,\n type GroupPolicy,\n type ReplyToMode,\n type StreamMode,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { TelegramAdvanced } from './telegram-advanced';\nimport { channelsInputClassName, joinAllowFrom, parseIdList, telegramDefaultBotToken } from './utils';\n\nexport function TelegramChannelSettingsDialog({\n open,\n onOpenChange,\n ch,\n form,\n baseline,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n copied,\n copyToken,\n updateTelegram,\n updateChannelAgentRoute,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n onTgAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n tgAdvanced: boolean;\n setTgAdvanced: (v: boolean | ((b: boolean) => boolean)) => void;\n showToken: boolean;\n setShowToken: (v: boolean | ((b: boolean) => boolean)) => void;\n copied: boolean;\n copyToken: () => Promise<void>;\n updateTelegram: (patch: Partial<ChannelsSettingsState['telegram']>) => void;\n updateChannelAgentRoute: (channel: 'telegram', accountId: string, agentId: string) => void;\n tgAccountsDraft: string;\n setTgAccountsDraft: (s: string) => void;\n tgAccountsError: string;\n onTgAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n replyOpts: { value: ReplyToMode; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const tg = form.telegram;\n const tgBaselineToken = baseline ? telegramDefaultBotToken(baseline.telegram) : '';\n const tgToken = telegramDefaultBotToken(tg);\n const telegramTokenDisplayLocked =\n !showToken && Boolean(String(tgBaselineToken).trim()) && tgToken === tgBaselineToken;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,48rem)] w-[min(100%-2rem,36rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <Dialog.Title className=\"text-lg font-semibold tracking-tight text-fg\">{ch.telegramTitle}</Dialog.Title>\n <Dialog.Description className=\"mt-1 text-sm text-fg-muted\">{ch.telegramSubtitle}</Dialog.Description>\n </div>\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.modalCancel}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n </div>\n\n <label className=\"mt-6 flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={tg.enabled}\n onChange={(e) => updateTelegram({ enabled: e.target.checked })}\n />\n <span>{ch.enableTelegramAria}</span>\n </label>\n\n <div className=\"mt-6 space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.telegramToken}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showToken ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={telegramTokenDisplayLocked}\n value={\n telegramTokenDisplayLocked\n ? '*'.repeat(Math.max(1, tgBaselineToken.length))\n : tgToken\n }\n onChange={(e) => {\n if (telegramTokenDisplayLocked) return;\n const prev = tg.accounts?.default ?? emptyTelegramAccount('default');\n updateTelegram({\n accounts: {\n ...tg.accounts,\n default: { ...prev, accountId: 'default', botToken: e.target.value },\n },\n });\n }}\n placeholder=\"123456789:ABCdefGHIjklMNOpqrsTUVwxyz\"\n />\n {tgToken ? (\n <Button type=\"button\" variant=\"secondary\" className=\"px-2 py-1 text-xs\" onClick={() => void copyToken()}>\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowToken((s) => !s)}\n >\n {showToken ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showToken ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.telegramTokenDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"123456789, 987654321\"\n value={joinAllowFrom(tg.allowFrom)}\n onChange={(e) => updateTelegram({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={telegramRoutingAccountIds(tg)}\n routes={form.channelAgentRoutes.telegram}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('telegram', acc, aid)}\n ch={ch}\n />\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"-ml-2 h-auto justify-start px-2 py-1 text-sm text-fg-muted hover:text-fg\"\n onClick={() => setTgAdvanced((a) => !a)}\n >\n <ChevronDown className={cn('mr-1 size-4 transition-transform', tgAdvanced && 'rotate-180')} />\n {tgAdvanced ? ch.advancedHide : ch.advancedShow}\n </Button>\n\n {tgAdvanced ? (\n <TelegramAdvanced\n tg={tg}\n updateTelegram={updateTelegram}\n ch={ch}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n replyOpts={replyOpts}\n streamOpts={streamOpts}\n tgAccountsDraft={tgAccountsDraft}\n setTgAccountsDraft={setTgAccountsDraft}\n tgAccountsError={tgAccountsError}\n onTgAccountsBlur={onTgAccountsBlur}\n />\n ) : null}\n </div>\n\n <div className=\"mt-8 flex flex-wrap justify-end gap-2 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">\n <Button type=\"button\" variant=\"secondary\" onClick={() => onOpenChange(false)}>\n {ch.modalCancel}\n </Button>\n <Button type=\"button\" variant=\"secondary\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n disabled={!dirty || saving}\n onClick={async () => {\n const ok = await save();\n if (ok) onOpenChange(false);\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport useSWR from 'swr';\n\nimport { fetchChatAgents } from '@/features/chat/chat-agents-api';\nimport { useGatewayConfigSwr } from '@/features/gateway/gateway-config-swr';\nimport {\n defaultChannelsState,\n normalizeChannelsFromConfig,\n patchChannelsSettings,\n type ChannelsSettingsState,\n type DmPolicy,\n type GroupPolicy,\n type ReplyToMode,\n type StreamMode,\n} from '@/features/settings/channels-config-api';\nimport { messages } from '@/i18n/messages';\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nimport { telegramDefaultBotToken } from './utils';\n\nexport function useChannelsSettingsPanel() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const ch = m.channelsSettings;\n const token = useGatewayStore((st) => st.token);\n const hasToken = Boolean(token);\n\n const [form, setForm] = useState<ChannelsSettingsState | null>(null);\n const [baseline, setBaseline] = useState<ChannelsSettingsState | null>(null);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [saveOk, setSaveOk] = useState(false);\n\n const [weixinModalOpen, setWeixinModalOpen] = useState(false);\n const [telegramModalOpen, setTelegramModalOpen] = useState(false);\n const [feishuModalOpen, setFeishuModalOpen] = useState(false);\n const [dingtalkModalOpen, setDingtalkModalOpen] = useState(false);\n const [removeTarget, setRemoveTarget] = useState<'weixin' | 'telegram' | 'feishu' | 'dingtalk' | null>(null);\n const [weixinSuccessBanner, setWeixinSuccessBanner] = useState<string | null>(null);\n const [feishuSetupSuccessBanner, setFeishuSetupSuccessBanner] = useState<string | null>(null);\n const [dingtalkSetupSuccessBanner, setDingtalkSetupSuccessBanner] = useState<string | null>(null);\n const [tgAdvanced, setTgAdvanced] = useState(false);\n const [showToken, setShowToken] = useState(false);\n const [showFeishuSecret, setShowFeishuSecret] = useState(false);\n const [showFeishuWebhookSecrets, setShowFeishuWebhookSecrets] = useState(false);\n const [showDingtalkSecret, setShowDingtalkSecret] = useState(false);\n const [copied, setCopied] = useState(false);\n const [feishuCopied, setFeishuCopied] = useState(false);\n const [dingtalkCopied, setDingtalkCopied] = useState(false);\n const [feishuWebhookCopied, setFeishuWebhookCopied] = useState(false);\n\n const [tgAccountsDraft, setTgAccountsDraft] = useState('');\n const [tgAccountsError, setTgAccountsError] = useState('');\n const [wxAccountsDraft, setWxAccountsDraft] = useState('');\n const [wxAccountsError, setWxAccountsError] = useState('');\n const [feishuAccountsDraft, setFeishuAccountsDraft] = useState('');\n const [feishuAccountsError, setFeishuAccountsError] = useState('');\n const [dingtalkAccountsDraft, setDingtalkAccountsDraft] = useState('');\n const [dingtalkAccountsError, setDingtalkAccountsError] = useState('');\n\n const { data: chatAgents } = useSWR(hasToken ? 'gateway-chat-agents-ch' : null, fetchChatAgents, {\n revalidateOnFocus: false,\n });\n\n const { data: cfgData, error: swrError, isLoading, mutate } = useGatewayConfigSwr(hasToken);\n\n const parsed = useMemo(\n () =>\n cfgData?.payload?.config !== undefined\n ? normalizeChannelsFromConfig(cfgData.payload.config)\n : null,\n [cfgData],\n );\n\n const dirty = useMemo(() => {\n if (!form || !baseline) return false;\n return JSON.stringify(form) !== JSON.stringify(baseline);\n }, [form, baseline]);\n\n useEffect(() => {\n if (!hasToken) {\n setForm(null);\n setBaseline(null);\n return;\n }\n if (parsed === null) return;\n if (!dirty) {\n setForm(parsed);\n setBaseline(structuredClone(parsed));\n setTgAccountsDraft(JSON.stringify(parsed.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(parsed.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(parsed.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(parsed.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setSaveOk(false);\n }\n }, [hasToken, parsed, dirty]);\n\n const loading = Boolean(hasToken && isLoading && cfgData === undefined && !swrError);\n const fetchError =\n swrError instanceof Error ? swrError.message : swrError ? String(swrError) : null;\n\n const updateChannelAgentRoute = useCallback(\n (channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk', accountId: string, agentId: string) => {\n setForm((f) => {\n if (!f) return null;\n const k =\n channel === 'telegram'\n ? 'telegram'\n : channel === 'weixin'\n ? 'weixin'\n : channel === 'feishu'\n ? 'feishu'\n : 'dingtalk';\n return {\n ...f,\n channelAgentRoutes: {\n ...f.channelAgentRoutes,\n [k]: { ...f.channelAgentRoutes[k], [accountId]: agentId.trim().toLowerCase() },\n },\n };\n });\n },\n [],\n );\n\n const updateTelegram = useCallback((patch: Partial<ChannelsSettingsState['telegram']>) => {\n setForm((f) => (f ? { ...f, telegram: { ...f.telegram, ...patch } } : null));\n }, []);\n\n const updateWeixin = useCallback((patch: Partial<ChannelsSettingsState['weixin']>) => {\n setForm((f) => (f ? { ...f, weixin: { ...f.weixin, ...patch } } : null));\n }, []);\n\n const updateFeishu = useCallback((patch: Partial<ChannelsSettingsState['feishu']>) => {\n setForm((f) => (f ? { ...f, feishu: { ...f.feishu, ...patch } } : null));\n }, []);\n\n const updateDingtalk = useCallback((patch: Partial<ChannelsSettingsState['dingtalk']>) => {\n setForm((f) => (f ? { ...f, dingtalk: { ...f.dingtalk, ...patch } } : null));\n }, []);\n\n const save = useCallback(async (): Promise<boolean> => {\n if (!form || saving) return false;\n setSaving(true);\n setError(null);\n setSaveOk(false);\n try {\n const next = await patchChannelsSettings(form);\n setForm(next);\n const baselineClone = structuredClone(next);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setSaveOk(true);\n window.setTimeout(() => setSaveOk(false), 2500);\n return true;\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n return false;\n } finally {\n setSaving(false);\n }\n }, [form, saving, ch.saveError]);\n\n const discard = useCallback(() => {\n if (!baseline) return;\n const b = structuredClone(baseline);\n setForm(b);\n setTgAccountsDraft(JSON.stringify(b.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(b.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(b.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(b.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setError(null);\n setSaveOk(false);\n }, [baseline]);\n\n const toggleChannelEnabled = useCallback(\n async (which: 'weixin' | 'telegram' | 'feishu' | 'dingtalk', enabled: boolean) => {\n if (!form || saving) return;\n const prev = form;\n const next: ChannelsSettingsState =\n which === 'weixin'\n ? { ...form, weixin: { ...form.weixin, enabled } }\n : which === 'telegram'\n ? { ...form, telegram: { ...form.telegram, enabled } }\n : which === 'feishu'\n ? { ...form, feishu: { ...form.feishu, enabled } }\n : { ...form, dingtalk: { ...form.dingtalk, enabled } };\n setForm(next);\n setSaving(true);\n setError(null);\n try {\n const synced = await patchChannelsSettings(next);\n setForm(synced);\n const baselineClone = structuredClone(synced);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n setForm(prev);\n } finally {\n setSaving(false);\n }\n },\n [form, saving, ch.saveError],\n );\n\n const removeChannel = useCallback(async () => {\n if (!form || !removeTarget || saving) return;\n const defaults = defaultChannelsState();\n const next: ChannelsSettingsState =\n removeTarget === 'weixin'\n ? { ...form, weixin: defaults.weixin }\n : removeTarget === 'telegram'\n ? { ...form, telegram: defaults.telegram }\n : removeTarget === 'feishu'\n ? { ...form, feishu: defaults.feishu }\n : { ...form, dingtalk: defaults.dingtalk };\n setSaving(true);\n setError(null);\n try {\n const synced = await patchChannelsSettings(next);\n setForm(synced);\n const baselineClone = structuredClone(synced);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setRemoveTarget(null);\n setSaveOk(true);\n window.setTimeout(() => setSaveOk(false), 2500);\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n } finally {\n setSaving(false);\n }\n }, [form, removeTarget, saving, ch.saveError]);\n\n const copyToken = useCallback(async () => {\n const t = form ? telegramDefaultBotToken(form.telegram) : '';\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setCopied(true);\n window.setTimeout(() => setCopied(false), 2000);\n }, [form]);\n\n const handleFeishuQrSetupSuccess = useCallback(\n (result: { appId: string; domain: string; openId?: string }) => {\n updateFeishu({\n appId: result.appId,\n domain: result.domain,\n enabled: true,\n });\n void mutate();\n setFeishuSetupSuccessBanner(ch.feishuQrSetupSuccess);\n window.setTimeout(() => setFeishuSetupSuccessBanner(null), 4000);\n },\n [updateFeishu, mutate, ch.feishuQrSetupSuccess],\n );\n\n const handleDingtalkQrSetupSuccess = useCallback(\n (result: { clientId: string }) => {\n updateDingtalk({\n clientId: result.clientId,\n enabled: true,\n });\n void mutate();\n setDingtalkSetupSuccessBanner(ch.dingtalkQrSetupSuccess);\n window.setTimeout(() => setDingtalkSetupSuccessBanner(null), 4000);\n },\n [updateDingtalk, mutate, ch.dingtalkQrSetupSuccess],\n );\n\n const copyDingtalkSecret = useCallback(async () => {\n const t = form?.dingtalk?.clientSecret;\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setDingtalkCopied(true);\n window.setTimeout(() => setDingtalkCopied(false), 2000);\n }, [form]);\n\n const copyFeishuSecret = useCallback(async () => {\n const t = form?.feishu?.appSecret;\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setFeishuCopied(true);\n window.setTimeout(() => setFeishuCopied(false), 2000);\n }, [form]);\n\n const copyFeishuWebhookConfig = useCallback(async () => {\n const fs = form?.feishu;\n if (!fs) return;\n const payload = {\n connectionMode: fs.connectionMode,\n verificationToken: fs.verificationToken || '',\n encryptKey: fs.encryptKey || '',\n webhookHost: fs.webhookHost || '',\n webhookPort: fs.webhookPort || 0,\n webhookPath: fs.webhookPath || '',\n };\n await navigator.clipboard.writeText(JSON.stringify(payload, null, 2)).catch(() => {});\n setFeishuWebhookCopied(true);\n window.setTimeout(() => setFeishuWebhookCopied(false), 2000);\n }, [form]);\n\n const onTgAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = tgAccountsDraft.trim();\n if (!raw) {\n updateTelegram({ accounts: {} });\n setTgAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateTelegram({ accounts: parsedJson as ChannelsSettingsState['telegram']['accounts'] });\n setTgAccountsError('');\n } catch (err) {\n setTgAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, tgAccountsDraft, updateTelegram, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onWxAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = wxAccountsDraft.trim();\n if (!raw) {\n updateWeixin({ accounts: {} });\n setWxAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateWeixin({ accounts: parsedJson as ChannelsSettingsState['weixin']['accounts'] });\n setWxAccountsError('');\n } catch (err) {\n setWxAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, wxAccountsDraft, updateWeixin, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onFeishuAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = feishuAccountsDraft.trim();\n if (!raw) {\n updateFeishu({ accounts: {} });\n setFeishuAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateFeishu({ accounts: parsedJson as ChannelsSettingsState['feishu']['accounts'] });\n setFeishuAccountsError('');\n } catch (err) {\n setFeishuAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, feishuAccountsDraft, updateFeishu, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onDingtalkAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = dingtalkAccountsDraft.trim();\n if (!raw) {\n updateDingtalk({ accounts: {} });\n setDingtalkAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateDingtalk({ accounts: parsedJson as ChannelsSettingsState['dingtalk']['accounts'] });\n setDingtalkAccountsError('');\n } catch (err) {\n setDingtalkAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, dingtalkAccountsDraft, updateDingtalk, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const dmOpts = useMemo(\n () =>\n (['pairing', 'allowlist', 'open', 'disabled'] as DmPolicy[]).map((value) => ({\n value,\n label: ch.policy.dm[value],\n })),\n [ch.policy.dm],\n );\n\n const groupOpts = useMemo(\n () =>\n (['open', 'disabled', 'allowlist'] as GroupPolicy[]).map((value) => ({\n value,\n label: ch.policy.group[value],\n })),\n [ch.policy.group],\n );\n\n const replyOpts = useMemo(\n () =>\n (['off', 'first', 'all'] as ReplyToMode[]).map((value) => ({\n value,\n label: ch.policy.reply[value],\n })),\n [ch.policy.reply],\n );\n\n const streamOpts = useMemo(\n () =>\n (['off', 'partial', 'block'] as StreamMode[]).map((value) => ({\n value,\n label: ch.policy.stream[value],\n })),\n [ch.policy.stream],\n );\n\n return {\n language,\n m,\n ch,\n hasToken,\n loading,\n fetchError,\n mutate,\n form,\n baseline,\n dirty,\n saving,\n error,\n saveOk,\n weixinModalOpen,\n setWeixinModalOpen,\n telegramModalOpen,\n setTelegramModalOpen,\n feishuModalOpen,\n setFeishuModalOpen,\n dingtalkModalOpen,\n setDingtalkModalOpen,\n removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n feishuSetupSuccessBanner,\n dingtalkSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n showDingtalkSecret,\n setShowDingtalkSecret,\n copied,\n feishuCopied,\n dingtalkCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n updateDingtalk,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n handleDingtalkQrSetupSuccess,\n copyFeishuSecret,\n copyDingtalkSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n };\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchWeixinGatewayQrLoginStart,\n fetchWeixinGatewayQrLoginStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function WeixinQrLoginDialog({\n open,\n onOpenChange,\n ch,\n onLoginSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onLoginSuccess: () => void | Promise<void>;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrcodeUrl, setQrcodeUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [hint, setHint] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const start = useCallback(async () => {\n setError(null);\n setHint(null);\n setSessionKey(null);\n setBusy(true);\n try {\n const r = await fetchWeixinGatewayQrLoginStart();\n setQrcodeUrl(r.qrcodeUrl);\n setSessionKey(r.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrcodeUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setHint(null);\n return;\n }\n void start();\n }, [open, start]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const st = await fetchWeixinGatewayQrLoginStatus(sessionKey);\n if (cancelled) return;\n if (st.phase === 'polling') {\n setQrcodeUrl(st.qrcodeUrl);\n if (st.qrStatus === 'scaned') {\n setHint(ch.weixinQrLoginScanned);\n } else {\n setHint(null);\n }\n return;\n }\n if (st.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (st.ok) {\n setQrcodeUrl(null);\n onOpenChange(false);\n await onLoginSuccess();\n } else {\n setError(st.message);\n setQrcodeUrl(null);\n }\n return;\n }\n if (st.phase === 'unknown') {\n setHint(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrcodeUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 2000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, ch.weixinQrLoginScanned, ch.weixinQrLoginSuccess, onLoginSuccess, onOpenChange]);\n\n useEffect(() => {\n if (!qrcodeUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrcodeUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrcodeUrl]);\n\n const showQr = Boolean(qrcodeUrl && sessionKey);\n /** True while waiting for a new login session (first open, regenerate). Keeps modal height stable. */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.weixinQrModalCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.weixinQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.weixinQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.weixinQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.weixinQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p\n className={cn(\n 'min-h-[1.25rem] text-center text-sm',\n hint && !qrFrameLoading ? 'text-accent' : 'text-fg-muted',\n )}\n >\n {qrFrameLoading ? ch.weixinQrLoginBusy : hint ?? '\\u00a0'}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrcodeUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrcodeUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.weixinQrEncoding}</p>\n ) : null}\n {showQr && qrcodeUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.weixinQrImageError}</p>\n <a\n href={qrcodeUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.weixinQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void start()}\n >\n {busy ? ch.weixinQrLoginBusy : ch.weixinQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import type { ChannelsSettingsState, DmPolicy, StreamMode } from '@/features/settings/channels-config-api';\nimport { weixinRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport { cn } from '@/lib/cn';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel, SelectField } from './field-primitives';\nimport { channelsInputClassName } from './utils';\n\nexport function WeixinAdvanced({\n wx,\n updateWeixin,\n ch,\n dmOpts,\n streamOpts,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n onWxAccountsBlur,\n channelAgentRoutesWx,\n defaultAgentId,\n agentItems,\n onAgentRouteChange,\n routingDisabled,\n}: {\n wx: ChannelsSettingsState['weixin'];\n updateWeixin: (p: Partial<ChannelsSettingsState['weixin']>) => void;\n ch: ChannelsSettingsMessages;\n dmOpts: { value: DmPolicy; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n wxAccountsDraft: string;\n setWxAccountsDraft: (s: string) => void;\n wxAccountsError: string;\n onWxAccountsBlur: () => void;\n channelAgentRoutesWx: Record<string, string>;\n defaultAgentId: string;\n agentItems: { id: string; name?: string }[];\n onAgentRouteChange: (accountId: string, agentId: string) => void;\n routingDisabled: boolean;\n}) {\n const inputClassName = channelsInputClassName;\n return (\n <div className=\"space-y-4 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinAllowFrom}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"wxid_..., openid_...\"\n value={wx.allowFrom.join(', ')}\n onChange={(e) =>\n updateWeixin({\n allowFrom: e.target.value\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean),\n })\n }\n />\n <FieldHint>{ch.weixinAllowFromDesc}</FieldHint>\n </div>\n <SelectField label={ch.dmPolicy} value={wx.dmPolicy} onChange={(v) => updateWeixin({ dmPolicy: v })} options={dmOpts} />\n <SelectField\n label={ch.streamMode}\n value={wx.streamMode}\n onChange={(v) => updateWeixin({ streamMode: v })}\n options={streamOpts}\n />\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n type=\"number\"\n min={10}\n max={200}\n className={inputClassName()}\n value={wx.historyLimit}\n onChange={(e) => updateWeixin({ historyLimit: parseInt(e.target.value, 10) || 50 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n type=\"number\"\n min={1000}\n max={10000}\n step={100}\n className={inputClassName()}\n value={wx.textChunkLimit}\n onChange={(e) => updateWeixin({ textChunkLimit: parseInt(e.target.value, 10) || 4000 })}\n />\n </div>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinRouteTag}</FieldLabel>\n <input\n className={inputClassName()}\n value={wx.routeTag}\n onChange={(e) => updateWeixin({ routeTag: e.target.value })}\n placeholder={ch.routeTagPlaceholder}\n />\n <FieldHint>{ch.weixinRouteTagDesc}</FieldHint>\n </div>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={wx.debug}\n onChange={(e) => updateWeixin({ debug: e.target.checked })}\n />\n {ch.weixinDebug}\n </label>\n <FieldHint>{ch.weixinDebugDesc}</FieldHint>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinAccountsJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={wxAccountsDraft}\n onChange={(e) => setWxAccountsDraft(e.target.value)}\n onBlur={onWxAccountsBlur}\n placeholder='{ \"personal\": { \"name\": \"...\", \"cdnBaseUrl\": \"...\", \"enabled\": true } }'\n />\n {wxAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{wxAccountsError}</p>\n ) : (\n <FieldHint>{ch.weixinAccountsJsonDesc}</FieldHint>\n )}\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={weixinRoutingAccountIds(wx)}\n routes={channelAgentRoutesWx}\n defaultAgentId={defaultAgentId}\n agentItems={agentItems}\n disabled={routingDisabled}\n onChange={onAgentRouteChange}\n ch={ch}\n />\n </div>\n );\n}\n","import { ChevronDown } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport type { ChannelsSettingsState, DmPolicy, StreamMode } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { WeixinAdvanced } from './weixin-advanced';\n\nexport function WeixinMoreSettingsSection({\n ch,\n wx,\n updateWeixin,\n dmOpts,\n streamOpts,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n onWxAccountsBlur,\n form,\n chatAgents,\n onAgentRouteChange,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n wx: ChannelsSettingsState['weixin'];\n updateWeixin: (patch: Partial<ChannelsSettingsState['weixin']>) => void;\n dmOpts: { value: DmPolicy; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n wxAccountsDraft: string;\n setWxAccountsDraft: (v: string) => void;\n wxAccountsError: string;\n onWxAccountsBlur: () => void;\n form: ChannelsSettingsState;\n chatAgents: ChatAgentsPayload | undefined;\n onAgentRouteChange: (accountId: string, agentId: string) => void;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.weixinAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={wx.enabled}\n onChange={(e) => updateWeixin({ enabled: e.target.checked })}\n />\n <span>{ch.enableWeixinAria}</span>\n </label>\n <div className=\"[&>div]:border-0 [&>div]:pt-0\">\n <WeixinAdvanced\n wx={wx}\n updateWeixin={updateWeixin}\n ch={ch}\n dmOpts={dmOpts}\n streamOpts={streamOpts}\n wxAccountsDraft={wxAccountsDraft}\n setWxAccountsDraft={setWxAccountsDraft}\n wxAccountsError={wxAccountsError}\n onWxAccountsBlur={onWxAccountsBlur}\n channelAgentRoutesWx={form.channelAgentRoutes.weixin}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n onAgentRouteChange={onAgentRouteChange}\n routingDisabled={saving}\n />\n </div>\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import { ExternalLink, MessageCircle, MessageSquare, Send } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport { docsGuidePageUrl } from '@/navigation';\n\nimport { ChannelImHubCard } from './channel-im-hub-card';\nimport { ChannelsRemoveChannelDialog } from './channels-remove-channel-dialog';\nimport { DingtalkMoreSettingsSection } from './dingtalk-more-settings-section';\nimport { DingtalkQrSetupDialog } from './dingtalk-qr-setup-dialog';\nimport { FeishuMoreSettingsSection } from './feishu-more-settings-section';\nimport { FeishuQrSetupDialog } from './feishu-qr-setup-dialog';\nimport { TelegramChannelSettingsDialog } from './telegram-channel-settings-dialog';\nimport { useChannelsSettingsPanel } from './use-channels-settings-panel';\nimport { WeixinQrLoginDialog } from './weixin-qr-login-dialog';\nimport { WeixinMoreSettingsSection } from './weixin-more-settings-section';\nimport { isDingtalkConfigured, isFeishuConfigured, isTelegramConfigured, isWeixinConfigured } from './utils';\n\nexport function ChannelsSettingsPanel() {\n const ctx = useChannelsSettingsPanel();\n const {\n language,\n m,\n ch,\n hasToken,\n loading,\n fetchError,\n mutate,\n form,\n baseline,\n dirty,\n saving,\n error,\n saveOk,\n weixinModalOpen,\n setWeixinModalOpen,\n telegramModalOpen,\n setTelegramModalOpen,\n feishuModalOpen,\n setFeishuModalOpen,\n removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n dingtalkModalOpen,\n setDingtalkModalOpen,\n feishuSetupSuccessBanner,\n dingtalkSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n showDingtalkSecret,\n setShowDingtalkSecret,\n copied,\n feishuCopied,\n dingtalkCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n updateDingtalk,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n handleDingtalkQrSetupSuccess,\n copyFeishuSecret,\n copyDingtalkSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n } = ctx;\n\n if (!hasToken) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <h1 className=\"text-lg font-semibold text-fg\">{m.settingsSections.channels}</h1>\n <p className=\"text-sm text-fg-muted\">{ch.needToken}</p>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <div className=\"h-8 w-48 animate-pulse rounded bg-surface-hover\" />\n <div className=\"mt-6 h-32 animate-pulse rounded-xl bg-surface-hover\" />\n <p className=\"mt-4 text-sm text-fg-muted\">{ch.loading}</p>\n </div>\n );\n }\n\n if (!form) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <p className=\"text-sm text-fg-muted\">{error ?? fetchError ?? ch.loadError}</p>\n <Button type=\"button\" variant=\"secondary\" onClick={() => void mutate()}>\n {ch.retry}\n </Button>\n </div>\n );\n }\n\n const wx = form.weixin;\n const tg = form.telegram;\n const fs = form.feishu;\n const dt = form.dingtalk;\n const weixinConfigured = isWeixinConfigured(wx);\n const telegramConfigured = isTelegramConfigured(tg);\n const feishuConfigured = isFeishuConfigured(fs);\n const dingtalkConfigured = isDingtalkConfigured(dt);\n\n const feishuMoreSettings = (\n <FeishuMoreSettingsSection\n ch={ch}\n form={form}\n baseline={baseline}\n showFeishuSecret={showFeishuSecret}\n setShowFeishuSecret={setShowFeishuSecret}\n showFeishuWebhookSecrets={showFeishuWebhookSecrets}\n setShowFeishuWebhookSecrets={setShowFeishuWebhookSecrets}\n feishuCopied={feishuCopied}\n feishuWebhookCopied={feishuWebhookCopied}\n copyFeishuSecret={copyFeishuSecret}\n copyFeishuWebhookConfig={copyFeishuWebhookConfig}\n updateFeishu={updateFeishu}\n updateChannelAgentRoute={updateChannelAgentRoute}\n feishuAccountsDraft={feishuAccountsDraft}\n setFeishuAccountsDraft={setFeishuAccountsDraft}\n feishuAccountsError={feishuAccountsError}\n onFeishuAccountsBlur={onFeishuAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n const dingtalkMoreSettings = (\n <DingtalkMoreSettingsSection\n ch={ch}\n form={form}\n baseline={baseline}\n showDingtalkSecret={showDingtalkSecret}\n setShowDingtalkSecret={setShowDingtalkSecret}\n dingtalkCopied={dingtalkCopied}\n copyDingtalkSecret={copyDingtalkSecret}\n updateDingtalk={updateDingtalk}\n updateChannelAgentRoute={updateChannelAgentRoute}\n dingtalkAccountsDraft={dingtalkAccountsDraft}\n setDingtalkAccountsDraft={setDingtalkAccountsDraft}\n dingtalkAccountsError={dingtalkAccountsError}\n onDingtalkAccountsBlur={onDingtalkAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n const weixinMoreSettings = (\n <WeixinMoreSettingsSection\n ch={ch}\n wx={wx}\n updateWeixin={updateWeixin}\n dmOpts={dmOpts}\n streamOpts={streamOpts}\n wxAccountsDraft={wxAccountsDraft}\n setWxAccountsDraft={setWxAccountsDraft}\n wxAccountsError={wxAccountsError}\n onWxAccountsBlur={onWxAccountsBlur}\n form={form}\n chatAgents={chatAgents}\n onAgentRouteChange={(acc, aid) => updateChannelAgentRoute('weixin', acc, aid)}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6\">\n <header className=\"flex flex-col gap-1\">\n <h1 className=\"text-lg font-semibold tracking-tight text-fg\">{m.settingsSections.channels}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{ch.subtitle}</p>\n <a\n href={docsGuidePageUrl(language, 'channels')}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-1 inline-flex items-center gap-1 text-sm text-accent hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n >\n {ch.docsLink}\n <ExternalLink className=\"size-3.5\" />\n </a>\n </header>\n\n {dirty ? <p className=\"text-xs text-amber-800 dark:text-amber-200\">{ch.unsavedHint}</p> : null}\n {saveOk ? <p className=\"text-xs text-fg-muted\">{ch.saved}</p> : null}\n {error ? <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n {weixinSuccessBanner ? <p className=\"text-xs text-accent\">{weixinSuccessBanner}</p> : null}\n {feishuSetupSuccessBanner ? (\n <div className=\"rounded-xl border border-success/30 bg-success-soft px-4 py-3 text-sm text-success\">\n {feishuSetupSuccessBanner}\n </div>\n ) : null}\n {dingtalkSetupSuccessBanner ? (\n <div className=\"rounded-xl border border-success/30 bg-success-soft px-4 py-3 text-sm text-success\">\n {dingtalkSetupSuccessBanner}\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-3\">\n <ChannelImHubCard\n icon={<MessageSquare className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.weixinTitle}\n subtitle={ch.weixinSubtitle}\n configured={weixinConfigured}\n enabled={wx.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('weixin', next)}\n onConfigure={() => setWeixinModalOpen(true)}\n onEdit={() => setWeixinModalOpen(true)}\n onRemove={() => setRemoveTarget('weixin')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<Send className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.telegramTitle}\n subtitle={ch.telegramSubtitle}\n configured={telegramConfigured}\n enabled={tg.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('telegram', next)}\n onConfigure={() => setTelegramModalOpen(true)}\n onEdit={() => setTelegramModalOpen(true)}\n onRemove={() => setRemoveTarget('telegram')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<MessageSquare className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.feishuTitle}\n subtitle={ch.feishuSubtitle}\n configured={feishuConfigured}\n enabled={fs.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('feishu', next)}\n onConfigure={() => setFeishuModalOpen(true)}\n onEdit={() => setFeishuModalOpen(true)}\n onRemove={() => setRemoveTarget('feishu')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<MessageCircle className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.dingtalkTitle}\n subtitle={ch.dingtalkSubtitle}\n configured={dingtalkConfigured}\n enabled={dt.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('dingtalk', next)}\n onConfigure={() => setDingtalkModalOpen(true)}\n onEdit={() => setDingtalkModalOpen(true)}\n onRemove={() => setRemoveTarget('dingtalk')}\n ch={ch}\n />\n </div>\n\n <WeixinQrLoginDialog\n open={weixinModalOpen}\n onOpenChange={setWeixinModalOpen}\n ch={ch}\n onLoginSuccess={async () => {\n await mutate();\n setWeixinSuccessBanner(ch.weixinQrLoginSuccess);\n window.setTimeout(() => setWeixinSuccessBanner(null), 4000);\n }}\n moreSettings={weixinMoreSettings}\n />\n\n <TelegramChannelSettingsDialog\n open={telegramModalOpen}\n onOpenChange={setTelegramModalOpen}\n ch={ch}\n form={form}\n baseline={baseline}\n tgAdvanced={tgAdvanced}\n setTgAdvanced={setTgAdvanced}\n showToken={showToken}\n setShowToken={setShowToken}\n copied={copied}\n copyToken={copyToken}\n updateTelegram={updateTelegram}\n updateChannelAgentRoute={updateChannelAgentRoute}\n tgAccountsDraft={tgAccountsDraft}\n setTgAccountsDraft={setTgAccountsDraft}\n tgAccountsError={tgAccountsError}\n onTgAccountsBlur={onTgAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n replyOpts={replyOpts}\n streamOpts={streamOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n\n <FeishuQrSetupDialog\n open={feishuModalOpen}\n onOpenChange={setFeishuModalOpen}\n ch={ch}\n onSetupSuccess={handleFeishuQrSetupSuccess}\n moreSettings={feishuMoreSettings}\n />\n\n <DingtalkQrSetupDialog\n open={dingtalkModalOpen}\n onOpenChange={setDingtalkModalOpen}\n ch={ch}\n onSetupSuccess={handleDingtalkQrSetupSuccess}\n moreSettings={dingtalkMoreSettings}\n />\n\n <ChannelsRemoveChannelDialog\n open={removeTarget !== null}\n onOpenChange={(o) => {\n if (!o) setRemoveTarget(null);\n }}\n ch={ch}\n removeTarget={removeTarget}\n onCancel={() => setRemoveTarget(null)}\n saving={saving}\n onConfirmRemove={() => void removeChannel()}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"channels-settings-Dn-hIRl1.js","names":[],"sources":["../../../../../web/src/features/settings/channels/channel-im-hub-card.tsx","../../../../../web/src/features/settings/channels/channels-remove-channel-dialog.tsx","../../../../../web/src/features/settings/channel-bindings-merge.ts","../../../../../web/src/features/settings/channels/utils.ts","../../../../../web/src/features/settings/channels/field-primitives.tsx","../../../../../web/src/features/settings/channels/channel-agent-routing-block.tsx","../../../../../web/src/features/settings/channels/dingtalk-more-settings-section.tsx","../../../../../web/src/features/settings/channels-config-api.ts","../../../../../web/src/features/settings/channels/dingtalk-qr-setup-dialog.tsx","../../../../../web/src/features/settings/channels/feishu-more-settings-section.tsx","../../../../../web/src/features/settings/channels/feishu-qr-setup-dialog.tsx","../../../../../web/src/features/settings/channels/telegram-advanced.tsx","../../../../../web/src/features/settings/channels/telegram-channel-settings-dialog.tsx","../../../../../web/src/features/settings/channels/use-channels-settings-panel.ts","../../../../../web/src/features/settings/channels/weixin-qr-login-dialog.tsx","../../../../../web/src/features/settings/channels/weixin-advanced.tsx","../../../../../web/src/features/settings/channels/weixin-more-settings-section.tsx","../../../../../web/src/features/settings/channels/channels-settings-panel.tsx"],"sourcesContent":["import * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport { MoreHorizontal, Pencil, Trash2 } from 'lucide-react';\nimport type { ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_POPOVER_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport type ChannelImHubCardProps = {\n icon: ReactNode;\n title: string;\n subtitle: string;\n configured: boolean;\n enabled: boolean;\n onToggle: (next: boolean) => void | Promise<void>;\n toggleDisabled: boolean;\n onConfigure: () => void;\n onEdit: () => void;\n onRemove: () => void;\n ch: ChannelsSettingsMessages;\n};\n\nexport function ChannelImHubCard({\n icon,\n title,\n subtitle,\n configured,\n enabled,\n onToggle,\n toggleDisabled,\n onConfigure,\n onEdit,\n onRemove,\n ch,\n}: ChannelImHubCardProps) {\n return (\n <div className=\"flex flex-col gap-3 rounded-2xl border border-edge bg-surface-base px-4 py-4 dark:border-edge sm:flex-row sm:items-center sm:gap-4\">\n <div className=\"flex min-w-0 flex-1 items-start gap-4\">\n <div className=\"flex size-12 shrink-0 items-center justify-center rounded-xl bg-surface-hover\" aria-hidden>\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-sm font-semibold text-fg\">{title}</h2>\n {configured ? (\n <span className=\"inline-flex items-center rounded-full bg-success-soft px-2 py-0.5 text-xs font-medium text-success\">\n {ch.hubConnectedBadge}\n </span>\n ) : null}\n </div>\n <p className=\"mt-1 text-xs text-fg-muted\">{subtitle}</p>\n </div>\n </div>\n\n {!configured ? (\n <div className=\"flex shrink-0 justify-end sm:justify-end\">\n <Button type=\"button\" variant=\"primary\" className=\"shrink-0\" onClick={onConfigure}>\n {ch.hubConfigureButton}\n </Button>\n </div>\n ) : (\n <div className=\"flex shrink-0 flex-wrap items-center justify-end gap-2 sm:gap-3\">\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"size-9 shrink-0 p-0\" aria-label={ch.menuMoreAria}>\n <MoreHorizontal className=\"size-5 text-fg-muted\" strokeWidth={1.75} />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className={cn(\n 'min-w-[11rem] rounded-xl border border-edge bg-surface-panel p-1 shadow-popover dark:border-edge',\n SETTINGS_SHELL_POPOVER_Z,\n )}\n sideOffset={6}\n align=\"end\"\n >\n <DropdownMenu.Item\n className=\"cursor-pointer rounded-lg px-3 py-2 text-sm text-fg outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover\"\n onSelect={() => onEdit()}\n >\n <span className=\"flex items-center gap-2\">\n <Pencil className=\"size-4 shrink-0 text-fg-muted\" strokeWidth={1.75} />\n {ch.menuEditConfig}\n </span>\n </DropdownMenu.Item>\n <DropdownMenu.Item\n className=\"cursor-pointer rounded-lg px-3 py-2 text-sm text-danger outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover\"\n onSelect={() => onRemove()}\n >\n <span className=\"flex items-center gap-2\">\n <Trash2 className=\"size-4 shrink-0\" strokeWidth={1.75} />\n {ch.menuRemoveConfig}\n </span>\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={enabled}\n aria-label={`${title} — ${ch.enableChannelAria}`}\n disabled={toggleDisabled}\n className={cn(\n 'inline-flex h-6 w-10 shrink-0 items-center rounded-full border border-edge p-0.5 transition-colors',\n enabled ? 'justify-end bg-accent' : 'justify-start bg-surface-hover',\n toggleDisabled && 'cursor-not-allowed opacity-50',\n )}\n onClick={() => void onToggle(!enabled)}\n >\n <span className=\"size-4 rounded-full bg-surface-panel shadow-surface ring-1 ring-edge/40 dark:ring-edge/55\" />\n </button>\n </div>\n )}\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function ChannelsRemoveChannelDialog({\n open,\n onOpenChange,\n ch,\n removeTarget,\n onCancel,\n saving,\n onConfirmRemove,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n removeTarget: 'weixin' | 'telegram' | 'feishu' | 'dingtalk' | null;\n onCancel: () => void;\n saving: boolean;\n onConfirmRemove: () => void;\n}) {\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 w-[min(100%-2rem,28rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Title className=\"text-base font-semibold text-fg\">{ch.removeChannelTitle}</Dialog.Title>\n <Dialog.Description className=\"mt-2 text-sm text-fg-muted\">\n {removeTarget\n ? ch.removeChannelConfirm.replace(\n '{{name}}',\n removeTarget === 'weixin'\n ? ch.weixinTitle\n : removeTarget === 'telegram'\n ? ch.telegramTitle\n : removeTarget === 'feishu'\n ? ch.feishuTitle\n : ch.dingtalkTitle,\n )\n : '\\u00a0'}\n </Dialog.Description>\n <div className=\"mt-6 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"secondary\" onClick={onCancel}>\n {ch.modalCancel}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"border-danger/40 bg-danger text-white hover:bg-danger/90 dark:border-danger/40\"\n disabled={saving}\n onClick={onConfirmRemove}\n >\n {saving ? ch.saving : ch.removeChannelAction}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","/**\n * Merge UI channel account → agent routes into `config.bindings`.\n * Managed rules use ids `ui:route:account:<channel>:<accountId>`.\n */\n\nimport type { BindingRuleWire, ChannelAgentRoutesState } from './types/channel-bindings';\n\nexport type { BindingRuleWire, ChannelAgentRoutesState } from './types/channel-bindings';\n\nfunction normAcc(s: string | undefined): string {\n return (s ?? '').trim().toLowerCase();\n}\n\nexport function isSimpleAccountOnlyRule(r: BindingRuleWire): boolean {\n const m = r.match;\n if (!m?.channel || !m.accountId) return false;\n if (m.peerId || m.peerKind || m.guildId || m.teamId) return false;\n if (m.memberRoleIds && m.memberRoleIds.length > 0) return false;\n return true;\n}\n\n/** Telegram: `accounts` keys (token lives per account, typically `default`). */\nexport function telegramRoutingAccountIds(tg: { accounts?: Record<string, unknown> }): string[] {\n return Object.keys(tg.accounts ?? {}).sort();\n}\n\nexport function weixinRoutingAccountIds(wx: { accounts?: Record<string, unknown> }): string[] {\n return Object.keys(wx.accounts ?? {}).sort();\n}\n\nexport function feishuRoutingAccountIds(fs: { appId?: string; appSecret?: string; accounts?: Record<string, unknown> }): string[] {\n const keys = Object.keys(fs.accounts ?? {});\n if (keys.length > 0) return [...keys].sort();\n if (typeof fs.appId === 'string' && fs.appId.trim() && typeof fs.appSecret === 'string' && fs.appSecret.trim()) {\n return ['default'];\n }\n return [];\n}\n\nexport function dingtalkRoutingAccountIds(dt: {\n clientId?: string;\n clientSecret?: string;\n accounts?: Record<string, unknown>;\n}): string[] {\n const keys = Object.keys(dt.accounts ?? {});\n if (keys.length > 0) return [...keys].sort();\n if (typeof dt.clientId === 'string' && dt.clientId.trim() && typeof dt.clientSecret === 'string' && dt.clientSecret.trim()) {\n return ['default'];\n }\n return [];\n}\n\nexport function extractChannelAgentRoutes(\n bindings: BindingRuleWire[],\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: string[],\n dingtalkAccountIds: string[],\n defaultAgentId: string,\n): ChannelAgentRoutesState {\n const telegram: Record<string, string> = {};\n const weixin: Record<string, string> = {};\n const feishu: Record<string, string> = {};\n const dingtalk: Record<string, string> = {};\n\n for (const id of telegramAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'telegram' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n telegram[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n for (const id of weixinAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'weixin' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n weixin[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n for (const id of feishuAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'feishu' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n feishu[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n for (const id of dingtalkAccountIds) {\n const rule = bindings.find(\n (r) =>\n normAcc(r.match?.channel) === 'dingtalk' &&\n normAcc(r.match?.accountId) === normAcc(id) &&\n isSimpleAccountOnlyRule(r),\n );\n dingtalk[id] = (rule?.agentId ?? defaultAgentId).trim().toLowerCase();\n }\n\n return { telegram, weixin, feishu, dingtalk };\n}\n\nexport function mergeChannelAgentBindings(\n previous: BindingRuleWire[],\n routes: ChannelAgentRoutesState,\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: string[],\n dingtalkAccountIds: string[],\n defaultAgentId: string,\n): BindingRuleWire[] {\n const tgAcc = new Set(telegramAccountIds.map(normAcc));\n const wxAcc = new Set(weixinAccountIds.map(normAcc));\n const fsAcc = new Set(feishuAccountIds.map(normAcc));\n const dtAcc = new Set(dingtalkAccountIds.map(normAcc));\n\n const filtered = previous.filter((r) => {\n if (r.id?.startsWith('ui:route:account:')) return false;\n if (!isSimpleAccountOnlyRule(r)) return true;\n const ch = normAcc(r.match.channel);\n const acc = normAcc(r.match.accountId);\n if (!acc || acc === '*') return true;\n if (ch === 'telegram' && tgAcc.has(acc)) return false;\n if (ch === 'weixin' && wxAcc.has(acc)) return false;\n if (ch === 'feishu' && fsAcc.has(acc)) return false;\n if (ch === 'dingtalk' && dtAcc.has(acc)) return false;\n return true;\n });\n\n const added: BindingRuleWire[] = [];\n\n for (const acc of telegramAccountIds) {\n const agentId = (routes.telegram[acc] ?? routes.telegram[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:telegram:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'telegram', accountId: acc },\n });\n }\n\n for (const acc of weixinAccountIds) {\n const agentId = (routes.weixin[acc] ?? routes.weixin[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:weixin:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'weixin', accountId: acc },\n });\n }\n\n for (const acc of feishuAccountIds) {\n const agentId = (routes.feishu[acc] ?? routes.feishu[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:feishu:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'feishu', accountId: acc },\n });\n }\n\n for (const acc of dingtalkAccountIds) {\n const agentId = (routes.dingtalk[acc] ?? routes.dingtalk[normAcc(acc)] ?? defaultAgentId).trim().toLowerCase();\n added.push({\n id: `ui:route:account:dingtalk:${acc}`,\n agentId,\n priority: 45,\n enabled: true,\n match: { channel: 'dingtalk', accountId: acc },\n });\n }\n\n return [...filtered, ...added];\n}\n","import type { ChannelsSettingsState } from '@/features/settings/channels-config-api';\nimport { cn } from '@/lib/cn';\nimport { nativeSelectMaxWidthClass, selectControlBaseClass, settingsInputFocusClass } from '@/lib/form-field-width';\n\nexport function channelsInputClassName(): string {\n return cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n 'dark:border-edge',\n );\n}\n\nexport function channelsSelectClassName(): string {\n return cn(selectControlBaseClass, nativeSelectMaxWidthClass);\n}\n\nexport function parseIdList(raw: string): (string | number)[] {\n return raw\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean)\n .map((s) => (/^-?\\d+$/.test(s) ? Number(s) : s));\n}\n\nexport function joinAllowFrom(ids: (string | number)[]): string {\n return ids.map(String).join(', ');\n}\n\nexport function telegramDefaultBotToken(tg: ChannelsSettingsState['telegram']): string {\n const t = tg.accounts?.default?.botToken;\n return typeof t === 'string' ? t : '';\n}\n\nexport function isTelegramConfigured(tg: ChannelsSettingsState['telegram']): boolean {\n return Object.values(tg.accounts ?? {}).some(\n (a) => typeof a.botToken === 'string' && a.botToken.trim().length > 0,\n );\n}\n\nexport function isWeixinConfigured(wx: ChannelsSettingsState['weixin']): boolean {\n return Object.keys(wx.accounts ?? {}).length > 0 || wx.allowFrom.length > 0;\n}\n\nexport function isFeishuConfigured(fs: ChannelsSettingsState['feishu']): boolean {\n return Boolean(fs.appId?.trim() && fs.appSecret?.trim()) || Object.keys(fs.accounts ?? {}).length > 0;\n}\n\nexport function isDingtalkConfigured(dt: ChannelsSettingsState['dingtalk']): boolean {\n return Boolean(dt.clientId?.trim() && dt.clientSecret?.trim()) || Object.keys(dt.accounts ?? {}).length > 0;\n}\n","import type { ReactNode } from 'react';\n\nimport { channelsSelectClassName } from './utils';\n\nexport function FieldLabel({ children }: { children: ReactNode }) {\n return <div className=\"text-sm font-medium text-fg\">{children}</div>;\n}\n\nexport function FieldHint({ children }: { children: ReactNode }) {\n return <p className=\"text-xs leading-relaxed text-fg-subtle\">{children}</p>;\n}\n\ntype SelectFieldProps<T extends string> = {\n label: string;\n value: T;\n onChange: (v: T) => void;\n options: { value: T; label: string }[];\n};\n\nexport function SelectField<T extends string>({ label, value, onChange, options }: SelectFieldProps<T>) {\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{label}</FieldLabel>\n <select className={channelsSelectClassName()} value={value} onChange={(e) => onChange(e.target.value as T)}>\n {options.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import { agentListDisplayName } from '@/features/settings/agents/agent-display-names';\nimport { nativeSelectMaxWidthClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport { messages, type ChannelsSettingsMessages } from '@/i18n/messages';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName } from './utils';\n\nexport function ChannelAgentRoutingBlock({\n accountIds,\n routes,\n defaultAgentId,\n agentItems,\n disabled,\n onChange,\n ch,\n}: {\n accountIds: string[];\n routes: Record<string, string>;\n defaultAgentId: string;\n agentItems: { id: string; name?: string }[];\n disabled?: boolean;\n onChange: (accountId: string, agentId: string) => void;\n ch: ChannelsSettingsMessages;\n}) {\n const language = useLocaleStore((s) => s.language);\n const agentsMessages = messages(language).agentsSettings;\n if (accountIds.length === 0) return null;\n const opts = agentItems.length > 0 ? agentItems : [{ id: defaultAgentId }];\n return (\n <div className=\"space-y-3 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div>\n <FieldLabel>{ch.agentRoutingTitle}</FieldLabel>\n <FieldHint>{ch.agentRoutingHint}</FieldHint>\n </div>\n <div className=\"space-y-2\">\n {accountIds.map((acc) => (\n <div\n key={acc}\n className=\"grid grid-cols-1 items-start gap-2 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2.5 sm:grid-cols-2 sm:items-center dark:border-edge\"\n >\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-fg-muted\">{ch.agentRoutingAccountLabel}</p>\n <p className=\"mt-0.5 truncate font-mono text-sm text-fg\" title={acc}>\n {acc}\n </p>\n </div>\n <div className=\"min-w-0\">\n <label className=\"sr-only\" htmlFor={`agent-route-${acc}`}>\n {ch.agentRoutingAgentLabel}\n </label>\n <select\n id={`agent-route-${acc}`}\n className={cn(channelsInputClassName(), nativeSelectMaxWidthClass)}\n disabled={disabled}\n value={(routes[acc] ?? defaultAgentId).toLowerCase()}\n onChange={(e) => onChange(acc, e.target.value)}\n >\n {opts.map((ag) => (\n <option key={ag.id} value={ag.id}>\n {`${agentListDisplayName(ag, agentsMessages)} (${ag.id})`}\n </option>\n ))}\n </select>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { Check, ChevronDown, Copy, Eye, EyeOff } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { dingtalkRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport type { ChannelsSettingsState, DmPolicy, GroupPolicy } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function DingtalkMoreSettingsSection({\n ch,\n form,\n baseline,\n showDingtalkSecret,\n setShowDingtalkSecret,\n dingtalkCopied,\n copyDingtalkSecret,\n updateDingtalk,\n updateChannelAgentRoute,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n showDingtalkSecret: boolean;\n setShowDingtalkSecret: (v: boolean | ((b: boolean) => boolean)) => void;\n dingtalkCopied: boolean;\n copyDingtalkSecret: () => Promise<void>;\n updateDingtalk: (patch: Partial<ChannelsSettingsState['dingtalk']>) => void;\n updateChannelAgentRoute: (\n channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk',\n accountId: string,\n agentId: string,\n ) => void;\n dingtalkAccountsDraft: string;\n setDingtalkAccountsDraft: (v: string) => void;\n dingtalkAccountsError: string;\n onDingtalkAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const dt = form.dingtalk;\n const dingtalkBaselineSecret = baseline?.dingtalk?.clientSecret ?? '';\n const dingtalkSecretDisplayLocked =\n !showDingtalkSecret &&\n Boolean(String(dingtalkBaselineSecret).trim()) &&\n dt.clientSecret === dingtalkBaselineSecret;\n\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.dingtalkAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={dt.enabled}\n onChange={(e) => updateDingtalk({ enabled: e.target.checked })}\n />\n <span>{ch.enableDingtalkAria}</span>\n </label>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.dingtalkClientId}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={dt.clientId}\n onChange={(e) => updateDingtalk({ clientId: e.target.value })}\n placeholder=\"dingxxx\"\n />\n <FieldHint>{ch.dingtalkClientIdDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.dingtalkClientSecret}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showDingtalkSecret ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={dingtalkSecretDisplayLocked}\n value={\n dingtalkSecretDisplayLocked\n ? '*'.repeat(Math.max(1, dt.clientSecret.length))\n : dt.clientSecret\n }\n onChange={(e) => {\n if (dingtalkSecretDisplayLocked) return;\n updateDingtalk({ clientSecret: e.target.value });\n }}\n placeholder=\"••••••••\"\n />\n {dt.clientSecret ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyDingtalkSecret()}\n >\n {dingtalkCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {dingtalkCopied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowDingtalkSecret((s) => !s)}\n >\n {showDingtalkSecret ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showDingtalkSecret ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.dingtalkClientSecretDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dingtalkEndpoint}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={dt.endpoint}\n onChange={(e) => updateDingtalk({ endpoint: e.target.value })}\n placeholder=\"https://api.dingtalk.com\"\n />\n <FieldHint>{ch.dingtalkEndpointDesc}</FieldHint>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={dt.debug}\n onChange={(e) => updateDingtalk({ debug: e.target.checked })}\n />\n {ch.dingtalkDebug}\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dmPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={dt.dmPolicy}\n onChange={(e) =>\n updateDingtalk({ dmPolicy: e.target.value as ChannelsSettingsState['dingtalk']['dmPolicy'] })\n }\n >\n {dmOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.groupPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={dt.groupPolicy}\n onChange={(e) =>\n updateDingtalk({\n groupPolicy: e.target.value as ChannelsSettingsState['dingtalk']['groupPolicy'],\n })\n }\n >\n {groupOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={dt.requireMention}\n onChange={(e) => updateDingtalk({ requireMention: e.target.checked })}\n />\n {ch.requireMention}\n </label>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"userId1, userId2\"\n value={joinAllowFrom(dt.allowFrom)}\n onChange={(e) => updateDingtalk({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"openConversationId1\"\n value={joinAllowFrom(dt.groupAllowFrom)}\n onChange={(e) => updateDingtalk({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromGroupsDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(dt.historyLimit)}\n onChange={(e) => updateDingtalk({ historyLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(dt.textChunkLimit)}\n onChange={(e) => updateDingtalk({ textChunkLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={dingtalkRoutingAccountIds(dt)}\n routes={form.channelAgentRoutes.dingtalk}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('dingtalk', acc, aid)}\n ch={ch}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={dingtalkAccountsDraft}\n onChange={(e) => setDingtalkAccountsDraft(e.target.value)}\n onBlur={onDingtalkAccountsBlur}\n placeholder='{ \"default\": { \"clientId\": \"...\", \"clientSecret\": \"...\", \"enabled\": true } }'\n />\n {dingtalkAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{dingtalkAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport {\n extractChannelAgentRoutes,\n mergeChannelAgentBindings,\n dingtalkRoutingAccountIds,\n feishuRoutingAccountIds,\n telegramRoutingAccountIds,\n weixinRoutingAccountIds,\n type BindingRuleWire,\n} from './channel-bindings-merge';\nimport type {\n ChannelsSettingsState,\n DmPolicy,\n GroupPolicy,\n ReplyToMode,\n StreamMode,\n TelegramAccount,\n WeixinAccount,\n} from './channels-settings.types';\n\nexport type {\n ChannelsSettingsState,\n TelegramConfig,\n WeixinConfig,\n} from './channels-settings.types';\n\nexport type { DmPolicy, GroupPolicy, ReplyToMode, StreamMode };\n\nexport function emptyTelegramAccount(accountId: string): TelegramAccount {\n return {\n accountId,\n name: '',\n enabled: true,\n botToken: '',\n allowFrom: [],\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n replyToMode: 'off',\n apiRoot: '',\n proxy: '',\n historyLimit: 50,\n textChunkLimit: 4000,\n streamMode: 'partial',\n };\n}\n\nexport function defaultChannelsState(): ChannelsSettingsState {\n return {\n bindingsFull: [],\n channelAgentRoutes: { telegram: {}, weixin: {}, feishu: {}, dingtalk: {} },\n defaultAgentId: 'main',\n telegram: {\n enabled: false,\n apiRoot: '',\n debug: false,\n allowFrom: [],\n groupAllowFrom: [],\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n replyToMode: 'off',\n streamMode: 'partial',\n historyLimit: 50,\n textChunkLimit: 4000,\n proxy: '',\n accounts: { default: emptyTelegramAccount('default') },\n },\n weixin: {\n enabled: false,\n dmPolicy: 'pairing',\n allowFrom: [],\n debug: false,\n streamMode: 'partial',\n historyLimit: 50,\n textChunkLimit: 4000,\n routeTag: '',\n accounts: {},\n },\n feishu: {\n enabled: false,\n defaultAccount: '',\n appId: '',\n appSecret: '',\n domain: 'feishu',\n connectionMode: 'websocket',\n verificationToken: '',\n encryptKey: '',\n webhookHost: '127.0.0.1',\n webhookPort: 3000,\n webhookPath: '/feishu/events',\n dmPolicy: 'pairing',\n groupPolicy: 'allowlist',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: true,\n historyLimit: 50,\n textChunkLimit: 4000,\n renderMode: 'auto',\n streaming: false,\n reactionNotifications: 'own',\n tools: { doc: true, wiki: true, drive: true, scopes: true, bitable: true, perm: false },\n actions: { reactions: true },\n accounts: {},\n },\n dingtalk: {\n enabled: false,\n defaultAccount: '',\n clientId: '',\n clientSecret: '',\n dmPolicy: 'pairing',\n groupPolicy: 'open',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: false,\n debug: false,\n endpoint: 'https://api.dingtalk.com',\n historyLimit: 50,\n textChunkLimit: 4000,\n accounts: {},\n },\n };\n}\n\nexport function normalizeChannelsFromConfig(config: unknown): ChannelsSettingsState {\n const cfg = config && typeof config === 'object' ? (config as { channels?: unknown }).channels : undefined;\n const ch = cfg && typeof cfg === 'object' ? (cfg as Record<string, unknown>) : {};\n const tg = ch.telegram as Record<string, unknown> | undefined;\n const wx = ch.weixin as Record<string, unknown> | undefined;\n const fs = ch.feishu as Record<string, unknown> | undefined;\n const dt = ch.dingtalk as Record<string, unknown> | undefined;\n\n const telegramAccounts = tg?.accounts;\n let accounts: Record<string, TelegramAccount> =\n telegramAccounts && typeof telegramAccounts === 'object' && !Array.isArray(telegramAccounts)\n ? { ...(telegramAccounts as Record<string, TelegramAccount>) }\n : {};\n\n const legacyTopToken = typeof tg?.botToken === 'string' ? tg.botToken.trim() : '';\n const defaultTok = accounts.default?.botToken?.trim() ?? '';\n if (legacyTopToken && !defaultTok) {\n accounts = {\n ...accounts,\n default: {\n ...(accounts.default ?? emptyTelegramAccount('default')),\n accountId: 'default',\n botToken: legacyTopToken,\n },\n };\n }\n if (!accounts.default) {\n accounts = { ...accounts, default: emptyTelegramAccount('default') };\n }\n\n const weixinAccounts = wx?.accounts;\n const wxAcc: Record<string, WeixinAccount> =\n weixinAccounts && typeof weixinAccounts === 'object' && !Array.isArray(weixinAccounts)\n ? (weixinAccounts as Record<string, WeixinAccount>)\n : {};\n\n const bindingsRaw = (() => {\n const cfgObj = config && typeof config === 'object' ? (config as Record<string, unknown>) : {};\n const b = cfgObj.bindings;\n return Array.isArray(b) ? (b as BindingRuleWire[]) : [];\n })();\n\n const agents = (() => {\n const cfgObj = config && typeof config === 'object' ? (config as Record<string, unknown>) : {};\n const a = cfgObj.agents;\n return a && typeof a === 'object' ? (a as Record<string, unknown>) : {};\n })();\n const defaultAgentId =\n typeof agents.defaultId === 'string' && agents.defaultId.trim()\n ? agents.defaultId.trim().toLowerCase()\n : 'main';\n\n const base = {\n telegram: {\n enabled: Boolean(tg?.enabled),\n apiRoot: typeof tg?.apiRoot === 'string' ? tg.apiRoot : '',\n debug: Boolean(tg?.debug),\n allowFrom: Array.isArray(tg?.allowFrom) ? [...(tg.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(tg?.groupAllowFrom) ? [...(tg.groupAllowFrom as (string | number)[])] : [],\n dmPolicy: (tg?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (tg?.groupPolicy as GroupPolicy) || 'open',\n replyToMode: (tg?.replyToMode as ReplyToMode) || 'off',\n streamMode: (tg?.streamMode as StreamMode) ?? 'partial',\n historyLimit: typeof tg?.historyLimit === 'number' ? tg.historyLimit : 50,\n textChunkLimit: typeof tg?.textChunkLimit === 'number' ? tg.textChunkLimit : 4000,\n proxy: typeof tg?.proxy === 'string' ? tg.proxy : '',\n accounts: { ...accounts },\n },\n weixin: {\n enabled: Boolean(wx?.enabled),\n dmPolicy: (wx?.dmPolicy as DmPolicy) || 'pairing',\n allowFrom: Array.isArray(wx?.allowFrom) ? [...(wx.allowFrom as string[])] : [],\n debug: Boolean(wx?.debug),\n streamMode: (wx?.streamMode as StreamMode) ?? 'partial',\n historyLimit: typeof wx?.historyLimit === 'number' ? wx.historyLimit : 50,\n textChunkLimit: typeof wx?.textChunkLimit === 'number' ? wx.textChunkLimit : 4000,\n routeTag: wx?.routeTag != null ? String(wx.routeTag) : '',\n accounts: { ...wxAcc },\n },\n feishu: {\n enabled: Boolean(fs?.enabled),\n defaultAccount: typeof fs?.defaultAccount === 'string' ? fs.defaultAccount : '',\n appId: typeof fs?.appId === 'string' ? fs.appId : '',\n appSecret: typeof fs?.appSecret === 'string' ? fs.appSecret : '',\n domain: (typeof fs?.domain === 'string' && fs.domain) || 'feishu',\n connectionMode: (fs?.connectionMode as any) || 'websocket',\n verificationToken: typeof fs?.verificationToken === 'string' ? fs.verificationToken : '',\n encryptKey: typeof fs?.encryptKey === 'string' ? fs.encryptKey : '',\n webhookHost: typeof fs?.webhookHost === 'string' ? fs.webhookHost : '127.0.0.1',\n webhookPort: typeof fs?.webhookPort === 'number' ? fs.webhookPort : 3000,\n webhookPath: typeof fs?.webhookPath === 'string' ? fs.webhookPath : '/feishu/events',\n dmPolicy: (fs?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (fs?.groupPolicy as GroupPolicy) || 'allowlist',\n allowFrom: Array.isArray(fs?.allowFrom) ? [...(fs.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(fs?.groupAllowFrom) ? [...(fs.groupAllowFrom as (string | number)[])] : [],\n requireMention: fs?.requireMention === undefined ? true : Boolean(fs.requireMention),\n historyLimit: typeof fs?.historyLimit === 'number' ? fs.historyLimit : 50,\n textChunkLimit: typeof fs?.textChunkLimit === 'number' ? fs.textChunkLimit : 4000,\n renderMode: (fs?.renderMode as any) || 'auto',\n streaming: fs?.streaming === undefined ? false : Boolean(fs.streaming),\n reactionNotifications: (fs?.reactionNotifications as any) || 'own',\n tools:\n fs?.tools && typeof fs.tools === 'object' && !Array.isArray(fs.tools)\n ? ({ ...(fs.tools as Record<string, boolean>) } as any)\n : undefined,\n actions:\n fs?.actions && typeof fs.actions === 'object' && !Array.isArray(fs.actions)\n ? ({ ...(fs.actions as Record<string, boolean>) } as any)\n : undefined,\n accounts:\n fs?.accounts && typeof fs.accounts === 'object' && !Array.isArray(fs.accounts)\n ? ({ ...(fs.accounts as Record<string, any>) } as any)\n : {},\n },\n dingtalk: {\n enabled: Boolean(dt?.enabled),\n defaultAccount: typeof dt?.defaultAccount === 'string' ? dt.defaultAccount : '',\n clientId: typeof dt?.clientId === 'string' ? dt.clientId : '',\n clientSecret: typeof dt?.clientSecret === 'string' ? dt.clientSecret : '',\n dmPolicy: (dt?.dmPolicy as DmPolicy) || 'pairing',\n groupPolicy: (dt?.groupPolicy as GroupPolicy) || 'open',\n allowFrom: Array.isArray(dt?.allowFrom) ? [...(dt.allowFrom as (string | number)[])] : [],\n groupAllowFrom: Array.isArray(dt?.groupAllowFrom) ? [...(dt.groupAllowFrom as (string | number)[])] : [],\n requireMention: dt?.requireMention === true,\n debug: Boolean(dt?.debug),\n endpoint: typeof dt?.endpoint === 'string' && dt.endpoint.trim() ? dt.endpoint.trim() : 'https://api.dingtalk.com',\n historyLimit: typeof dt?.historyLimit === 'number' ? dt.historyLimit : 50,\n textChunkLimit: typeof dt?.textChunkLimit === 'number' ? dt.textChunkLimit : 4000,\n accounts:\n dt?.accounts && typeof dt.accounts === 'object' && !Array.isArray(dt.accounts)\n ? ({ ...(dt.accounts as Record<string, unknown>) } as ChannelsSettingsState['dingtalk']['accounts'])\n : {},\n },\n };\n\n const tgIds = telegramRoutingAccountIds(base.telegram);\n const wxIds = weixinRoutingAccountIds(base.weixin);\n const fsIds = feishuRoutingAccountIds(base.feishu);\n const dtIds = dingtalkRoutingAccountIds(base.dingtalk);\n const channelAgentRoutes = extractChannelAgentRoutes(bindingsRaw, tgIds, wxIds, fsIds, dtIds, defaultAgentId);\n\n return {\n ...base,\n bindingsFull: bindingsRaw.map((r) => ({ ...r })),\n channelAgentRoutes,\n defaultAgentId,\n };\n}\n\nexport async function fetchChannelsSettings(): Promise<ChannelsSettingsState> {\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'));\n const c = res.payload?.config;\n return normalizeChannelsFromConfig(c ?? {});\n}\n\nexport type WeixinGatewayQrLoginStatusPayload =\n | { phase: 'polling'; qrcodeUrl: string; qrStatus?: string }\n | { phase: 'done'; ok: true; accountId: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchWeixinGatewayQrLoginStart(body?: {\n account?: string;\n timeoutMs?: number;\n}): Promise<{ sessionKey: string; qrcodeUrl: string }> {\n const res = await fetchJson<{ ok: boolean; payload: { sessionKey: string; qrcodeUrl: string } }>(\n apiUrl('/api/channels/weixin/login/start'),\n { method: 'POST', body: JSON.stringify(body ?? {}) },\n );\n return res.payload;\n}\n\nexport async function fetchWeixinGatewayQrLoginStatus(\n sessionKey: string,\n): Promise<WeixinGatewayQrLoginStatusPayload> {\n const res = await fetchJson<{ ok: boolean; payload: { status: WeixinGatewayQrLoginStatusPayload } }>(\n apiUrl(`/api/channels/weixin/login/${encodeURIComponent(sessionKey)}`),\n );\n return res.payload.status;\n}\n\nexport async function patchChannelsSettings(state: ChannelsSettingsState): Promise<ChannelsSettingsState> {\n const tg = state.telegram;\n const wx = state.weixin;\n const fs = state.feishu;\n const dt = state.dingtalk;\n const mergedBindings = mergeChannelAgentBindings(\n state.bindingsFull,\n state.channelAgentRoutes,\n telegramRoutingAccountIds(tg),\n weixinRoutingAccountIds(wx),\n feishuRoutingAccountIds(fs),\n dingtalkRoutingAccountIds(dt),\n state.defaultAgentId,\n );\n const weixinRouteTag: string | number | null = (() => {\n const raw = wx.routeTag.trim();\n if (!raw) return null;\n return /^\\d+$/.test(raw) ? Number(raw) : raw;\n })();\n\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({\n bindings: mergedBindings,\n channels: {\n telegram: {\n enabled: tg.enabled,\n apiRoot: tg.apiRoot || undefined,\n debug: tg.debug,\n allowFrom: tg.allowFrom,\n groupAllowFrom: tg.groupAllowFrom.length ? tg.groupAllowFrom : undefined,\n dmPolicy: tg.dmPolicy,\n groupPolicy: tg.groupPolicy,\n replyToMode: tg.replyToMode,\n streamMode: tg.streamMode,\n historyLimit: tg.historyLimit,\n textChunkLimit: tg.textChunkLimit,\n proxy: tg.proxy || undefined,\n // Always send `accounts` (including `{}`) so PATCH clears stale entries instead of omitting the field.\n accounts: tg.accounts,\n },\n weixin: {\n enabled: wx.enabled,\n dmPolicy: wx.dmPolicy,\n allowFrom: wx.allowFrom,\n debug: wx.debug,\n streamMode: wx.streamMode,\n historyLimit: wx.historyLimit,\n textChunkLimit: wx.textChunkLimit,\n routeTag: weixinRouteTag,\n accounts: wx.accounts,\n },\n feishu: {\n enabled: fs.enabled,\n defaultAccount: fs.defaultAccount || undefined,\n appId: fs.appId,\n appSecret: fs.appSecret || undefined,\n domain: fs.domain || undefined,\n connectionMode: fs.connectionMode,\n verificationToken: (fs as any).verificationToken?.trim() ? (fs as any).verificationToken : undefined,\n encryptKey: (fs as any).encryptKey?.trim() ? (fs as any).encryptKey : undefined,\n webhookHost: (fs as any).webhookHost?.trim() ? (fs as any).webhookHost : undefined,\n webhookPort: typeof (fs as any).webhookPort === 'number' ? (fs as any).webhookPort : undefined,\n webhookPath: (fs as any).webhookPath?.trim() ? (fs as any).webhookPath : undefined,\n dmPolicy: fs.dmPolicy,\n groupPolicy: fs.groupPolicy,\n allowFrom: fs.allowFrom,\n groupAllowFrom: fs.groupAllowFrom.length ? fs.groupAllowFrom : undefined,\n requireMention: fs.requireMention,\n historyLimit: fs.historyLimit,\n textChunkLimit: fs.textChunkLimit,\n renderMode: fs.renderMode,\n streaming: fs.streaming,\n reactionNotifications: fs.reactionNotifications,\n tools: (fs as any).tools,\n actions: (fs as any).actions,\n accounts: fs.accounts,\n },\n dingtalk: {\n enabled: dt.enabled,\n defaultAccount: dt.defaultAccount || undefined,\n clientId: dt.clientId,\n clientSecret: dt.clientSecret || undefined,\n dmPolicy: dt.dmPolicy,\n groupPolicy: dt.groupPolicy,\n allowFrom: dt.allowFrom,\n groupAllowFrom: dt.groupAllowFrom.length ? dt.groupAllowFrom : undefined,\n requireMention: dt.requireMention,\n debug: dt.debug,\n endpoint: dt.endpoint?.trim() ? dt.endpoint : undefined,\n historyLimit: dt.historyLimit,\n textChunkLimit: dt.textChunkLimit,\n accounts: dt.accounts,\n },\n },\n }),\n });\n const c = res.payload?.config;\n void revalidateGatewayConfig();\n if (c) return normalizeChannelsFromConfig(c);\n return {\n ...state,\n bindingsFull: mergedBindings,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Feishu QR scan-to-create\n// ---------------------------------------------------------------------------\n\nexport type FeishuSetupStatusPayload =\n | { phase: 'polling' }\n | { phase: 'done'; ok: true; appId: string; domain: string; openId?: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchFeishuSetupStart(body?: {\n domain?: 'feishu' | 'lark';\n}): Promise<{ sessionKey: string; qrUrl: string }> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { sessionKey: string; qrUrl: string };\n }>(apiUrl('/api/channels/feishu/setup/start'), {\n method: 'POST',\n body: JSON.stringify(body ?? {}),\n });\n return res.payload;\n}\n\nexport async function fetchFeishuSetupStatus(sessionKey: string): Promise<FeishuSetupStatusPayload> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { status: FeishuSetupStatusPayload };\n }>(apiUrl(`/api/channels/feishu/setup/${encodeURIComponent(sessionKey)}`));\n return res.payload.status;\n}\n\n// ---------------------------------------------------------------------------\n// DingTalk QR app registration\n// ---------------------------------------------------------------------------\n\nexport type DingtalkSetupStatusPayload =\n | { phase: 'polling' }\n | { phase: 'done'; ok: true; clientId: string }\n | { phase: 'done'; ok: false; message: string }\n | { phase: 'unknown'; message: string };\n\nexport async function fetchDingtalkSetupStart(): Promise<{ sessionKey: string; qrUrl: string }> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { sessionKey: string; qrUrl: string };\n }>(apiUrl('/api/channels/dingtalk/setup/start'), {\n method: 'POST',\n body: JSON.stringify({}),\n });\n return res.payload;\n}\n\nexport async function fetchDingtalkSetupStatus(sessionKey: string): Promise<DingtalkSetupStatusPayload> {\n const res = await fetchJson<{\n ok: boolean;\n payload: { status: DingtalkSetupStatusPayload };\n }>(apiUrl(`/api/channels/dingtalk/setup/${encodeURIComponent(sessionKey)}`));\n return res.payload.status;\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchDingtalkSetupStart,\n fetchDingtalkSetupStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function DingtalkQrSetupDialog({\n open,\n onOpenChange,\n ch,\n onSetupSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onSetupSuccess: (result: { clientId: string }) => void;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const startScan = useCallback(async () => {\n setError(null);\n setSessionKey(null);\n setQrUrl(null);\n setBusy(true);\n try {\n const result = await fetchDingtalkSetupStart();\n setQrUrl(result.qrUrl);\n setSessionKey(result.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setBusy(false);\n return;\n }\n void startScan();\n }, [open, startScan]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const status = await fetchDingtalkSetupStatus(sessionKey);\n if (cancelled) return;\n\n if (status.phase === 'polling') return;\n\n if (status.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (status.ok) {\n setQrUrl(null);\n onOpenChange(false);\n onSetupSuccess({ clientId: status.clientId });\n } else {\n setError(status.message);\n setQrUrl(null);\n }\n return;\n }\n\n if (status.phase === 'unknown') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(status.message);\n setSessionKey(null);\n setQrUrl(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 3000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, onOpenChange, onSetupSuccess]);\n\n useEffect(() => {\n if (!qrUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrUrl]);\n\n const showQr = Boolean(qrUrl && sessionKey);\n /** True while waiting for a new session (first open, regenerate, or after errors). Keeps modal height stable. */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.dingtalkQrCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.dingtalkQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.dingtalkQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.dingtalkQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.dingtalkQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p className=\"text-sm text-fg-muted\">\n {qrFrameLoading ? ch.dingtalkQrStarting : ch.dingtalkQrScanHint}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.dingtalkQrEncoding}</p>\n ) : null}\n {showQr && qrUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.dingtalkQrImageError}</p>\n <a\n href={qrUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.dingtalkQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void startScan()}\n >\n {busy ? ch.dingtalkQrStarting : ch.dingtalkQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import { Check, ChevronDown, Copy, Eye, EyeOff } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { feishuRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport type { ChannelsSettingsState, DmPolicy, GroupPolicy } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function FeishuMoreSettingsSection({\n ch,\n form,\n baseline,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n feishuCopied,\n feishuWebhookCopied,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n updateFeishu,\n updateChannelAgentRoute,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n onFeishuAccountsBlur,\n dmOpts,\n groupOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n showFeishuSecret: boolean;\n setShowFeishuSecret: (v: boolean | ((b: boolean) => boolean)) => void;\n showFeishuWebhookSecrets: boolean;\n setShowFeishuWebhookSecrets: (v: boolean | ((b: boolean) => boolean)) => void;\n feishuCopied: boolean;\n feishuWebhookCopied: boolean;\n copyFeishuSecret: () => Promise<void>;\n copyFeishuWebhookConfig: () => Promise<void>;\n updateFeishu: (patch: Partial<ChannelsSettingsState['feishu']>) => void;\n updateChannelAgentRoute: (\n channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk',\n accountId: string,\n agentId: string,\n ) => void;\n feishuAccountsDraft: string;\n setFeishuAccountsDraft: (v: string) => void;\n feishuAccountsError: string;\n onFeishuAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const fs = form.feishu;\n const feishuBaselineSecret = baseline?.feishu?.appSecret ?? '';\n const feishuSecretDisplayLocked =\n !showFeishuSecret &&\n Boolean(String(feishuBaselineSecret).trim()) &&\n fs.appSecret === feishuBaselineSecret;\n\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.feishuAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={fs.enabled}\n onChange={(e) => updateFeishu({ enabled: e.target.checked })}\n />\n <span>{ch.enableFeishuAria}</span>\n </label>\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.feishuAppId}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.appId}\n onChange={(e) => updateFeishu({ appId: e.target.value })}\n placeholder=\"cli_xxx\"\n />\n <FieldHint>{ch.feishuAppIdDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.feishuAppSecret}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuSecret ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={feishuSecretDisplayLocked}\n value={\n feishuSecretDisplayLocked\n ? '*'.repeat(Math.max(1, fs.appSecret.length))\n : fs.appSecret\n }\n onChange={(e) => {\n if (feishuSecretDisplayLocked) return;\n updateFeishu({ appSecret: e.target.value });\n }}\n placeholder=\"••••••••\"\n />\n {fs.appSecret ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyFeishuSecret()}\n >\n {feishuCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {feishuCopied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowFeishuSecret((s) => !s)}\n >\n {showFeishuSecret ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showFeishuSecret ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.feishuAppSecretDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.feishuDomain}</FieldLabel>\n <select\n className={inputClassName()}\n value={String(fs.domain || 'feishu')}\n onChange={(e) => updateFeishu({ domain: e.target.value })}\n >\n <option value=\"feishu\">feishu</option>\n <option value=\"lark\">lark</option>\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.connectionMode}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.connectionMode}\n onChange={(e) =>\n updateFeishu({ connectionMode: e.target.value as ChannelsSettingsState['feishu']['connectionMode'] })\n }\n >\n <option value=\"websocket\">websocket</option>\n <option value=\"webhook\">webhook</option>\n </select>\n <FieldHint>{ch.connectionModeDesc}</FieldHint>\n </div>\n </div>\n\n {fs.connectionMode === 'webhook' ? (\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"text-sm font-medium text-fg\">{ch.webhookTitle}</div>\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowFeishuWebhookSecrets((s) => !s)}\n >\n {showFeishuWebhookSecrets ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showFeishuWebhookSecrets ? ch.hide : ch.show}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => void copyFeishuWebhookConfig()}\n >\n {feishuWebhookCopied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {feishuWebhookCopied ? ch.copied : ch.copy}\n </Button>\n </div>\n </div>\n\n <div className=\"mt-3 grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.verificationToken}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuWebhookSecrets ? 'text' : 'password'}\n autoComplete=\"off\"\n value={fs.verificationToken ?? ''}\n onChange={(e) => updateFeishu({ verificationToken: e.target.value })}\n />\n <FieldHint>{ch.verificationTokenDesc}</FieldHint>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.encryptKey}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showFeishuWebhookSecrets ? 'text' : 'password'}\n autoComplete=\"off\"\n value={fs.encryptKey ?? ''}\n onChange={(e) => updateFeishu({ encryptKey: e.target.value })}\n />\n <FieldHint>{ch.encryptKeyDesc}</FieldHint>\n </div>\n </div>\n\n <div className=\"mt-3 grid gap-3 sm:grid-cols-3\">\n <div className=\"flex flex-col gap-1.5 sm:col-span-2\">\n <FieldLabel>{ch.webhookHost}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.webhookHost ?? ''}\n onChange={(e) => updateFeishu({ webhookHost: e.target.value })}\n placeholder=\"127.0.0.1\"\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.webhookPort}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.webhookPort ?? '')}\n onChange={(e) =>\n updateFeishu({ webhookPort: Number(e.target.value || '0') || 0 })\n }\n placeholder=\"3000\"\n />\n </div>\n </div>\n\n <div className=\"mt-3 flex flex-col gap-1.5\">\n <FieldLabel>{ch.webhookPath}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n value={fs.webhookPath ?? ''}\n onChange={(e) => updateFeishu({ webhookPath: e.target.value })}\n placeholder=\"/feishu/events\"\n />\n <FieldHint>{ch.webhookPathDesc}</FieldHint>\n </div>\n </div>\n ) : null}\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.renderMode}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.renderMode}\n onChange={(e) =>\n updateFeishu({ renderMode: e.target.value as ChannelsSettingsState['feishu']['renderMode'] })\n }\n >\n <option value=\"auto\">auto</option>\n <option value=\"raw\">raw</option>\n <option value=\"card\">card</option>\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.reactionNotifications}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.reactionNotifications}\n onChange={(e) =>\n updateFeishu({\n reactionNotifications: e.target\n .value as ChannelsSettingsState['feishu']['reactionNotifications'],\n })\n }\n >\n <option value=\"off\">off</option>\n <option value=\"own\">own</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={fs.streaming}\n onChange={(e) => updateFeishu({ streaming: e.target.checked })}\n />\n {ch.enableStreaming}\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.dmPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.dmPolicy}\n onChange={(e) =>\n updateFeishu({ dmPolicy: e.target.value as ChannelsSettingsState['feishu']['dmPolicy'] })\n }\n >\n {dmOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.groupPolicy}</FieldLabel>\n <select\n className={inputClassName()}\n value={fs.groupPolicy}\n onChange={(e) =>\n updateFeishu({ groupPolicy: e.target.value as ChannelsSettingsState['feishu']['groupPolicy'] })\n }\n >\n {groupOpts.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={fs.requireMention}\n onChange={(e) => updateFeishu({ requireMention: e.target.checked })}\n />\n {ch.requireMention}\n </label>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"ou_xxx, on_xxx\"\n value={joinAllowFrom(fs.allowFrom)}\n onChange={(e) => updateFeishu({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"oc_xxx, oc_yyy\"\n value={joinAllowFrom(fs.groupAllowFrom)}\n onChange={(e) => updateFeishu({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromGroupsDesc}</FieldHint>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.historyLimit)}\n onChange={(e) => updateFeishu({ historyLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type=\"number\"\n inputMode=\"numeric\"\n value={String(fs.textChunkLimit)}\n onChange={(e) => updateFeishu({ textChunkLimit: Number(e.target.value || '0') || 0 })}\n />\n </div>\n </div>\n\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"text-sm font-medium text-fg\">{ch.feishuToolsTitle}</div>\n <div className=\"mt-2 grid gap-2 sm:grid-cols-2\">\n {(\n [\n ['doc', ch.feishuToolDoc],\n ['wiki', ch.feishuToolWiki],\n ['drive', ch.feishuToolDrive],\n ['perm', ch.feishuToolPerm],\n ['bitable', ch.feishuToolBitable],\n ['scopes', ch.feishuToolScopes],\n ] as const\n ).map(([key, label]) => (\n <label key={key} className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={Boolean(fs.tools?.[key])}\n onChange={(e) =>\n updateFeishu({\n tools: { ...fs.tools, [key]: e.target.checked },\n })\n }\n />\n {label}\n </label>\n ))}\n </div>\n <div className=\"mt-2\">\n <FieldHint>{ch.feishuToolsDesc}</FieldHint>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle\">\n <div className=\"text-sm font-medium text-fg\">{ch.feishuActionsTitle}</div>\n <label className=\"mt-2 flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={Boolean(fs.actions?.reactions)}\n onChange={(e) =>\n updateFeishu({\n actions: { ...fs.actions, reactions: e.target.checked },\n })\n }\n />\n {ch.feishuActionReactions}\n </label>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={feishuRoutingAccountIds(fs)}\n routes={form.channelAgentRoutes.feishu}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('feishu', acc, aid)}\n ch={ch}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={feishuAccountsDraft}\n onChange={(e) => setFeishuAccountsDraft(e.target.value)}\n onBlur={onFeishuAccountsBlur}\n placeholder='{ \"default\": { \"appId\": \"...\", \"appSecret\": \"...\", \"enabled\": true } }'\n />\n {feishuAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{feishuAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchFeishuSetupStart,\n fetchFeishuSetupStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\ntype FeishuDomain = 'feishu' | 'lark';\n\nexport function FeishuQrSetupDialog({\n open,\n onOpenChange,\n ch,\n onSetupSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onSetupSuccess: (result: { appId: string; domain: string; openId?: string }) => void;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [domain, setDomain] = useState<FeishuDomain>('feishu');\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const startScan = useCallback(async (d: FeishuDomain) => {\n setDomain(d);\n setError(null);\n setSessionKey(null);\n setQrUrl(null);\n setBusy(true);\n try {\n const result = await fetchFeishuSetupStart({ domain: d });\n setQrUrl(result.qrUrl);\n setSessionKey(result.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setDomain('feishu');\n setBusy(false);\n return;\n }\n void startScan('feishu');\n }, [open, startScan]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const status = await fetchFeishuSetupStatus(sessionKey);\n if (cancelled) return;\n\n if (status.phase === 'polling') return;\n\n if (status.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (status.ok) {\n setQrUrl(null);\n onOpenChange(false);\n onSetupSuccess({\n appId: status.appId,\n domain: status.domain,\n openId: status.openId,\n });\n } else {\n setError(status.message);\n setQrUrl(null);\n }\n return;\n }\n\n if (status.phase === 'unknown') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(status.message);\n setSessionKey(null);\n setQrUrl(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 3000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, onOpenChange, onSetupSuccess]);\n\n useEffect(() => {\n if (!qrUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrUrl]);\n\n const showQr = Boolean(qrUrl && sessionKey);\n /** Keep pill visible for the whole open session so region toggles do not collapse the modal. */\n const showRegionSwitch = open;\n /** True until the first QR session is ready (covers first paint before useEffect + region switches). */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.feishuQrCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.feishuQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.feishuQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.feishuQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.feishuQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? (\n <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p>\n ) : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p className=\"text-sm text-fg-muted\">\n {qrFrameLoading ? ch.feishuQrStarting : ch.feishuQrScanHint}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.feishuQrEncoding}</p>\n ) : null}\n {showQr && qrUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.feishuQrImageError}</p>\n <a\n href={qrUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.feishuQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n {showRegionSwitch ? (\n <div\n className=\"mx-auto mt-4 flex w-full max-w-[20rem] justify-center px-1\"\n role=\"group\"\n aria-label={ch.feishuRegionSwitchAria}\n >\n <div className=\"inline-flex w-full rounded-full border border-edge bg-surface-muted/60 p-1 dark:border-edge dark:bg-surface-base\">\n <button\n type=\"button\"\n disabled={busy}\n className={cn(\n 'min-w-0 flex-1 rounded-full px-3 py-2 text-center text-sm font-medium transition-colors',\n domain === 'feishu'\n ? 'bg-surface-panel text-fg shadow-sm dark:bg-surface-panel'\n : 'text-fg-muted hover:text-fg',\n )}\n onClick={() => void startScan('feishu')}\n >\n {ch.feishuRegionChina}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n className={cn(\n 'min-w-0 flex-1 rounded-full px-3 py-2 text-center text-sm font-medium transition-colors',\n domain === 'lark'\n ? 'bg-surface-panel text-fg shadow-sm dark:bg-surface-panel'\n : 'text-fg-muted hover:text-fg',\n )}\n onClick={() => void startScan('lark')}\n >\n {ch.feishuRegionInternational}\n </button>\n </div>\n </div>\n ) : null}\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void startScan(domain)}\n >\n {busy ? ch.feishuQrStarting : ch.feishuQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import type {\n ChannelsSettingsState,\n DmPolicy,\n GroupPolicy,\n ReplyToMode,\n StreamMode,\n} from '@/features/settings/channels-config-api';\nimport { cn } from '@/lib/cn';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { FieldHint, FieldLabel, SelectField } from './field-primitives';\nimport { channelsInputClassName, joinAllowFrom, parseIdList } from './utils';\n\nexport function TelegramAdvanced({\n tg,\n updateTelegram,\n ch,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n onTgAccountsBlur,\n}: {\n tg: ChannelsSettingsState['telegram'];\n updateTelegram: (p: Partial<ChannelsSettingsState['telegram']>) => void;\n ch: ChannelsSettingsMessages;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n replyOpts: { value: ReplyToMode; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n tgAccountsDraft: string;\n setTgAccountsDraft: (s: string) => void;\n tgAccountsError: string;\n onTgAccountsBlur: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n return (\n <div className=\"space-y-4 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.apiRoot}</FieldLabel>\n <input\n className={inputClassName()}\n value={tg.apiRoot}\n onChange={(e) => updateTelegram({ apiRoot: e.target.value })}\n placeholder=\"https://api.telegram.org\"\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.proxy}</FieldLabel>\n <input\n className={inputClassName()}\n value={tg.proxy}\n onChange={(e) => updateTelegram({ proxy: e.target.value })}\n placeholder=\"http://proxy.example.com:8080\"\n />\n </div>\n <SelectField label={ch.dmPolicy} value={tg.dmPolicy} onChange={(v) => updateTelegram({ dmPolicy: v })} options={dmOpts} />\n <SelectField\n label={ch.groupPolicy}\n value={tg.groupPolicy}\n onChange={(v) => updateTelegram({ groupPolicy: v })}\n options={groupOpts}\n />\n <SelectField\n label={ch.replyToMode}\n value={tg.replyToMode}\n onChange={(v) => updateTelegram({ replyToMode: v })}\n options={replyOpts}\n />\n <SelectField\n label={ch.streamMode}\n value={tg.streamMode}\n onChange={(v) => updateTelegram({ streamMode: v })}\n options={streamOpts}\n />\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromGroups}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"-1001234567890\"\n value={joinAllowFrom(tg.groupAllowFrom)}\n onChange={(e) => updateTelegram({ groupAllowFrom: parseIdList(e.target.value) })}\n />\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n type=\"number\"\n min={10}\n max={200}\n className={inputClassName()}\n value={tg.historyLimit}\n onChange={(e) => updateTelegram({ historyLimit: parseInt(e.target.value, 10) || 50 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n type=\"number\"\n min={1000}\n max={10000}\n step={100}\n className={inputClassName()}\n value={tg.textChunkLimit}\n onChange={(e) => updateTelegram({ textChunkLimit: parseInt(e.target.value, 10) || 4000 })}\n />\n </div>\n </div>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={tg.debug}\n onChange={(e) => updateTelegram({ debug: e.target.checked })}\n />\n {ch.telegramDebug}\n </label>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.multiAccountJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={tgAccountsDraft}\n onChange={(e) => setTgAccountsDraft(e.target.value)}\n onBlur={onTgAccountsBlur}\n placeholder='{ \"personal\": { \"accountId\": \"personal\", \"botToken\": \"...\", ... } }'\n />\n {tgAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{tgAccountsError}</p>\n ) : (\n <FieldHint>{ch.multiAccountJsonDesc}</FieldHint>\n )}\n </div>\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { Check, ChevronDown, Copy, Eye, EyeOff, X } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport { telegramRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport {\n emptyTelegramAccount,\n type ChannelsSettingsState,\n type DmPolicy,\n type GroupPolicy,\n type ReplyToMode,\n type StreamMode,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel } from './field-primitives';\nimport { TelegramAdvanced } from './telegram-advanced';\nimport { channelsInputClassName, joinAllowFrom, parseIdList, telegramDefaultBotToken } from './utils';\n\nexport function TelegramChannelSettingsDialog({\n open,\n onOpenChange,\n ch,\n form,\n baseline,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n copied,\n copyToken,\n updateTelegram,\n updateChannelAgentRoute,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n onTgAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n chatAgents,\n saving,\n dirty,\n save,\n discard,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n form: ChannelsSettingsState;\n baseline: ChannelsSettingsState | null;\n tgAdvanced: boolean;\n setTgAdvanced: (v: boolean | ((b: boolean) => boolean)) => void;\n showToken: boolean;\n setShowToken: (v: boolean | ((b: boolean) => boolean)) => void;\n copied: boolean;\n copyToken: () => Promise<void>;\n updateTelegram: (patch: Partial<ChannelsSettingsState['telegram']>) => void;\n updateChannelAgentRoute: (channel: 'telegram', accountId: string, agentId: string) => void;\n tgAccountsDraft: string;\n setTgAccountsDraft: (s: string) => void;\n tgAccountsError: string;\n onTgAccountsBlur: () => void;\n dmOpts: { value: DmPolicy; label: string }[];\n groupOpts: { value: GroupPolicy; label: string }[];\n replyOpts: { value: ReplyToMode; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n chatAgents: ChatAgentsPayload | undefined;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n const inputClassName = channelsInputClassName;\n const tg = form.telegram;\n const tgBaselineToken = baseline ? telegramDefaultBotToken(baseline.telegram) : '';\n const tgToken = telegramDefaultBotToken(tg);\n const telegramTokenDisplayLocked =\n !showToken && Boolean(String(tgBaselineToken).trim()) && tgToken === tgBaselineToken;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,48rem)] w-[min(100%-2rem,36rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <Dialog.Title className=\"text-lg font-semibold tracking-tight text-fg\">{ch.telegramTitle}</Dialog.Title>\n <Dialog.Description className=\"mt-1 text-sm text-fg-muted\">{ch.telegramSubtitle}</Dialog.Description>\n </div>\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.modalCancel}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n </div>\n\n <label className=\"mt-6 flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={tg.enabled}\n onChange={(e) => updateTelegram({ enabled: e.target.checked })}\n />\n <span>{ch.enableTelegramAria}</span>\n </label>\n\n <div className=\"mt-6 space-y-4\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>\n {ch.telegramToken}\n <span className=\"text-red-600 dark:text-red-400\"> *</span>\n </FieldLabel>\n <div className=\"flex flex-wrap gap-2\">\n <input\n className={cn(inputClassName(), 'min-w-0 flex-1 font-mono text-xs')}\n type={showToken ? 'text' : 'password'}\n autoComplete=\"off\"\n readOnly={telegramTokenDisplayLocked}\n value={\n telegramTokenDisplayLocked\n ? '*'.repeat(Math.max(1, tgBaselineToken.length))\n : tgToken\n }\n onChange={(e) => {\n if (telegramTokenDisplayLocked) return;\n const prev = tg.accounts?.default ?? emptyTelegramAccount('default');\n updateTelegram({\n accounts: {\n ...tg.accounts,\n default: { ...prev, accountId: 'default', botToken: e.target.value },\n },\n });\n }}\n placeholder=\"123456789:ABCdefGHIjklMNOpqrsTUVwxyz\"\n />\n {tgToken ? (\n <Button type=\"button\" variant=\"secondary\" className=\"px-2 py-1 text-xs\" onClick={() => void copyToken()}>\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? ch.copied : ch.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n onClick={() => setShowToken((s) => !s)}\n >\n {showToken ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n {showToken ? ch.hide : ch.show}\n </Button>\n </div>\n <FieldHint>{ch.telegramTokenDesc}</FieldHint>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.allowFromDm}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"123456789, 987654321\"\n value={joinAllowFrom(tg.allowFrom)}\n onChange={(e) => updateTelegram({ allowFrom: parseIdList(e.target.value) })}\n />\n <FieldHint>{ch.allowFromDmDesc}</FieldHint>\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={telegramRoutingAccountIds(tg)}\n routes={form.channelAgentRoutes.telegram}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n disabled={saving}\n onChange={(acc, aid) => updateChannelAgentRoute('telegram', acc, aid)}\n ch={ch}\n />\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"-ml-2 h-auto justify-start px-2 py-1 text-sm text-fg-muted hover:text-fg\"\n onClick={() => setTgAdvanced((a) => !a)}\n >\n <ChevronDown className={cn('mr-1 size-4 transition-transform', tgAdvanced && 'rotate-180')} />\n {tgAdvanced ? ch.advancedHide : ch.advancedShow}\n </Button>\n\n {tgAdvanced ? (\n <TelegramAdvanced\n tg={tg}\n updateTelegram={updateTelegram}\n ch={ch}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n replyOpts={replyOpts}\n streamOpts={streamOpts}\n tgAccountsDraft={tgAccountsDraft}\n setTgAccountsDraft={setTgAccountsDraft}\n tgAccountsError={tgAccountsError}\n onTgAccountsBlur={onTgAccountsBlur}\n />\n ) : null}\n </div>\n\n <div className=\"mt-8 flex flex-wrap justify-end gap-2 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">\n <Button type=\"button\" variant=\"secondary\" onClick={() => onOpenChange(false)}>\n {ch.modalCancel}\n </Button>\n <Button type=\"button\" variant=\"secondary\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n disabled={!dirty || saving}\n onClick={async () => {\n const ok = await save();\n if (ok) onOpenChange(false);\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport useSWR from 'swr';\n\nimport { fetchChatAgents } from '@/features/chat/chat-agents-api';\nimport { useGatewayConfigSwr } from '@/features/gateway/gateway-config-swr';\nimport {\n defaultChannelsState,\n normalizeChannelsFromConfig,\n patchChannelsSettings,\n type ChannelsSettingsState,\n type DmPolicy,\n type GroupPolicy,\n type ReplyToMode,\n type StreamMode,\n} from '@/features/settings/channels-config-api';\nimport { messages } from '@/i18n/messages';\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nimport { telegramDefaultBotToken } from './utils';\n\nexport function useChannelsSettingsPanel() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const ch = m.channelsSettings;\n const token = useGatewayStore((st) => st.token);\n const hasToken = Boolean(token);\n\n const [form, setForm] = useState<ChannelsSettingsState | null>(null);\n const [baseline, setBaseline] = useState<ChannelsSettingsState | null>(null);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [saveOk, setSaveOk] = useState(false);\n\n const [weixinModalOpen, setWeixinModalOpen] = useState(false);\n const [telegramModalOpen, setTelegramModalOpen] = useState(false);\n const [feishuModalOpen, setFeishuModalOpen] = useState(false);\n const [dingtalkModalOpen, setDingtalkModalOpen] = useState(false);\n const [removeTarget, setRemoveTarget] = useState<'weixin' | 'telegram' | 'feishu' | 'dingtalk' | null>(null);\n const [weixinSuccessBanner, setWeixinSuccessBanner] = useState<string | null>(null);\n const [feishuSetupSuccessBanner, setFeishuSetupSuccessBanner] = useState<string | null>(null);\n const [dingtalkSetupSuccessBanner, setDingtalkSetupSuccessBanner] = useState<string | null>(null);\n const [tgAdvanced, setTgAdvanced] = useState(false);\n const [showToken, setShowToken] = useState(false);\n const [showFeishuSecret, setShowFeishuSecret] = useState(false);\n const [showFeishuWebhookSecrets, setShowFeishuWebhookSecrets] = useState(false);\n const [showDingtalkSecret, setShowDingtalkSecret] = useState(false);\n const [copied, setCopied] = useState(false);\n const [feishuCopied, setFeishuCopied] = useState(false);\n const [dingtalkCopied, setDingtalkCopied] = useState(false);\n const [feishuWebhookCopied, setFeishuWebhookCopied] = useState(false);\n\n const [tgAccountsDraft, setTgAccountsDraft] = useState('');\n const [tgAccountsError, setTgAccountsError] = useState('');\n const [wxAccountsDraft, setWxAccountsDraft] = useState('');\n const [wxAccountsError, setWxAccountsError] = useState('');\n const [feishuAccountsDraft, setFeishuAccountsDraft] = useState('');\n const [feishuAccountsError, setFeishuAccountsError] = useState('');\n const [dingtalkAccountsDraft, setDingtalkAccountsDraft] = useState('');\n const [dingtalkAccountsError, setDingtalkAccountsError] = useState('');\n\n const { data: chatAgents } = useSWR(hasToken ? 'gateway-chat-agents-ch' : null, fetchChatAgents, {\n revalidateOnFocus: false,\n });\n\n const { data: cfgData, error: swrError, isLoading, mutate } = useGatewayConfigSwr(hasToken);\n\n const parsed = useMemo(\n () =>\n cfgData?.payload?.config !== undefined\n ? normalizeChannelsFromConfig(cfgData.payload.config)\n : null,\n [cfgData],\n );\n\n const dirty = useMemo(() => {\n if (!form || !baseline) return false;\n return JSON.stringify(form) !== JSON.stringify(baseline);\n }, [form, baseline]);\n\n useEffect(() => {\n if (!hasToken) {\n setForm(null);\n setBaseline(null);\n return;\n }\n if (parsed === null) return;\n if (!dirty) {\n setForm(parsed);\n setBaseline(structuredClone(parsed));\n setTgAccountsDraft(JSON.stringify(parsed.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(parsed.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(parsed.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(parsed.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setSaveOk(false);\n }\n }, [hasToken, parsed, dirty]);\n\n const loading = Boolean(hasToken && isLoading && cfgData === undefined && !swrError);\n const fetchError =\n swrError instanceof Error ? swrError.message : swrError ? String(swrError) : null;\n\n const updateChannelAgentRoute = useCallback(\n (channel: 'telegram' | 'weixin' | 'feishu' | 'dingtalk', accountId: string, agentId: string) => {\n setForm((f) => {\n if (!f) return null;\n const k =\n channel === 'telegram'\n ? 'telegram'\n : channel === 'weixin'\n ? 'weixin'\n : channel === 'feishu'\n ? 'feishu'\n : 'dingtalk';\n return {\n ...f,\n channelAgentRoutes: {\n ...f.channelAgentRoutes,\n [k]: { ...f.channelAgentRoutes[k], [accountId]: agentId.trim().toLowerCase() },\n },\n };\n });\n },\n [],\n );\n\n const updateTelegram = useCallback((patch: Partial<ChannelsSettingsState['telegram']>) => {\n setForm((f) => (f ? { ...f, telegram: { ...f.telegram, ...patch } } : null));\n }, []);\n\n const updateWeixin = useCallback((patch: Partial<ChannelsSettingsState['weixin']>) => {\n setForm((f) => (f ? { ...f, weixin: { ...f.weixin, ...patch } } : null));\n }, []);\n\n const updateFeishu = useCallback((patch: Partial<ChannelsSettingsState['feishu']>) => {\n setForm((f) => (f ? { ...f, feishu: { ...f.feishu, ...patch } } : null));\n }, []);\n\n const updateDingtalk = useCallback((patch: Partial<ChannelsSettingsState['dingtalk']>) => {\n setForm((f) => (f ? { ...f, dingtalk: { ...f.dingtalk, ...patch } } : null));\n }, []);\n\n const save = useCallback(async (): Promise<boolean> => {\n if (!form || saving) return false;\n setSaving(true);\n setError(null);\n setSaveOk(false);\n try {\n const next = await patchChannelsSettings(form);\n setForm(next);\n const baselineClone = structuredClone(next);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setSaveOk(true);\n window.setTimeout(() => setSaveOk(false), 2500);\n return true;\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n return false;\n } finally {\n setSaving(false);\n }\n }, [form, saving, ch.saveError]);\n\n const discard = useCallback(() => {\n if (!baseline) return;\n const b = structuredClone(baseline);\n setForm(b);\n setTgAccountsDraft(JSON.stringify(b.telegram.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsDraft(JSON.stringify(b.weixin.accounts ?? {}, null, 2));\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(b.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(b.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setError(null);\n setSaveOk(false);\n }, [baseline]);\n\n const toggleChannelEnabled = useCallback(\n async (which: 'weixin' | 'telegram' | 'feishu' | 'dingtalk', enabled: boolean) => {\n if (!form || saving) return;\n const prev = form;\n const next: ChannelsSettingsState =\n which === 'weixin'\n ? { ...form, weixin: { ...form.weixin, enabled } }\n : which === 'telegram'\n ? { ...form, telegram: { ...form.telegram, enabled } }\n : which === 'feishu'\n ? { ...form, feishu: { ...form.feishu, enabled } }\n : { ...form, dingtalk: { ...form.dingtalk, enabled } };\n setForm(next);\n setSaving(true);\n setError(null);\n try {\n const synced = await patchChannelsSettings(next);\n setForm(synced);\n const baselineClone = structuredClone(synced);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n setForm(prev);\n } finally {\n setSaving(false);\n }\n },\n [form, saving, ch.saveError],\n );\n\n const removeChannel = useCallback(async () => {\n if (!form || !removeTarget || saving) return;\n const defaults = defaultChannelsState();\n const next: ChannelsSettingsState =\n removeTarget === 'weixin'\n ? { ...form, weixin: defaults.weixin }\n : removeTarget === 'telegram'\n ? { ...form, telegram: defaults.telegram }\n : removeTarget === 'feishu'\n ? { ...form, feishu: defaults.feishu }\n : { ...form, dingtalk: defaults.dingtalk };\n setSaving(true);\n setError(null);\n try {\n const synced = await patchChannelsSettings(next);\n setForm(synced);\n const baselineClone = structuredClone(synced);\n setBaseline(baselineClone);\n setTgAccountsDraft(JSON.stringify(baselineClone.telegram.accounts ?? {}, null, 2));\n setWxAccountsDraft(JSON.stringify(baselineClone.weixin.accounts ?? {}, null, 2));\n setTgAccountsError('');\n setWxAccountsError('');\n setFeishuAccountsDraft(JSON.stringify(baselineClone.feishu?.accounts ?? {}, null, 2));\n setFeishuAccountsError('');\n setDingtalkAccountsDraft(JSON.stringify(baselineClone.dingtalk?.accounts ?? {}, null, 2));\n setDingtalkAccountsError('');\n setRemoveTarget(null);\n setSaveOk(true);\n window.setTimeout(() => setSaveOk(false), 2500);\n } catch (e) {\n setError(e instanceof Error ? e.message : ch.saveError);\n } finally {\n setSaving(false);\n }\n }, [form, removeTarget, saving, ch.saveError]);\n\n const copyToken = useCallback(async () => {\n const t = form ? telegramDefaultBotToken(form.telegram) : '';\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setCopied(true);\n window.setTimeout(() => setCopied(false), 2000);\n }, [form]);\n\n const handleFeishuQrSetupSuccess = useCallback(\n (result: { appId: string; domain: string; openId?: string }) => {\n updateFeishu({\n appId: result.appId,\n domain: result.domain,\n enabled: true,\n });\n void mutate();\n setFeishuSetupSuccessBanner(ch.feishuQrSetupSuccess);\n window.setTimeout(() => setFeishuSetupSuccessBanner(null), 4000);\n },\n [updateFeishu, mutate, ch.feishuQrSetupSuccess],\n );\n\n const handleDingtalkQrSetupSuccess = useCallback(\n (result: { clientId: string }) => {\n updateDingtalk({\n clientId: result.clientId,\n enabled: true,\n });\n void mutate();\n setDingtalkSetupSuccessBanner(ch.dingtalkQrSetupSuccess);\n window.setTimeout(() => setDingtalkSetupSuccessBanner(null), 4000);\n },\n [updateDingtalk, mutate, ch.dingtalkQrSetupSuccess],\n );\n\n const copyDingtalkSecret = useCallback(async () => {\n const t = form?.dingtalk?.clientSecret;\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setDingtalkCopied(true);\n window.setTimeout(() => setDingtalkCopied(false), 2000);\n }, [form]);\n\n const copyFeishuSecret = useCallback(async () => {\n const t = form?.feishu?.appSecret;\n if (!t) return;\n await navigator.clipboard.writeText(t).catch(() => {});\n setFeishuCopied(true);\n window.setTimeout(() => setFeishuCopied(false), 2000);\n }, [form]);\n\n const copyFeishuWebhookConfig = useCallback(async () => {\n const fs = form?.feishu;\n if (!fs) return;\n const payload = {\n connectionMode: fs.connectionMode,\n verificationToken: fs.verificationToken || '',\n encryptKey: fs.encryptKey || '',\n webhookHost: fs.webhookHost || '',\n webhookPort: fs.webhookPort || 0,\n webhookPath: fs.webhookPath || '',\n };\n await navigator.clipboard.writeText(JSON.stringify(payload, null, 2)).catch(() => {});\n setFeishuWebhookCopied(true);\n window.setTimeout(() => setFeishuWebhookCopied(false), 2000);\n }, [form]);\n\n const onTgAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = tgAccountsDraft.trim();\n if (!raw) {\n updateTelegram({ accounts: {} });\n setTgAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateTelegram({ accounts: parsedJson as ChannelsSettingsState['telegram']['accounts'] });\n setTgAccountsError('');\n } catch (err) {\n setTgAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, tgAccountsDraft, updateTelegram, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onWxAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = wxAccountsDraft.trim();\n if (!raw) {\n updateWeixin({ accounts: {} });\n setWxAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateWeixin({ accounts: parsedJson as ChannelsSettingsState['weixin']['accounts'] });\n setWxAccountsError('');\n } catch (err) {\n setWxAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, wxAccountsDraft, updateWeixin, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onFeishuAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = feishuAccountsDraft.trim();\n if (!raw) {\n updateFeishu({ accounts: {} });\n setFeishuAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateFeishu({ accounts: parsedJson as ChannelsSettingsState['feishu']['accounts'] });\n setFeishuAccountsError('');\n } catch (err) {\n setFeishuAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, feishuAccountsDraft, updateFeishu, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const onDingtalkAccountsBlur = useCallback(() => {\n if (!form) return;\n const raw = dingtalkAccountsDraft.trim();\n if (!raw) {\n updateDingtalk({ accounts: {} });\n setDingtalkAccountsError('');\n return;\n }\n try {\n const parsedJson = JSON.parse(raw) as unknown;\n if (typeof parsedJson !== 'object' || parsedJson === null || Array.isArray(parsedJson)) {\n throw new Error(ch.jsonObjectAccounts);\n }\n updateDingtalk({ accounts: parsedJson as ChannelsSettingsState['dingtalk']['accounts'] });\n setDingtalkAccountsError('');\n } catch (err) {\n setDingtalkAccountsError(err instanceof Error ? err.message : ch.jsonInvalid);\n }\n }, [form, dingtalkAccountsDraft, updateDingtalk, ch.jsonObjectAccounts, ch.jsonInvalid]);\n\n const dmOpts = useMemo(\n () =>\n (['pairing', 'allowlist', 'open', 'disabled'] as DmPolicy[]).map((value) => ({\n value,\n label: ch.policy.dm[value],\n })),\n [ch.policy.dm],\n );\n\n const groupOpts = useMemo(\n () =>\n (['open', 'disabled', 'allowlist'] as GroupPolicy[]).map((value) => ({\n value,\n label: ch.policy.group[value],\n })),\n [ch.policy.group],\n );\n\n const replyOpts = useMemo(\n () =>\n (['off', 'first', 'all'] as ReplyToMode[]).map((value) => ({\n value,\n label: ch.policy.reply[value],\n })),\n [ch.policy.reply],\n );\n\n const streamOpts = useMemo(\n () =>\n (['off', 'partial', 'block'] as StreamMode[]).map((value) => ({\n value,\n label: ch.policy.stream[value],\n })),\n [ch.policy.stream],\n );\n\n return {\n language,\n m,\n ch,\n hasToken,\n loading,\n fetchError,\n mutate,\n form,\n baseline,\n dirty,\n saving,\n error,\n saveOk,\n weixinModalOpen,\n setWeixinModalOpen,\n telegramModalOpen,\n setTelegramModalOpen,\n feishuModalOpen,\n setFeishuModalOpen,\n dingtalkModalOpen,\n setDingtalkModalOpen,\n removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n feishuSetupSuccessBanner,\n dingtalkSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n showDingtalkSecret,\n setShowDingtalkSecret,\n copied,\n feishuCopied,\n dingtalkCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n updateDingtalk,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n handleDingtalkQrSetupSuccess,\n copyFeishuSecret,\n copyDingtalkSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n };\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ExternalLink, X } from 'lucide-react';\nimport QRCode from 'qrcode';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n fetchWeixinGatewayQrLoginStart,\n fetchWeixinGatewayQrLoginStatus,\n} from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { SETTINGS_SHELL_CONTENT_Z, SETTINGS_SHELL_OVERLAY_Z } from '@/lib/settings-shell-dialog-layer';\n\nexport function WeixinQrLoginDialog({\n open,\n onOpenChange,\n ch,\n onLoginSuccess,\n moreSettings,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n ch: ChannelsSettingsMessages;\n onLoginSuccess: () => void | Promise<void>;\n moreSettings?: ReactNode;\n}) {\n const [busy, setBusy] = useState(false);\n const [sessionKey, setSessionKey] = useState<string | null>(null);\n const [qrcodeUrl, setQrcodeUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [hint, setHint] = useState<string | null>(null);\n const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);\n const [qrGenFailed, setQrGenFailed] = useState(false);\n\n const start = useCallback(async () => {\n setError(null);\n setHint(null);\n setSessionKey(null);\n setBusy(true);\n try {\n const r = await fetchWeixinGatewayQrLoginStart();\n setQrcodeUrl(r.qrcodeUrl);\n setSessionKey(r.sessionKey);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Start failed');\n } finally {\n setBusy(false);\n }\n }, []);\n\n useEffect(() => {\n if (!open) {\n setSessionKey(null);\n setQrcodeUrl(null);\n setError(null);\n setQrDataUrl(null);\n setQrGenFailed(false);\n setHint(null);\n return;\n }\n void start();\n }, [open, start]);\n\n useEffect(() => {\n if (!sessionKey) return;\n let cancelled = false;\n let intervalId: number | undefined;\n\n const poll = async () => {\n try {\n const st = await fetchWeixinGatewayQrLoginStatus(sessionKey);\n if (cancelled) return;\n if (st.phase === 'polling') {\n setQrcodeUrl(st.qrcodeUrl);\n if (st.qrStatus === 'scaned') {\n setHint(ch.weixinQrLoginScanned);\n } else {\n setHint(null);\n }\n return;\n }\n if (st.phase === 'done') {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n intervalId = undefined;\n }\n setSessionKey(null);\n if (st.ok) {\n setQrcodeUrl(null);\n onOpenChange(false);\n await onLoginSuccess();\n } else {\n setError(st.message);\n setQrcodeUrl(null);\n }\n return;\n }\n if (st.phase === 'unknown') {\n setHint(null);\n }\n } catch (e) {\n if (!cancelled) {\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n setError(e instanceof Error ? e.message : 'Request failed');\n setSessionKey(null);\n setQrcodeUrl(null);\n }\n }\n };\n\n intervalId = window.setInterval(() => void poll(), 2000);\n void poll();\n return () => {\n cancelled = true;\n if (intervalId !== undefined) {\n window.clearInterval(intervalId);\n }\n };\n }, [sessionKey, ch.weixinQrLoginScanned, ch.weixinQrLoginSuccess, onLoginSuccess, onOpenChange]);\n\n useEffect(() => {\n if (!qrcodeUrl) {\n setQrDataUrl(null);\n setQrGenFailed(false);\n return;\n }\n let cancelled = false;\n setQrGenFailed(false);\n void QRCode.toDataURL(qrcodeUrl, {\n width: 208,\n margin: 2,\n errorCorrectionLevel: 'M',\n color: { dark: '#000000ff', light: '#ffffffff' },\n })\n .then((url) => {\n if (!cancelled) setQrDataUrl(url);\n })\n .catch(() => {\n if (!cancelled) {\n setQrGenFailed(true);\n setQrDataUrl(null);\n }\n });\n return () => {\n cancelled = true;\n };\n }, [qrcodeUrl]);\n\n const showQr = Boolean(qrcodeUrl && sessionKey);\n /** True while waiting for a new login session (first open, regenerate). Keeps modal height stable. */\n const qrFrameLoading = open && !error && !showQr;\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay\n className={cn(\n 'xopc-dialog-overlay fixed inset-0 bg-scrim backdrop-blur-[1px]',\n SETTINGS_SHELL_OVERLAY_Z,\n )}\n />\n <Dialog.Content\n className={cn(\n 'fixed left-1/2 top-1/2 max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2',\n SETTINGS_SHELL_CONTENT_Z,\n 'overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge',\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Dialog.Close asChild>\n <button\n type=\"button\"\n className=\"absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n aria-label={ch.weixinQrModalCloseAria}\n >\n <X className=\"size-4\" />\n </button>\n </Dialog.Close>\n\n <Dialog.Title className=\"sr-only\">{ch.weixinQrModalTitle}</Dialog.Title>\n <Dialog.Description className=\"sr-only\">{ch.weixinQrModalSubtitle}</Dialog.Description>\n\n <div className=\"text-center\">\n <p className=\"text-lg font-semibold tracking-tight text-fg\">{ch.weixinQrModalTitle}</p>\n <p className=\"mt-1.5 text-sm text-fg-muted\">{ch.weixinQrModalSubtitle}</p>\n </div>\n\n <div className=\"mt-6 flex min-h-[17.5rem] flex-col items-center justify-center gap-3\">\n {error ? <p className=\"text-center text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n\n {!error && (showQr || qrFrameLoading) ? (\n <div className=\"flex w-full flex-col items-center gap-3\">\n <p\n className={cn(\n 'min-h-[1.25rem] text-center text-sm',\n hint && !qrFrameLoading ? 'text-accent' : 'text-fg-muted',\n )}\n >\n {qrFrameLoading ? ch.weixinQrLoginBusy : hint ?? '\\u00a0'}\n </p>\n <div\n className={cn(\n 'relative flex h-52 w-52 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-edge-subtle bg-white p-3 dark:border-edge',\n qrFrameLoading && 'bg-surface-muted/40 dark:bg-surface-base',\n )}\n >\n {qrFrameLoading ? (\n <div\n className=\"absolute inset-3 animate-pulse rounded-md bg-surface-muted dark:bg-surface-hover\"\n aria-hidden\n />\n ) : null}\n {showQr && qrcodeUrl && !error && qrDataUrl && !qrGenFailed ? (\n <img src={qrDataUrl} alt=\"\" className=\"relative z-[1] size-full object-contain\" />\n ) : null}\n {showQr && qrcodeUrl && !error && !qrDataUrl && !qrGenFailed && !qrFrameLoading ? (\n <p className=\"relative z-[1] px-2 text-center text-sm text-fg-muted\">{ch.weixinQrEncoding}</p>\n ) : null}\n {showQr && qrcodeUrl && !error && qrGenFailed ? (\n <div className=\"relative z-[1] flex size-full flex-col items-center justify-center gap-2 px-1\">\n <p className=\"text-center text-xs text-fg-muted\">{ch.weixinQrImageError}</p>\n <a\n href={qrcodeUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent underline-offset-2 hover:underline\"\n >\n <ExternalLink className=\"size-3 shrink-0\" />\n {ch.weixinQrOpenLink}\n </a>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n\n <div className=\"mt-6\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel\"\n disabled={busy}\n onClick={() => void start()}\n >\n {busy ? ch.weixinQrLoginBusy : ch.weixinQrRegenerate}\n </Button>\n </div>\n\n {moreSettings ? (\n <div className=\"mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle\">{moreSettings}</div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import type { ChannelsSettingsState, DmPolicy, StreamMode } from '@/features/settings/channels-config-api';\nimport { weixinRoutingAccountIds } from '@/features/settings/channel-bindings-merge';\nimport { cn } from '@/lib/cn';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { ChannelAgentRoutingBlock } from './channel-agent-routing-block';\nimport { FieldHint, FieldLabel, SelectField } from './field-primitives';\nimport { channelsInputClassName } from './utils';\n\nexport function WeixinAdvanced({\n wx,\n updateWeixin,\n ch,\n dmOpts,\n streamOpts,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n onWxAccountsBlur,\n channelAgentRoutesWx,\n defaultAgentId,\n agentItems,\n onAgentRouteChange,\n routingDisabled,\n}: {\n wx: ChannelsSettingsState['weixin'];\n updateWeixin: (p: Partial<ChannelsSettingsState['weixin']>) => void;\n ch: ChannelsSettingsMessages;\n dmOpts: { value: DmPolicy; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n wxAccountsDraft: string;\n setWxAccountsDraft: (s: string) => void;\n wxAccountsError: string;\n onWxAccountsBlur: () => void;\n channelAgentRoutesWx: Record<string, string>;\n defaultAgentId: string;\n agentItems: { id: string; name?: string }[];\n onAgentRouteChange: (accountId: string, agentId: string) => void;\n routingDisabled: boolean;\n}) {\n const inputClassName = channelsInputClassName;\n return (\n <div className=\"space-y-4 border-t border-edge-subtle pt-4 dark:border-edge\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinAllowFrom}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[2.75rem] resize-y font-mono text-xs')}\n rows={2}\n placeholder=\"wxid_..., openid_...\"\n value={wx.allowFrom.join(', ')}\n onChange={(e) =>\n updateWeixin({\n allowFrom: e.target.value\n .split(/[,\\n]/)\n .map((s) => s.trim())\n .filter(Boolean),\n })\n }\n />\n <FieldHint>{ch.weixinAllowFromDesc}</FieldHint>\n </div>\n <SelectField label={ch.dmPolicy} value={wx.dmPolicy} onChange={(v) => updateWeixin({ dmPolicy: v })} options={dmOpts} />\n <SelectField\n label={ch.streamMode}\n value={wx.streamMode}\n onChange={(v) => updateWeixin({ streamMode: v })}\n options={streamOpts}\n />\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.historyLimit}</FieldLabel>\n <input\n type=\"number\"\n min={10}\n max={200}\n className={inputClassName()}\n value={wx.historyLimit}\n onChange={(e) => updateWeixin({ historyLimit: parseInt(e.target.value, 10) || 50 })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.textChunkLimit}</FieldLabel>\n <input\n type=\"number\"\n min={1000}\n max={10000}\n step={100}\n className={inputClassName()}\n value={wx.textChunkLimit}\n onChange={(e) => updateWeixin({ textChunkLimit: parseInt(e.target.value, 10) || 4000 })}\n />\n </div>\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinRouteTag}</FieldLabel>\n <input\n className={inputClassName()}\n value={wx.routeTag}\n onChange={(e) => updateWeixin({ routeTag: e.target.value })}\n placeholder={ch.routeTagPlaceholder}\n />\n <FieldHint>{ch.weixinRouteTagDesc}</FieldHint>\n </div>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox\"\n checked={wx.debug}\n onChange={(e) => updateWeixin({ debug: e.target.checked })}\n />\n {ch.weixinDebug}\n </label>\n <FieldHint>{ch.weixinDebugDesc}</FieldHint>\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel>{ch.weixinAccountsJson}</FieldLabel>\n <textarea\n className={cn(inputClassName(), 'min-h-[140px] resize-y font-mono text-xs')}\n spellCheck={false}\n value={wxAccountsDraft}\n onChange={(e) => setWxAccountsDraft(e.target.value)}\n onBlur={onWxAccountsBlur}\n placeholder='{ \"personal\": { \"name\": \"...\", \"cdnBaseUrl\": \"...\", \"enabled\": true } }'\n />\n {wxAccountsError ? (\n <p className=\"text-xs text-red-600 dark:text-red-400\">{wxAccountsError}</p>\n ) : (\n <FieldHint>{ch.weixinAccountsJsonDesc}</FieldHint>\n )}\n </div>\n\n <ChannelAgentRoutingBlock\n accountIds={weixinRoutingAccountIds(wx)}\n routes={channelAgentRoutesWx}\n defaultAgentId={defaultAgentId}\n agentItems={agentItems}\n disabled={routingDisabled}\n onChange={onAgentRouteChange}\n ch={ch}\n />\n </div>\n );\n}\n","import { ChevronDown } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport type { ChatAgentsPayload } from '@/features/chat/chat-agents-api';\nimport type { ChannelsSettingsState, DmPolicy, StreamMode } from '@/features/settings/channels-config-api';\nimport type { ChannelsSettingsMessages } from '@/i18n/messages';\n\nimport { WeixinAdvanced } from './weixin-advanced';\n\nexport function WeixinMoreSettingsSection({\n ch,\n wx,\n updateWeixin,\n dmOpts,\n streamOpts,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n onWxAccountsBlur,\n form,\n chatAgents,\n onAgentRouteChange,\n saving,\n dirty,\n save,\n discard,\n}: {\n ch: ChannelsSettingsMessages;\n wx: ChannelsSettingsState['weixin'];\n updateWeixin: (patch: Partial<ChannelsSettingsState['weixin']>) => void;\n dmOpts: { value: DmPolicy; label: string }[];\n streamOpts: { value: StreamMode; label: string }[];\n wxAccountsDraft: string;\n setWxAccountsDraft: (v: string) => void;\n wxAccountsError: string;\n onWxAccountsBlur: () => void;\n form: ChannelsSettingsState;\n chatAgents: ChatAgentsPayload | undefined;\n onAgentRouteChange: (accountId: string, agentId: string) => void;\n saving: boolean;\n dirty: boolean;\n save: () => Promise<boolean>;\n discard: () => void;\n}) {\n return (\n <details className=\"group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge\">\n <summary className=\"cursor-pointer list-none rounded-xl px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover group-open:rounded-b-none [&::-webkit-details-marker]:hidden\">\n <span className=\"inline-flex items-center gap-2\">\n <ChevronDown className=\"size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180\" />\n {ch.advancedShow}\n </span>\n </summary>\n <div className=\"space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle\">\n <p className=\"text-xs leading-relaxed text-fg-muted\">{ch.weixinAdvancedHint}</p>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm text-fg\">\n <input\n type=\"checkbox\"\n className=\"ui-checkbox mt-0.5\"\n checked={wx.enabled}\n onChange={(e) => updateWeixin({ enabled: e.target.checked })}\n />\n <span>{ch.enableWeixinAria}</span>\n </label>\n <div className=\"[&>div]:border-0 [&>div]:pt-0\">\n <WeixinAdvanced\n wx={wx}\n updateWeixin={updateWeixin}\n ch={ch}\n dmOpts={dmOpts}\n streamOpts={streamOpts}\n wxAccountsDraft={wxAccountsDraft}\n setWxAccountsDraft={setWxAccountsDraft}\n wxAccountsError={wxAccountsError}\n onWxAccountsBlur={onWxAccountsBlur}\n channelAgentRoutesWx={form.channelAgentRoutes.weixin}\n defaultAgentId={form.defaultAgentId}\n agentItems={chatAgents?.items ?? []}\n onAgentRouteChange={onAgentRouteChange}\n routingDisabled={saving}\n />\n </div>\n <div className=\"flex flex-col gap-2 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" className=\"w-full sm:w-auto\" disabled={!dirty || saving} onClick={discard}>\n {ch.discard}\n </Button>\n <Button\n type=\"button\"\n variant=\"primary\"\n className=\"w-full sm:w-auto\"\n disabled={!dirty || saving}\n onClick={async () => {\n await save();\n }}\n >\n {saving ? ch.saving : ch.save}\n </Button>\n </div>\n </div>\n </details>\n );\n}\n","import { ExternalLink, MessageCircle, MessageSquare, Send } from 'lucide-react';\n\nimport { Button } from '@/components/ui/button';\nimport { docsGuidePageUrl } from '@/navigation';\n\nimport { ChannelImHubCard } from './channel-im-hub-card';\nimport { ChannelsRemoveChannelDialog } from './channels-remove-channel-dialog';\nimport { DingtalkMoreSettingsSection } from './dingtalk-more-settings-section';\nimport { DingtalkQrSetupDialog } from './dingtalk-qr-setup-dialog';\nimport { FeishuMoreSettingsSection } from './feishu-more-settings-section';\nimport { FeishuQrSetupDialog } from './feishu-qr-setup-dialog';\nimport { TelegramChannelSettingsDialog } from './telegram-channel-settings-dialog';\nimport { useChannelsSettingsPanel } from './use-channels-settings-panel';\nimport { WeixinQrLoginDialog } from './weixin-qr-login-dialog';\nimport { WeixinMoreSettingsSection } from './weixin-more-settings-section';\nimport { isDingtalkConfigured, isFeishuConfigured, isTelegramConfigured, isWeixinConfigured } from './utils';\n\nexport function ChannelsSettingsPanel() {\n const ctx = useChannelsSettingsPanel();\n const {\n language,\n m,\n ch,\n hasToken,\n loading,\n fetchError,\n mutate,\n form,\n baseline,\n dirty,\n saving,\n error,\n saveOk,\n weixinModalOpen,\n setWeixinModalOpen,\n telegramModalOpen,\n setTelegramModalOpen,\n feishuModalOpen,\n setFeishuModalOpen,\n removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n dingtalkModalOpen,\n setDingtalkModalOpen,\n feishuSetupSuccessBanner,\n dingtalkSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n showDingtalkSecret,\n setShowDingtalkSecret,\n copied,\n feishuCopied,\n dingtalkCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n dingtalkAccountsDraft,\n setDingtalkAccountsDraft,\n dingtalkAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n updateDingtalk,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n handleDingtalkQrSetupSuccess,\n copyFeishuSecret,\n copyDingtalkSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\n onDingtalkAccountsBlur,\n dmOpts,\n groupOpts,\n replyOpts,\n streamOpts,\n } = ctx;\n\n if (!hasToken) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <h1 className=\"text-lg font-semibold text-fg\">{m.settingsSections.channels}</h1>\n <p className=\"text-sm text-fg-muted\">{ch.needToken}</p>\n </div>\n );\n }\n\n if (loading) {\n return (\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <div className=\"h-8 w-48 animate-pulse rounded bg-surface-hover\" />\n <div className=\"mt-6 h-32 animate-pulse rounded-xl bg-surface-hover\" />\n <p className=\"mt-4 text-sm text-fg-muted\">{ch.loading}</p>\n </div>\n );\n }\n\n if (!form) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8\">\n <p className=\"text-sm text-fg-muted\">{error ?? fetchError ?? ch.loadError}</p>\n <Button type=\"button\" variant=\"secondary\" onClick={() => void mutate()}>\n {ch.retry}\n </Button>\n </div>\n );\n }\n\n const wx = form.weixin;\n const tg = form.telegram;\n const fs = form.feishu;\n const dt = form.dingtalk;\n const weixinConfigured = isWeixinConfigured(wx);\n const telegramConfigured = isTelegramConfigured(tg);\n const feishuConfigured = isFeishuConfigured(fs);\n const dingtalkConfigured = isDingtalkConfigured(dt);\n\n const feishuMoreSettings = (\n <FeishuMoreSettingsSection\n ch={ch}\n form={form}\n baseline={baseline}\n showFeishuSecret={showFeishuSecret}\n setShowFeishuSecret={setShowFeishuSecret}\n showFeishuWebhookSecrets={showFeishuWebhookSecrets}\n setShowFeishuWebhookSecrets={setShowFeishuWebhookSecrets}\n feishuCopied={feishuCopied}\n feishuWebhookCopied={feishuWebhookCopied}\n copyFeishuSecret={copyFeishuSecret}\n copyFeishuWebhookConfig={copyFeishuWebhookConfig}\n updateFeishu={updateFeishu}\n updateChannelAgentRoute={updateChannelAgentRoute}\n feishuAccountsDraft={feishuAccountsDraft}\n setFeishuAccountsDraft={setFeishuAccountsDraft}\n feishuAccountsError={feishuAccountsError}\n onFeishuAccountsBlur={onFeishuAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n const dingtalkMoreSettings = (\n <DingtalkMoreSettingsSection\n ch={ch}\n form={form}\n baseline={baseline}\n showDingtalkSecret={showDingtalkSecret}\n setShowDingtalkSecret={setShowDingtalkSecret}\n dingtalkCopied={dingtalkCopied}\n copyDingtalkSecret={copyDingtalkSecret}\n updateDingtalk={updateDingtalk}\n updateChannelAgentRoute={updateChannelAgentRoute}\n dingtalkAccountsDraft={dingtalkAccountsDraft}\n setDingtalkAccountsDraft={setDingtalkAccountsDraft}\n dingtalkAccountsError={dingtalkAccountsError}\n onDingtalkAccountsBlur={onDingtalkAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n const weixinMoreSettings = (\n <WeixinMoreSettingsSection\n ch={ch}\n wx={wx}\n updateWeixin={updateWeixin}\n dmOpts={dmOpts}\n streamOpts={streamOpts}\n wxAccountsDraft={wxAccountsDraft}\n setWxAccountsDraft={setWxAccountsDraft}\n wxAccountsError={wxAccountsError}\n onWxAccountsBlur={onWxAccountsBlur}\n form={form}\n chatAgents={chatAgents}\n onAgentRouteChange={(acc, aid) => updateChannelAgentRoute('weixin', acc, aid)}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n );\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6\">\n <header className=\"flex flex-col gap-1\">\n <h1 className=\"text-lg font-semibold tracking-tight text-fg\">{m.settingsSections.channels}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{ch.subtitle}</p>\n <a\n href={docsGuidePageUrl(language, 'channels')}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-1 inline-flex items-center gap-1 text-sm text-accent hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40\"\n >\n {ch.docsLink}\n <ExternalLink className=\"size-3.5\" />\n </a>\n </header>\n\n {dirty ? <p className=\"text-xs text-amber-800 dark:text-amber-200\">{ch.unsavedHint}</p> : null}\n {saveOk ? <p className=\"text-xs text-fg-muted\">{ch.saved}</p> : null}\n {error ? <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p> : null}\n {weixinSuccessBanner ? <p className=\"text-xs text-accent\">{weixinSuccessBanner}</p> : null}\n {feishuSetupSuccessBanner ? (\n <div className=\"rounded-xl border border-success/30 bg-success-soft px-4 py-3 text-sm text-success\">\n {feishuSetupSuccessBanner}\n </div>\n ) : null}\n {dingtalkSetupSuccessBanner ? (\n <div className=\"rounded-xl border border-success/30 bg-success-soft px-4 py-3 text-sm text-success\">\n {dingtalkSetupSuccessBanner}\n </div>\n ) : null}\n\n <div className=\"flex flex-col gap-3\">\n <ChannelImHubCard\n icon={<MessageSquare className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.weixinTitle}\n subtitle={ch.weixinSubtitle}\n configured={weixinConfigured}\n enabled={wx.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('weixin', next)}\n onConfigure={() => setWeixinModalOpen(true)}\n onEdit={() => setWeixinModalOpen(true)}\n onRemove={() => setRemoveTarget('weixin')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<Send className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.telegramTitle}\n subtitle={ch.telegramSubtitle}\n configured={telegramConfigured}\n enabled={tg.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('telegram', next)}\n onConfigure={() => setTelegramModalOpen(true)}\n onEdit={() => setTelegramModalOpen(true)}\n onRemove={() => setRemoveTarget('telegram')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<MessageSquare className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.feishuTitle}\n subtitle={ch.feishuSubtitle}\n configured={feishuConfigured}\n enabled={fs.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('feishu', next)}\n onConfigure={() => setFeishuModalOpen(true)}\n onEdit={() => setFeishuModalOpen(true)}\n onRemove={() => setRemoveTarget('feishu')}\n ch={ch}\n />\n <ChannelImHubCard\n icon={<MessageCircle className=\"size-6 text-accent\" strokeWidth={1.75} />}\n title={ch.dingtalkTitle}\n subtitle={ch.dingtalkSubtitle}\n configured={dingtalkConfigured}\n enabled={dt.enabled}\n toggleDisabled={saving}\n onToggle={(next) => void toggleChannelEnabled('dingtalk', next)}\n onConfigure={() => setDingtalkModalOpen(true)}\n onEdit={() => setDingtalkModalOpen(true)}\n onRemove={() => setRemoveTarget('dingtalk')}\n ch={ch}\n />\n </div>\n\n <WeixinQrLoginDialog\n open={weixinModalOpen}\n onOpenChange={setWeixinModalOpen}\n ch={ch}\n onLoginSuccess={async () => {\n await mutate();\n setWeixinSuccessBanner(ch.weixinQrLoginSuccess);\n window.setTimeout(() => setWeixinSuccessBanner(null), 4000);\n }}\n moreSettings={weixinMoreSettings}\n />\n\n <TelegramChannelSettingsDialog\n open={telegramModalOpen}\n onOpenChange={setTelegramModalOpen}\n ch={ch}\n form={form}\n baseline={baseline}\n tgAdvanced={tgAdvanced}\n setTgAdvanced={setTgAdvanced}\n showToken={showToken}\n setShowToken={setShowToken}\n copied={copied}\n copyToken={copyToken}\n updateTelegram={updateTelegram}\n updateChannelAgentRoute={updateChannelAgentRoute}\n tgAccountsDraft={tgAccountsDraft}\n setTgAccountsDraft={setTgAccountsDraft}\n tgAccountsError={tgAccountsError}\n onTgAccountsBlur={onTgAccountsBlur}\n dmOpts={dmOpts}\n groupOpts={groupOpts}\n replyOpts={replyOpts}\n streamOpts={streamOpts}\n chatAgents={chatAgents}\n saving={saving}\n dirty={dirty}\n save={save}\n discard={discard}\n />\n\n <FeishuQrSetupDialog\n open={feishuModalOpen}\n onOpenChange={setFeishuModalOpen}\n ch={ch}\n onSetupSuccess={handleFeishuQrSetupSuccess}\n moreSettings={feishuMoreSettings}\n />\n\n <DingtalkQrSetupDialog\n open={dingtalkModalOpen}\n onOpenChange={setDingtalkModalOpen}\n ch={ch}\n onSetupSuccess={handleDingtalkQrSetupSuccess}\n moreSettings={dingtalkMoreSettings}\n />\n\n <ChannelsRemoveChannelDialog\n open={removeTarget !== null}\n onOpenChange={(o) => {\n if (!o) setRemoveTarget(null);\n }}\n ch={ch}\n removeTarget={removeTarget}\n onCancel={() => setRemoveTarget(null)}\n saving={saving}\n onConfirmRemove={() => void removeChannel()}\n />\n </div>\n );\n}\n"],"mappings":"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"}