@xopcai/xopc 0.0.58 → 0.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/gateway/static/root/assets/{agents-kfTaZM98.js → agents-BgeuYTaG.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-kfTaZM98.js.map → agents-BgeuYTaG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-DD4Y41az.js → apps-page-DXOoxQ3t.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-DD4Y41az.js.map → apps-page-DXOoxQ3t.js.map} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-CzQhBqZZ.js → channels-settings-BtblELP8.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-CzQhBqZZ.js.map → channels-settings-BtblELP8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-dreaming-jobs-Bw0WqucT.js → cron-dreaming-jobs-D5kvbjSY.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-dreaming-jobs-Bw0WqucT.js.map → cron-dreaming-jobs-D5kvbjSY.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-DzdhjVlI.js → cron-page-4hk422N-.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-DzdhjVlI.js.map → cron-page-4hk422N-.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-CwfwOj0f.js → dist-CEmPWsYK.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-CwfwOj0f.js.map → dist-CEmPWsYK.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-6MugjoYl.js → extension-debug-page-z0vfOyIu.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-6MugjoYl.js.map → extension-debug-page-z0vfOyIu.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DG6W4O_G.js → extension-page-CFaT0yHk.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-DG6W4O_G.js.map → extension-page-CFaT0yHk.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DmmeUN--.js → extension-settings-page-7atlEJU0.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-DmmeUN--.js.map → extension-settings-page-7atlEJU0.js.map} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BzwYrxvL.js → heartbeat-config-api-DnmmSrTx.js} +2 -2
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BzwYrxvL.js.map → heartbeat-config-api-DnmmSrTx.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-BDiwAtHo.js → index-DvMI6Vqn.js} +4 -4
- package/dist/gateway/static/root/assets/{index-BDiwAtHo.js.map → index-DvMI6Vqn.js.map} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-BaOXC1YZ.js → logs-page-XKXcjB3g.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-BaOXC1YZ.js.map → logs-page-XKXcjB3g.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-C_VA9TOA.js → sessions-page-1DyACBG7.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-C_VA9TOA.js.map → sessions-page-1DyACBG7.js.map} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DMjZKSwv.js → settings-page-TrmEN1eQ.js} +2 -2
- package/dist/gateway/static/root/assets/{settings-page-DMjZKSwv.js.map → settings-page-TrmEN1eQ.js.map} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-vObv6AB7.js → skills-page-Dcvjtm-1.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-vObv6AB7.js.map → skills-page-Dcvjtm-1.js.map} +1 -1
- package/dist/gateway/static/root/assets/{use-image-provider-credentials-CoM2HUB_.js → use-image-provider-credentials-D6TXcMU2.js} +2 -2
- package/dist/gateway/static/root/assets/{use-image-provider-credentials-CoM2HUB_.js.map → use-image-provider-credentials-D6TXcMU2.js.map} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +6 -6
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/embedded/run-turn.js +6 -2
- package/dist/src/agent/embedded/run-turn.js.map +1 -1
- package/dist/src/agent/embedded/xopc-auth-storage.d.ts +9 -0
- package/dist/src/agent/embedded/xopc-auth-storage.js +13 -1
- package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
- package/dist/src/agent/embedded/xopc-stream-bridge.d.ts +11 -0
- package/dist/src/agent/embedded/xopc-stream-bridge.js +24 -0
- package/dist/src/agent/embedded/xopc-stream-bridge.js.map +1 -0
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/image/load-image-media.js +1 -1
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/service.js +5 -5
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +1 -1
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/auth/credentials.js +3 -3
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +4 -4
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/utils/init-workspace.js +2 -2
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/profile.js +2 -2
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.js +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/hono/lib/extension-store.js +1 -1
- package/dist/src/gateway/hono/lib/static-ui.js +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config.js +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +3 -3
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/lock.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.js +2 -2
- package/dist/src/gateway/service.js +5 -5
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +2 -2
- package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
- package/dist/src/session/parity/sessions-json-file.js +1 -1
- package/dist/src/session/parity/transcript-file-lock.js +2 -2
- package/dist/src/session/parity/transcript-paths.js +1 -1
- package/dist/src/session/search-index-cache.js +1 -1
- package/dist/src/session/search-index.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +4 -4
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels-settings-CzQhBqZZ.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/feishu-more-settings-section.tsx","../../../../../web/src/features/settings/channels-config-api.ts","../../../../../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' | 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 : ch.feishuTitle,\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 extractChannelAgentRoutes(\n bindings: BindingRuleWire[],\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: 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\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 return { telegram, weixin, feishu };\n}\n\nexport function mergeChannelAgentBindings(\n previous: BindingRuleWire[],\n routes: ChannelAgentRoutesState,\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: 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\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 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 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","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 { 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',\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 { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport {\n extractChannelAgentRoutes,\n mergeChannelAgentBindings,\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: {} },\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: 'open',\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: 'open',\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 };\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\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) || 'open',\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) || 'open',\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 };\n\n const tgIds = telegramRoutingAccountIds(base.telegram);\n const wxIds = weixinRoutingAccountIds(base.weixin);\n const fsIds = feishuRoutingAccountIds(base.feishu);\n const channelAgentRoutes = extractChannelAgentRoutes(bindingsRaw, tgIds, wxIds, fsIds, 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 mergedBindings = mergeChannelAgentBindings(\n state.bindingsFull,\n state.channelAgentRoutes,\n telegramRoutingAccountIds(tg),\n weixinRoutingAccountIds(wx),\n feishuRoutingAccountIds(fs),\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 },\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","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 [removeTarget, setRemoveTarget] = useState<'weixin' | 'telegram' | 'feishu' | null>(null);\n const [weixinSuccessBanner, setWeixinSuccessBanner] = useState<string | null>(null);\n const [feishuSetupSuccessBanner, setFeishuSetupSuccessBanner] = 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 [copied, setCopied] = useState(false);\n const [feishuCopied, setFeishuCopied] = 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\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 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', accountId: string, agentId: string) => {\n setForm((f) => {\n if (!f) return null;\n const k = channel === 'telegram' ? 'telegram' : channel === 'weixin' ? 'weixin' : 'feishu';\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 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 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 setError(null);\n setSaveOk(false);\n }, [baseline]);\n\n const toggleChannelEnabled = useCallback(\n async (which: 'weixin' | 'telegram' | 'feishu', 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 : { ...form, feishu: { ...form.feishu, 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 } 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 : { ...form, feishu: defaults.feishu };\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 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 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 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 removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n feishuSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n copied,\n feishuCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\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, 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 { 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 { 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 feishuSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n copied,\n feishuCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\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 weixinConfigured = isWeixinConfigured(wx);\n const telegramConfigured = isTelegramConfigured(tg);\n const feishuConfigured = isFeishuConfigured(fs);\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 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\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 </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 <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-BtblELP8.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/feishu-more-settings-section.tsx","../../../../../web/src/features/settings/channels-config-api.ts","../../../../../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' | 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 : ch.feishuTitle,\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 extractChannelAgentRoutes(\n bindings: BindingRuleWire[],\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: 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\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 return { telegram, weixin, feishu };\n}\n\nexport function mergeChannelAgentBindings(\n previous: BindingRuleWire[],\n routes: ChannelAgentRoutesState,\n telegramAccountIds: string[],\n weixinAccountIds: string[],\n feishuAccountIds: 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\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 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 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","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 { 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',\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 { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport {\n extractChannelAgentRoutes,\n mergeChannelAgentBindings,\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: {} },\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: 'open',\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: 'open',\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 };\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\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) || 'open',\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) || 'open',\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 };\n\n const tgIds = telegramRoutingAccountIds(base.telegram);\n const wxIds = weixinRoutingAccountIds(base.weixin);\n const fsIds = feishuRoutingAccountIds(base.feishu);\n const channelAgentRoutes = extractChannelAgentRoutes(bindingsRaw, tgIds, wxIds, fsIds, 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 mergedBindings = mergeChannelAgentBindings(\n state.bindingsFull,\n state.channelAgentRoutes,\n telegramRoutingAccountIds(tg),\n weixinRoutingAccountIds(wx),\n feishuRoutingAccountIds(fs),\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 },\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","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 [removeTarget, setRemoveTarget] = useState<'weixin' | 'telegram' | 'feishu' | null>(null);\n const [weixinSuccessBanner, setWeixinSuccessBanner] = useState<string | null>(null);\n const [feishuSetupSuccessBanner, setFeishuSetupSuccessBanner] = 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 [copied, setCopied] = useState(false);\n const [feishuCopied, setFeishuCopied] = 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\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 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', accountId: string, agentId: string) => {\n setForm((f) => {\n if (!f) return null;\n const k = channel === 'telegram' ? 'telegram' : channel === 'weixin' ? 'weixin' : 'feishu';\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 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 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 setError(null);\n setSaveOk(false);\n }, [baseline]);\n\n const toggleChannelEnabled = useCallback(\n async (which: 'weixin' | 'telegram' | 'feishu', 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 : { ...form, feishu: { ...form.feishu, 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 } 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 : { ...form, feishu: defaults.feishu };\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 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 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 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 removeTarget,\n setRemoveTarget,\n weixinSuccessBanner,\n setWeixinSuccessBanner,\n feishuSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n copied,\n feishuCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\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, 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 { 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 { 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 feishuSetupSuccessBanner,\n tgAdvanced,\n setTgAdvanced,\n showToken,\n setShowToken,\n showFeishuSecret,\n setShowFeishuSecret,\n showFeishuWebhookSecrets,\n setShowFeishuWebhookSecrets,\n copied,\n feishuCopied,\n feishuWebhookCopied,\n tgAccountsDraft,\n setTgAccountsDraft,\n tgAccountsError,\n wxAccountsDraft,\n setWxAccountsDraft,\n wxAccountsError,\n feishuAccountsDraft,\n setFeishuAccountsDraft,\n feishuAccountsError,\n chatAgents,\n updateChannelAgentRoute,\n updateTelegram,\n updateWeixin,\n updateFeishu,\n save,\n discard,\n toggleChannelEnabled,\n removeChannel,\n copyToken,\n handleFeishuQrSetupSuccess,\n copyFeishuSecret,\n copyFeishuWebhookConfig,\n onTgAccountsBlur,\n onWxAccountsBlur,\n onFeishuAccountsBlur,\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 weixinConfigured = isWeixinConfigured(wx);\n const telegramConfigured = isTelegramConfigured(tg);\n const feishuConfigured = isFeishuConfigured(fs);\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 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\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 </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 <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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"}
|