@hualinge/relay-web 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/dist/assets/AgentsPage-2u2kFBCH.js +68 -0
- package/dist/assets/AgentsPage-2u2kFBCH.js.map +1 -0
- package/dist/assets/AgentsPage-BGbbVmeL.css +1 -0
- package/dist/assets/Alert-D88Fk6to.js +2 -0
- package/dist/assets/Alert-D88Fk6to.js.map +1 -0
- package/dist/assets/AppModal-BYZTSuch.js +2 -0
- package/dist/assets/AppModal-BYZTSuch.js.map +1 -0
- package/dist/assets/CenteredLoadingState-DHor-9vF.js +2 -0
- package/dist/assets/CenteredLoadingState-DHor-9vF.js.map +1 -0
- package/dist/assets/ChannelsPage-CbI0kqkd.js +2 -0
- package/dist/assets/ChannelsPage-CbI0kqkd.js.map +1 -0
- package/dist/assets/EmptyDataState-6mNx2Xhl.js +2 -0
- package/dist/assets/EmptyDataState-6mNx2Xhl.js.map +1 -0
- package/dist/assets/HelpPrompt-BPzDcC8F.js +2 -0
- package/dist/assets/HelpPrompt-BPzDcC8F.js.map +1 -0
- package/dist/assets/HomePage-t78sDDUj.js +2 -0
- package/dist/assets/HomePage-t78sDDUj.js.map +1 -0
- package/dist/assets/InspirationPage-BTqLpcHY.js +3 -0
- package/dist/assets/InspirationPage-BTqLpcHY.js.map +1 -0
- package/dist/assets/ModelsPage-YF0gpUxy.js +2 -0
- package/dist/assets/ModelsPage-YF0gpUxy.js.map +1 -0
- package/dist/assets/NameInitialIcon-DP-6_HQY.js +7 -0
- package/dist/assets/NameInitialIcon-DP-6_HQY.js.map +1 -0
- package/dist/assets/NoSearchResultsState-BiiYdZ_Z.js +2 -0
- package/dist/assets/NoSearchResultsState-BiiYdZ_Z.js.map +1 -0
- package/dist/assets/OverflowTooltip-CE5PjAb-.js +2 -0
- package/dist/assets/OverflowTooltip-CE5PjAb-.js.map +1 -0
- package/dist/assets/PasswordField-DmzjtnCg.js +2 -0
- package/dist/assets/PasswordField-DmzjtnCg.js.map +1 -0
- package/dist/assets/RefreshButton-BzYzeo5A.js +2 -0
- package/dist/assets/RefreshButton-BzYzeo5A.js.map +1 -0
- package/dist/assets/RightContentHeader-DoNDQ9Lo.js +3 -0
- package/dist/assets/RightContentHeader-DoNDQ9Lo.js.map +1 -0
- package/dist/assets/SchedulePage-CfW6lZVI.js +2 -0
- package/dist/assets/SchedulePage-CfW6lZVI.js.map +1 -0
- package/dist/assets/SearchInput-tux8xXH1.js +2 -0
- package/dist/assets/SearchInput-tux8xXH1.js.map +1 -0
- package/dist/assets/SkillAvatar-DwGvsY4f.js +2 -0
- package/dist/assets/SkillAvatar-DwGvsY4f.js.map +1 -0
- package/dist/assets/SkillsPage-ppqwKMvj.js +2 -0
- package/dist/assets/SkillsPage-ppqwKMvj.js.map +1 -0
- package/dist/assets/SkillsTab-c_As1DIr.css +1 -0
- package/dist/assets/SkillsTab-kY7MNdxy.js +2 -0
- package/dist/assets/SkillsTab-kY7MNdxy.js.map +1 -0
- package/dist/assets/Tab-FE0F2EQP.js +2 -0
- package/dist/assets/Tab-FE0F2EQP.js.map +1 -0
- package/dist/assets/ThreadPage-B0jElW5R.js +53 -0
- package/dist/assets/ThreadPage-B0jElW5R.js.map +1 -0
- package/dist/assets/UploadSkillModal-DHZL12vm.js +8 -0
- package/dist/assets/UploadSkillModal-DHZL12vm.js.map +1 -0
- package/dist/assets/XlsxDocumentPreview-BY-ht09K.js +5 -0
- package/dist/assets/XlsxDocumentPreview-BY-ht09K.js.map +1 -0
- package/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +2 -0
- package/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js.map +1 -0
- package/dist/assets/chat-input-options-CpkOtPgQ.js +2 -0
- package/dist/assets/chat-input-options-CpkOtPgQ.js.map +1 -0
- package/dist/assets/docx-preview-zfB-orwa.js +28 -0
- package/dist/assets/docx-preview-zfB-orwa.js.map +1 -0
- package/dist/assets/exceljs.min-BY7KKJsM.js +58 -0
- package/dist/assets/exceljs.min-BY7KKJsM.js.map +1 -0
- package/dist/assets/helpers-CCilgpNy.js +2 -0
- package/dist/assets/helpers-CCilgpNy.js.map +1 -0
- package/dist/assets/hub-agent-editor.client-2DmCRGuY.js +2 -0
- package/dist/assets/hub-agent-editor.client-2DmCRGuY.js.map +1 -0
- package/dist/assets/hub-agent-editor.payload-D4sgJRSH.js +4 -0
- package/dist/assets/hub-agent-editor.payload-D4sgJRSH.js.map +1 -0
- package/dist/assets/hub-tag-editor-BBdd-aHK.js +2 -0
- package/dist/assets/hub-tag-editor-BBdd-aHK.js.map +1 -0
- package/dist/assets/index-Bed0I5IL.css +1 -0
- package/dist/assets/index-Bxf2_cvh.js +2 -0
- package/dist/assets/index-Bxf2_cvh.js.map +1 -0
- package/dist/assets/index-Cb4fQgom.js +103 -0
- package/dist/assets/index-Cb4fQgom.js.map +1 -0
- package/dist/assets/index-DQ2vVjmV.js +30 -0
- package/dist/assets/index-DQ2vVjmV.js.map +1 -0
- package/dist/assets/index-UBJEdbMO.js +2 -0
- package/dist/assets/index-UBJEdbMO.js.map +1 -0
- package/dist/assets/jszip.min-DPdj3o0t.js +13 -0
- package/dist/assets/jszip.min-DPdj3o0t.js.map +1 -0
- package/dist/assets/quick-actions-DzZE-zyP.js +2 -0
- package/dist/assets/quick-actions-DzZE-zyP.js.map +1 -0
- package/dist/assets/skill-options-cache-D1BJGTCU.js +2 -0
- package/dist/assets/skill-options-cache-D1BJGTCU.js.map +1 -0
- package/dist/assets/status-helpers-BILdm2MI.js +2 -0
- package/dist/assets/status-helpers-BILdm2MI.js.map +1 -0
- package/dist/assets/thread-title-Cerb2mHa.js +2 -0
- package/dist/assets/thread-title-Cerb2mHa.js.map +1 -0
- package/dist/assets/thread-utils-Ct3yp4R3.js +2 -0
- package/dist/assets/thread-utils-Ct3yp4R3.js.map +1 -0
- package/dist/assets/useAgentData-D-k9cXfg.js +2 -0
- package/dist/assets/useAgentData-D-k9cXfg.js.map +1 -0
- package/dist/assets/useEscapeKey-CEQ6-8GR.js +2 -0
- package/dist/assets/useEscapeKey-CEQ6-8GR.js.map +1 -0
- package/dist/assets/useExpertCatalog-BZdw1CYs.js +2 -0
- package/dist/assets/useExpertCatalog-BZdw1CYs.js.map +1 -0
- package/dist/assets/usePromptBlocks-5sz8Qh51.js +2 -0
- package/dist/assets/usePromptBlocks-5sz8Qh51.js.map +1 -0
- package/dist/assets/useSocket-YigidotN.css +1 -0
- package/dist/assets/useSocket-y3-zWhVL.js +11 -0
- package/dist/assets/useSocket-y3-zWhVL.js.map +1 -0
- package/dist/assets/utils--_pbLpCq.js +2 -0
- package/dist/assets/utils--_pbLpCq.js.map +1 -0
- package/dist/assets/vad-web-C_R267y1.js +2 -0
- package/dist/assets/vad-web-C_R267y1.js.map +1 -0
- package/dist/avatars/agent-avatar-1.png +0 -0
- package/dist/avatars/agent-avatar-2.png +0 -0
- package/dist/avatars/agent-avatar-3.png +0 -0
- package/dist/avatars/agent-avatar-4.png +0 -0
- package/dist/avatars/agent-avatar-5.png +0 -0
- package/dist/avatars/agent-avatar-6.png +0 -0
- package/dist/avatars/agent-avatar-7.png +0 -0
- package/dist/avatars/agent-avatar-8.png +0 -0
- package/dist/avatars/agent-avatar-9.png +0 -0
- package/dist/avatars/agentteams.png +0 -0
- package/dist/avatars/antig-opus.png +0 -0
- package/dist/avatars/antigravity.png +0 -0
- package/dist/avatars/assistant.svg +17 -0
- package/dist/avatars/codex-kawaii.png +0 -0
- package/dist/avatars/codex.png +0 -0
- package/dist/avatars/codex_box.png +0 -0
- package/dist/avatars/codex_iquid.png +0 -0
- package/dist/avatars/dare.png +0 -0
- package/dist/avatars/gemini-kawaii.png +0 -0
- package/dist/avatars/gemini.png +0 -0
- package/dist/avatars/gemini25.png +0 -0
- package/dist/avatars/gpt52.png +0 -0
- package/dist/avatars/jiuwenclaw.png +0 -0
- package/dist/avatars/office.svg +17 -0
- package/dist/avatars/opencode.png +0 -0
- package/dist/avatars/opus-45.png +0 -0
- package/dist/avatars/opus-kawaii.png +0 -0
- package/dist/avatars/opus.png +0 -0
- package/dist/avatars/sonnet.png +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/icons/arrow-left.svg +3 -0
- package/dist/icons/arrow-right.svg +3 -0
- package/dist/icons/attach.svg +9 -0
- package/dist/icons/chart/dislike.svg +3 -0
- package/dist/icons/chart/disliked.svg +3 -0
- package/dist/icons/chart/folder.svg +15 -0
- package/dist/icons/chart/home-loading.webp +0 -0
- package/dist/icons/chart/like.svg +3 -0
- package/dist/icons/chart/liked.svg +5 -0
- package/dist/icons/chart/loading.svg +26 -0
- package/dist/icons/chart/success.svg +7 -0
- package/dist/icons/check-line.svg +3 -0
- package/dist/icons/chevron-left.svg +3 -0
- package/dist/icons/chevron-right.svg +3 -0
- package/dist/icons/collapse.svg +14 -0
- package/dist/icons/common-delete.svg +4 -0
- package/dist/icons/common-folder.svg +4 -0
- package/dist/icons/copy.svg +4 -0
- package/dist/icons/cross-line.svg +4 -0
- package/dist/icons/data-analysis.svg +7 -0
- package/dist/icons/data-visualization.svg +10 -0
- package/dist/icons/deep-research.svg +4 -0
- package/dist/icons/document-processing.svg +5 -0
- package/dist/icons/edit.svg +4 -0
- package/dist/icons/expand.svg +6 -0
- package/dist/icons/expert-debate.svg +4 -0
- package/dist/icons/eye.svg +4 -0
- package/dist/icons/favicon.svg +7 -0
- package/dist/icons/file-docx.svg +60 -0
- package/dist/icons/file-folder.svg +4 -0
- package/dist/icons/file-gitignore.svg +35 -0
- package/dist/icons/file-html.svg +6 -0
- package/dist/icons/file-ini.svg +63 -0
- package/dist/icons/file-json.svg +4 -0
- package/dist/icons/file-md.svg +68 -0
- package/dist/icons/file-py.svg +4 -0
- package/dist/icons/file-sh.svg +7 -0
- package/dist/icons/file-txt.svg +37 -0
- package/dist/icons/file-zip.svg +21 -0
- package/dist/icons/file.svg +4 -0
- package/dist/icons/files-csv.svg +14 -0
- package/dist/icons/files-docx.svg +10 -0
- package/dist/icons/files-pdf.svg +14 -0
- package/dist/icons/files-ppt.svg +14 -0
- package/dist/icons/files-txt.svg +16 -0
- package/dist/icons/files-xlsx.svg +14 -0
- package/dist/icons/financial-services.svg +8 -0
- package/dist/icons/flie-html.svg +60 -0
- package/dist/icons/guided-mode.svg +9 -0
- package/dist/icons/icon-192x192.png +0 -0
- package/dist/icons/icon-512x512.png +0 -0
- package/dist/icons/icon-arrow-down.svg +4 -0
- package/dist/icons/icon-arrow-up.svg +4 -0
- package/dist/icons/icon-clear-all.svg +3 -0
- package/dist/icons/icon-close.svg +4 -0
- package/dist/icons/icon-code.svg +38 -0
- package/dist/icons/icon-drag-file.svg +26 -0
- package/dist/icons/icon-help.svg +4 -0
- package/dist/icons/icon-md.svg +53 -0
- package/dist/icons/icon-refresh.svg +4 -0
- package/dist/icons/icon-toggle.svg +6 -0
- package/dist/icons/icon-top.svg +7 -0
- package/dist/icons/icon-upload.svg +5 -0
- package/dist/icons/information.svg +6 -0
- package/dist/icons/inspiration/icon-excel.svg +14 -0
- package/dist/icons/inspiration/icon-inspiration.svg +5 -0
- package/dist/icons/inspiration/icon-markdown.svg +12 -0
- package/dist/icons/inspiration/icon-word.svg +10 -0
- package/dist/icons/link.svg +6 -0
- package/dist/icons/lock.svg +4 -0
- package/dist/icons/menu/agents.svg +39 -0
- package/dist/icons/menu/channels.svg +4 -0
- package/dist/icons/menu/icon-inspiration.svg +5 -0
- package/dist/icons/menu/models.svg +4 -0
- package/dist/icons/menu/new-chat.svg +59 -0
- package/dist/icons/menu/schedule.svg +4 -0
- package/dist/icons/menu/skills.svg +4 -0
- package/dist/icons/message-error.svg +6 -0
- package/dist/icons/message-prompt.svg +9 -0
- package/dist/icons/message-success.svg +6 -0
- package/dist/icons/message-warn.svg +8 -0
- package/dist/icons/more-trigger.svg +4 -0
- package/dist/icons/nss/1.svg +14 -0
- package/dist/icons/nss/2.svg +14 -0
- package/dist/icons/nss/3.svg +14 -0
- package/dist/icons/outline.svg +6 -0
- package/dist/icons/query_the_optical_power_border.svg +99 -0
- package/dist/icons/schedule.svg +4 -0
- package/dist/icons/settings-feedback/feedback-bug.svg +20 -0
- package/dist/icons/settings-feedback/feedback-file.svg +4 -0
- package/dist/icons/settings-feedback/feedback-idea.svg +14 -0
- package/dist/icons/settings-feedback/settings-gear.svg +4 -0
- package/dist/icons/settings-feedback/settings-link.svg +4 -0
- package/dist/icons/settings-feedback/settings-memory.svg +7 -0
- package/dist/icons/settings-feedback/settings-privacy.svg +37 -0
- package/dist/icons/settings-feedback/settings-search.svg +2 -0
- package/dist/icons/slides.svg +4 -0
- package/dist/icons/status/info-error.svg +9 -0
- package/dist/icons/style-template.svg +11 -0
- package/dist/icons/tool-error.svg +4 -0
- package/dist/icons/userprofile/help.svg +5 -0
- package/dist/icons/userprofile/keep-awake.svg +4 -0
- package/dist/icons/userprofile/question.svg +4 -0
- package/dist/icons/userprofile/security.svg +7 -0
- package/dist/icons/userprofile/style-template.svg +11 -0
- package/dist/icons/userprofile/theme.svg +14 -0
- package/dist/icons/userprofile/usage.svg +4 -0
- package/dist/icons/userprofile/version.svg +85 -0
- package/dist/icons/video-generation.svg +4 -0
- package/dist/images/OfficeClaw.svg +21 -0
- package/dist/images/add.svg +4 -0
- package/dist/images/agent-management-icons/agent-check.svg +23 -0
- package/dist/images/agent-management-icons/agent-close.svg +4 -0
- package/dist/images/agent-management-icons/agent-collab.svg +4 -0
- package/dist/images/agent-management-icons/agent-delete.svg +18 -0
- package/dist/images/agent-management-icons/agent-edit.svg +18 -0
- package/dist/images/agent-management-icons/agent-more.svg +4 -0
- package/dist/images/agent-management-icons/agent-persona.svg +4 -0
- package/dist/images/agent-management-icons/agent-random-avatar.svg +39 -0
- package/dist/images/agent-management-icons/agent-refresh.svg +4 -0
- package/dist/images/agent-management-icons/agent-skills.svg +4 -0
- package/dist/images/agent-management-icons/agent-template.svg +12 -0
- package/dist/images/agent-management-icons/anchor-current.svg +5 -0
- package/dist/images/agent-management-icons/anchor-other.svg +4 -0
- package/dist/images/chat-empty-agent.svg +12 -0
- package/dist/images/chat-empty-im.svg +14 -0
- package/dist/images/connectors/dingtalk.png +0 -0
- package/dist/images/connectors/dingtalk.svg +18 -0
- package/dist/images/connectors/feishu.png +0 -0
- package/dist/images/connectors/feishu.svg +12 -0
- package/dist/images/connectors/imessage.png +0 -0
- package/dist/images/connectors/wecom-agent.png +0 -0
- package/dist/images/connectors/wecom-bot.png +0 -0
- package/dist/images/connectors/weixin.png +0 -0
- package/dist/images/connectors/weixin.svg +19 -0
- package/dist/images/connectors/xiaoyi.png +0 -0
- package/dist/images/connectors/xiaoyi.svg +12 -0
- package/dist/images/create-agent-random-avatar.svg +39 -0
- package/dist/images/deepseek.svg +1 -0
- package/dist/images/default-ppt-template.png +0 -0
- package/dist/images/file-browser-tree/code.svg +60 -0
- package/dist/images/file-browser-tree/gitignore.svg +35 -0
- package/dist/images/file-browser-tree/image.svg +12 -0
- package/dist/images/file-browser-tree/markdown.svg +68 -0
- package/dist/images/file-browser-tree/pdf.svg +4 -0
- package/dist/images/file-browser-tree/ppt.svg +4 -0
- package/dist/images/file-browser-tree/public-file.svg +37 -0
- package/dist/images/file-browser-tree/word.svg +60 -0
- package/dist/images/file-browser-tree/xlsx.svg +4 -0
- package/dist/images/html-preview-toolbar/copy.svg +4 -0
- package/dist/images/html-preview-toolbar/open-external.svg +4 -0
- package/dist/images/html-preview-toolbar/refresh.svg +4 -0
- package/dist/images/information.svg +4 -0
- package/dist/images/inspiration/blue-bg.png +0 -0
- package/dist/images/inspiration/doc-example.png +0 -0
- package/dist/images/inspiration/excel-example.png +0 -0
- package/dist/images/inspiration/green-bg.png +0 -0
- package/dist/images/inspiration/markdown-example.png +0 -0
- package/dist/images/inspiration/orange-bg.png +0 -0
- package/dist/images/inspiration/purple-bg.png +0 -0
- package/dist/images/inspiration/task-bg.png +0 -0
- package/dist/images/inspiration-bg.png +0 -0
- package/dist/images/inspiration-products/default.svg +11 -0
- package/dist/images/invitation-background-4x.png +0 -0
- package/dist/images/kimi.svg +1 -0
- package/dist/images/link-blue.svg +4 -0
- package/dist/images/link.svg +4 -0
- package/dist/images/lobster.svg +118 -0
- package/dist/images/login1.svg +93 -0
- package/dist/images/login2.svg +80 -0
- package/dist/images/login3.svg +44 -0
- package/dist/images/login4.svg +18 -0
- package/dist/images/mode-default-icon.svg +22 -0
- package/dist/images/no-data.svg +26 -0
- package/dist/images/no-search-results.svg +25 -0
- package/dist/images/ppt-preview/placeholder-main.webp +0 -0
- package/dist/images/ppt-preview/placeholder-thumb.webp +0 -0
- package/dist/images/ppt-template/dark-tech.png +0 -0
- package/dist/images/ppt-template/huawei.png +0 -0
- package/dist/images/ppt-template/light-tech.png +0 -0
- package/dist/images/ppt-template/paper-humanities.png +0 -0
- package/dist/images/ppt-template/template-default.png +0 -0
- package/dist/images/ppt-template/template-error.png +0 -0
- package/dist/images/ppt-template/template-generate-bg.svg +9639 -0
- package/dist/images/qwen.svg +1 -0
- package/dist/images/task-list/empty-state.svg +4 -0
- package/dist/images/task-list.svg +1 -0
- package/dist/images/vendor.svg +4 -0
- package/dist/images/version-bg.svg +85 -0
- package/dist/images/version.svg +9 -0
- package/dist/images/zhipu.svg +1 -0
- package/dist/index.html +74 -0
- package/dist/loading-point-style.webp +0 -0
- package/dist/loading-small.webp +0 -0
- package/dist/manifest.json +25 -0
- package/package.json +126 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._skillGrid_1sdgq_7{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}._skillCard_1sdgq_13{display:flex;align-items:center;height:74px;padding:16px 24px;border-radius:12px;border:1px solid rgba(194,194,194,1);background:#fff}._cardIcon_1sdgq_23{flex-shrink:0;margin-right:12px}._cardContent_1sdgq_28{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}._cardName_1sdgq_36{font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._cardDescription_1sdgq_45{font-size:12px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._emptyState_1sdgq_53{font-size:14px;color:var(--text-muted)}._backdrop_1qwya_8{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;display:flex;justify-content:flex-end;background:var(--overlay-backdrop-strong);animation:_fadeIn_1qwya_1 .2s ease-out forwards}._drawer_1qwya_19{position:absolute;right:0;top:var(--content-header-height, 36px);height:calc(100% - var(--content-header-height, 36px));width:700px;display:flex;flex-direction:column;border-left:1px solid var(--modal-border);background:var(--modal-surface);box-shadow:var(--modal-shadow);animation:_slideInRight_1qwya_1 .3s ease-out forwards}._header_1qwya_34{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--panel-divider);flex-shrink:0}._title_1qwya_43{font-size:18px;font-weight:700;color:var(--modal-title-text);margin:0}._closeButton_1qwya_50{display:inline-flex;height:1.5rem;width:1.5rem;align-items:center;justify-content:center;border-radius:.25rem;color:var(--modal-close-icon);transition:background-color .2s ease,color .2s ease;background:transparent;border:none;cursor:pointer;padding:0}._closeButton_1qwya_50:hover{background:var(--modal-close-hover-bg);color:var(--modal-close-icon-hover)}._body_1qwya_71{display:flex;flex-direction:column;flex:1;min-height:0;padding:1rem 1.25rem;gap:1rem}._searchWrapper_1qwya_80{flex-shrink:0;display:flex;align-items:center;gap:8px}._content_1qwya_87{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;margin-bottom:56px}._emptyState_1qwya_95{display:flex;align-items:center;justify-content:center;height:200px;font-size:13px;color:var(--modal-empty-text)}._footer_1qwya_105{position:absolute;bottom:0;left:0;right:0;height:72px;display:flex;justify-content:space-between;align-items:center;padding:0 1.25rem;border-top:1px solid var(--panel-divider);background:var(--modal-surface);flex-shrink:0;box-sizing:border-box}._tabsWrapper_1qwya_122{flex-shrink:0}._tabs_1qwya_122{display:flex;gap:var(--space-5)}._tab_1qwya_122{height:32px;padding:0;font-size:14px;font-weight:500;color:var(--text-muted);background:transparent;border:none;cursor:pointer;transition:color .2s ease;position:relative}._tab_1qwya_122:hover{color:var(--text-primary)}._tabActive_1qwya_148{color:var(--text-primary);font-weight:600}._tabActive_1qwya_148:after{content:"";position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--text-accent);border-radius:1px}._categoriesWrapper_1qwya_165{flex-shrink:0;padding-bottom:16px}._categories_1qwya_165{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-4)}._categoryItem_1qwya_177{display:flex;align-items:center}._categoryDivider_1qwya_182{width:1px;height:16px;background:#dbdbdb;margin-right:16px}._categoryTab_1qwya_189{display:inline-flex;min-height:28px;align-items:center;padding:0;font-size:14px;line-height:1;color:var(--text-muted);background:transparent;border:none;cursor:pointer;transition:color .2s ease}._categoryTab_1qwya_189:hover{color:var(--text-primary)}._categoryTabActive_1qwya_207{color:var(--text-primary);font-weight:600}._skillGrid_1qwya_213{display:grid;gap:var(--space-7);grid-template-columns:repeat(2,minmax(0,1fr));min-width:0}._card_1qwya_222{display:flex;flex-direction:column;flex:1;min-height:106px;gap:var(--space-5);padding:16px;border-radius:8px;border:1px solid #E5E5E5;background:#fafafa}._card_1qwya_222:hover{border-color:var(--text-accent);background:#fff}._cardSelected_1qwya_239{background:#f0f7ff;border-color:transparent}._cardSelected_1qwya_239:hover{background:#f0f7ff}._cardHeader_1qwya_249{display:flex;align-items:flex-start;gap:var(--space-5)}._cardContent_1qwya_255{min-width:0;flex:1}._badge_1qwya_260{display:inline-flex;align-items:center;height:18px;padding:0 6px;font-size:11px;line-height:18px;color:var(--text-secondary);background:#e6e6e6;border-radius:4px}._cardTitle_1qwya_272{font-size:14px;line-height:24px;font-weight:var(--font-weight-bold);color:var(--text-primary);margin:0}._cardDescription_1qwya_280{display:-webkit-box;overflow:hidden;font-size:var(--font-size-md);line-height:22px;color:var(--text-secondary);-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;margin:0;margin-top:var(--space-3)}._checkbox_1qwya_294{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:4px;border:1.5px solid var(--text-muted);color:transparent;transition:all .2s ease;flex-shrink:0}._checkboxChecked_1qwya_307{background:var(--text-accent);border-color:var(--text-accent);color:#fff}._cardFooter_1qwya_314{margin-top:auto;padding-top:var(--space-3)}._installButton_1qwya_319{display:inline-flex;align-items:center;justify-content:center;padding:0;font-size:13px;line-height:1;font-weight:500;color:var(--text-accent);background:transparent;border:none;cursor:pointer;transition:all .2s ease}._installButton_1qwya_319:hover{text-decoration:underline;text-underline-offset:2px}._loadMore_1qwya_340{display:flex;justify-content:center;padding:16px 0}@media(max-width:480px){._skillGrid_1qwya_213{grid-template-columns:1fr}}@keyframes _fadeIn_1qwya_1{0%{opacity:0}to{opacity:1}}@keyframes _slideInRight_1qwya_1{0%{transform:translate(100%)}to{transform:translate(0)}}._skillGrid_qcha4_7{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}._skillCard_qcha4_13{display:flex;align-items:center;height:80px;padding:12px;border-radius:12px;border:1px solid rgba(240,240,240,1);background:#fafafa;position:relative;transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease}._skillCard_qcha4_13:hover{border-color:transparent;box-shadow:0 2px 8px #00000014;background:#fff}._skillCard_qcha4_13:hover ._deleteButton_qcha4_31{opacity:1}._cardIcon_qcha4_35{flex-shrink:0;margin-right:10px}._cardContent_qcha4_40{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}._cardName_qcha4_48{font-size:14px;font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._cardDescription_qcha4_57{font-size:12px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._cardTags_qcha4_65{display:flex;flex-wrap:wrap;gap:4px}._cardTag_qcha4_65{font-size:11px;padding:0 6px;height:18px;line-height:18px;border-radius:4px;background:#e6e6e6;color:var(--text-secondary)}._deleteButton_qcha4_31{position:absolute;top:50%;right:8px;transform:translateY(-50%);width:20px;height:20px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;cursor:pointer;opacity:0;transition:opacity .2s ease;color:var(--text-muted);padding:0}._deleteButton_qcha4_31:hover{color:var(--text-primary)}._emptyState_qcha4_104{grid-column:1 / -1;display:flex;align-items:center;justify-content:center;height:80px;font-size:14px;color:var(--text-muted)}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./index-Cb4fQgom.js";const o={error:{bg:"var(--alert-error-bg)",icon:e.jsx("img",{src:"/icons/message-error.svg",alt:"","aria-hidden":"true",className:"h-4 w-4"})},prompt:{bg:"var(--alert-prompt-bg)",icon:e.jsx("img",{src:"/icons/message-prompt.svg",alt:"","aria-hidden":"true",className:"h-4 w-4"})},warn:{bg:"var(--alert-warn-bg)",icon:e.jsx("img",{src:"/icons/message-warn.svg",alt:"","aria-hidden":"true",className:"h-4 w-4"})}},l=()=>e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:e.jsx("path",{d:"M4 4l8 8M12 4l-8 8",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})});function x({mode:s,children:a,closable:i=!0,onClose:r,className:n=""}){const t=o[s];return e.jsxs("div",{className:`flex w-full gap-2 rounded-[8px] px-4 py-2 ${n}`,style:{backgroundColor:t.bg},role:"alert",children:[e.jsx("span",{"data-testid":"alert-status-icon",className:"flex h-4 w-4 flex-shrink-0 items-center justify-center text-[var(--text-primary)] mt-[2px]",children:t.icon}),e.jsx("div",{className:"min-w-0 flex-1 text-sm text-[var(--text-primary)]",children:a}),i&&r&&e.jsx("button",{onClick:r,className:"flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-[4px] text-[var(--text-label-secondary)] transition-colors hover:text-[var(--text-primary)]","aria-label":"Close",children:e.jsx(l,{})})]})}export{x as A};
|
|
2
|
+
//# sourceMappingURL=Alert-D88Fk6to.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert-D88Fk6to.js","sources":["../../src/components/shared/Alert.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ReactNode } from 'react';\n\nexport type AlertMode = 'error' | 'prompt' | 'warn';\n\nexport interface AlertProps {\n /** Alert mode determines background color and icon */\n mode: AlertMode;\n /** Content text or React nodes */\n children: ReactNode;\n /** Show/hide the close button on the right */\n closable?: boolean;\n /** Callback when close button is clicked */\n onClose?: () => void;\n /** Additional CSS classes */\n className?: string;\n}\n\nconst ALERT_VARIANTS = {\n error: {\n bg: 'var(--alert-error-bg)',\n icon: <img src=\"/icons/message-error.svg\" alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4\" />,\n },\n prompt: {\n bg: 'var(--alert-prompt-bg)',\n icon: <img src=\"/icons/message-prompt.svg\" alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4\" />,\n },\n warn: {\n bg: 'var(--alert-warn-bg)',\n icon: <img src=\"/icons/message-warn.svg\" alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4\" />,\n },\n} as const;\n\nconst CloseIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n </svg>\n);\n\nexport function Alert({ mode, children, closable = true, onClose, className = '' }: AlertProps) {\n const variant = ALERT_VARIANTS[mode];\n\n return (\n <div\n className={`flex w-full gap-2 rounded-[8px] px-4 py-2 ${className}`}\n style={{ backgroundColor: variant.bg }}\n role=\"alert\"\n >\n {/* Left icon */}\n <span\n data-testid=\"alert-status-icon\"\n className=\"flex h-4 w-4 flex-shrink-0 items-center justify-center text-[var(--text-primary)] mt-[2px]\"\n >\n {variant.icon}\n </span>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1 text-sm text-[var(--text-primary)]\">\n {children}\n </div>\n\n {/* Right close button */}\n {closable && onClose && (\n <button\n onClick={onClose}\n className=\"flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-[4px] text-[var(--text-label-secondary)] transition-colors hover:text-[var(--text-primary)]\"\n aria-label=\"Close\"\n >\n <CloseIcon />\n </button>\n )}\n </div>\n );\n}\n"],"names":["ALERT_VARIANTS","jsx","CloseIcon","Alert","mode","children","closable","onClose","className","variant","jsxs"],"mappings":"wCAmBA,MAAMA,EAAiB,CACrB,MAAO,CACL,GAAI,wBACJ,KAAMC,EAAAA,IAAC,MAAA,CAAI,IAAI,2BAA2B,IAAI,GAAG,cAAY,OAAO,UAAU,SAAA,CAAU,CAAA,EAE1F,OAAQ,CACN,GAAI,yBACJ,KAAMA,EAAAA,IAAC,MAAA,CAAI,IAAI,4BAA4B,IAAI,GAAG,cAAY,OAAO,UAAU,SAAA,CAAU,CAAA,EAE3F,KAAM,CACJ,GAAI,uBACJ,KAAMA,EAAAA,IAAC,MAAA,CAAI,IAAI,0BAA0B,IAAI,GAAG,cAAY,OAAO,UAAU,SAAA,CAAU,CAAA,CAE3F,EAEMC,EAAY,IAChBD,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,SAAAA,EAAAA,IAAC,OAAA,CAAK,EAAE,qBAAqB,OAAO,eAAe,YAAY,MAAM,cAAc,OAAA,CAAO,CAAA,CAC5F,EAGK,SAASE,EAAM,CAAE,KAAAC,EAAM,SAAAC,EAAU,SAAAC,EAAW,GAAM,QAAAC,EAAS,UAAAC,EAAY,IAAkB,CAC9F,MAAMC,EAAUT,EAAeI,CAAI,EAEnC,OACEM,EAAAA,KAAC,MAAA,CACC,UAAW,6CAA6CF,CAAS,GACjE,MAAO,CAAE,gBAAiBC,EAAQ,EAAA,EAClC,KAAK,QAGL,SAAA,CAAAR,EAAAA,IAAC,OAAA,CACC,cAAY,oBACZ,UAAU,6FAET,SAAAQ,EAAQ,IAAA,CAAA,EAIXR,EAAAA,IAAC,MAAA,CAAI,UAAU,oDACZ,SAAAI,CAAA,CACH,EAGCC,GAAYC,GACXN,EAAAA,IAAC,SAAA,CACC,QAASM,EACT,UAAU,6JACV,aAAW,QAEX,eAACL,EAAA,CAAA,CAAU,CAAA,CAAA,CACb,CAAA,CAAA,CAIR"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e,a as B}from"./index-Cb4fQgom.js";function o(...t){return t.filter(Boolean).join(" ")}function z({open:t,onClose:n,children:d,title:r,panelClassName:c,bodyClassName:u,headerClassName:m,titleClassName:p,backdropClassName:f,zIndexClassName:x="z-50",disableBackdropClose:s=!1,showCloseButton:l=!0,closeButtonAriaLabel:h="close",backdropTestId:j,panelTestId:g,bodyTestId:k,panelRef:N,panelTabIndex:b,panelStyle:y,backdropRole:M,backdropAriaModal:P,backdropAriaLabel:w}){if(!t)return null;const C=a=>{a.target===a.currentTarget&&(a.stopPropagation(),!s&&n())},D=a=>{a.target===a.currentTarget&&(a.stopPropagation(),s&&a.preventDefault())},v=a=>{a.stopPropagation()},T=r||l,A=()=>r?typeof r=="string"||typeof r=="number"?e.jsx("h3",{className:o("ui-modal-title",p),children:r}):r:e.jsx("span",{}),i=e.jsx("div",{role:M,"aria-modal":P,"aria-label":w,className:o("ui-modal-backdrop",x,f),onMouseDown:D,onClick:C,"data-testid":j,children:e.jsxs("div",{ref:N,tabIndex:b,style:y,className:o("ui-modal-panel",c),onClick:v,"data-testid":g,children:[T?e.jsxs("div",{className:o("ui-modal-header",m),children:[e.jsx("div",{className:"ui-modal-title-slot",children:A()}),l?e.jsx("button",{type:"button",onClick:n,"aria-label":h,className:"ui-modal-close-button",children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12"})})}):null]}):null,e.jsx("div",{"data-testid":k,className:u,children:d})]})});return typeof document>"u"?i:B.createPortal(i,document.body)}export{z as A};
|
|
2
|
+
//# sourceMappingURL=AppModal-BYZTSuch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppModal-BYZTSuch.js","sources":["../../src/components/AppModal.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { type AriaRole, type CSSProperties, type MouseEvent, type ReactNode, type Ref } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface AppModalProps {\n open: boolean;\n onClose: () => void;\n children: ReactNode;\n title?: ReactNode;\n panelClassName?: string;\n bodyClassName?: string;\n headerClassName?: string;\n titleClassName?: string;\n backdropClassName?: string;\n zIndexClassName?: string;\n disableBackdropClose?: boolean;\n showCloseButton?: boolean;\n closeButtonAriaLabel?: string;\n backdropTestId?: string;\n panelTestId?: string;\n bodyTestId?: string;\n panelRef?: Ref<HTMLDivElement>;\n panelTabIndex?: number;\n panelStyle?: CSSProperties;\n backdropRole?: AriaRole;\n backdropAriaModal?: boolean;\n backdropAriaLabel?: string;\n}\n\nfunction joinClasses(...values: Array<string | false | null | undefined>) {\n return values.filter(Boolean).join(' ');\n}\n\nexport function AppModal({\n open,\n onClose,\n children,\n title,\n panelClassName,\n bodyClassName,\n headerClassName,\n titleClassName,\n backdropClassName,\n zIndexClassName = 'z-50',\n disableBackdropClose = false,\n showCloseButton = true,\n closeButtonAriaLabel = 'close',\n backdropTestId,\n panelTestId,\n bodyTestId,\n panelRef,\n panelTabIndex,\n panelStyle,\n backdropRole,\n backdropAriaModal,\n backdropAriaLabel,\n}: AppModalProps) {\n if (!open) return null;\n\n const handleBackdropClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return;\n // Prevent backdrop clicks from bubbling into underlying page handlers.\n event.stopPropagation();\n if (disableBackdropClose) return;\n onClose();\n };\n\n const handleBackdropMouseDown = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return;\n event.stopPropagation();\n if (disableBackdropClose) {\n event.preventDefault();\n }\n };\n\n const handlePanelClick = (event: MouseEvent<HTMLDivElement>) => {\n event.stopPropagation();\n };\n\n const showHeader = title || showCloseButton;\n const renderTitle = () => {\n if (!title) return <span />;\n if (typeof title === 'string' || typeof title === 'number') {\n return <h3 className={joinClasses('ui-modal-title', titleClassName)}>{title}</h3>;\n }\n return title;\n };\n\n const modalNode = (\n <div\n role={backdropRole}\n aria-modal={backdropAriaModal}\n aria-label={backdropAriaLabel}\n className={joinClasses('ui-modal-backdrop', zIndexClassName, backdropClassName)}\n onMouseDown={handleBackdropMouseDown}\n onClick={handleBackdropClick}\n data-testid={backdropTestId}\n >\n <div\n ref={panelRef}\n tabIndex={panelTabIndex}\n style={panelStyle}\n className={joinClasses('ui-modal-panel', panelClassName)}\n onClick={handlePanelClick}\n data-testid={panelTestId}\n >\n {showHeader ? (\n <div className={joinClasses('ui-modal-header', headerClassName)}>\n <div className=\"ui-modal-title-slot\">{renderTitle()}</div>\n {showCloseButton ? (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={closeButtonAriaLabel}\n className=\"ui-modal-close-button\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n ) : null}\n </div>\n ) : null}\n <div data-testid={bodyTestId} className={bodyClassName}>\n {children}\n </div>\n </div>\n </div>\n );\n\n if (typeof document === 'undefined') {\n return modalNode;\n }\n return createPortal(modalNode, document.body);\n}\n"],"names":["joinClasses","values","AppModal","open","onClose","children","title","panelClassName","bodyClassName","headerClassName","titleClassName","backdropClassName","zIndexClassName","disableBackdropClose","showCloseButton","closeButtonAriaLabel","backdropTestId","panelTestId","bodyTestId","panelRef","panelTabIndex","panelStyle","backdropRole","backdropAriaModal","backdropAriaLabel","handleBackdropClick","event","handleBackdropMouseDown","handlePanelClick","showHeader","renderTitle","jsx","modalNode","jsxs","createPortal"],"mappings":"+CAoCA,SAASA,KAAeC,EAAkD,CACxE,OAAOA,EAAO,OAAO,OAAO,EAAE,KAAK,GAAG,CACxC,CAEO,SAASC,EAAS,CACvB,KAAAC,EACA,QAAAC,EACA,SAAAC,EACA,MAAAC,EACA,eAAAC,EACA,cAAAC,EACA,gBAAAC,EACA,eAAAC,EACA,kBAAAC,EACA,gBAAAC,EAAkB,OAClB,qBAAAC,EAAuB,GACvB,gBAAAC,EAAkB,GAClB,qBAAAC,EAAuB,QACvB,eAAAC,EACA,YAAAC,EACA,WAAAC,EACA,SAAAC,EACA,cAAAC,EACA,WAAAC,EACA,aAAAC,EACA,kBAAAC,EACA,kBAAAC,CACF,EAAkB,CAChB,GAAI,CAACrB,EAAM,OAAO,KAElB,MAAMsB,EAAuBC,GAAsC,CAC7DA,EAAM,SAAWA,EAAM,gBAE3BA,EAAM,gBAAA,EACF,CAAAb,GACJT,EAAA,EACF,EAEMuB,EAA2BD,GAAsC,CACjEA,EAAM,SAAWA,EAAM,gBAC3BA,EAAM,gBAAA,EACFb,GACFa,EAAM,eAAA,EAEV,EAEME,EAAoBF,GAAsC,CAC9DA,EAAM,gBAAA,CACR,EAEMG,EAAavB,GAASQ,EACtBgB,EAAc,IACbxB,EACD,OAAOA,GAAU,UAAY,OAAOA,GAAU,eACxC,KAAA,CAAG,UAAWN,EAAY,iBAAkBU,CAAc,EAAI,SAAAJ,EAAM,EAEvEA,EAJYyB,MAAC,OAAA,CAAA,CAAK,EAOrBC,EACJD,EAAAA,IAAC,MAAA,CACC,KAAMT,EACN,aAAYC,EACZ,aAAYC,EACZ,UAAWxB,EAAY,oBAAqBY,EAAiBD,CAAiB,EAC9E,YAAagB,EACb,QAASF,EACT,cAAaT,EAEb,SAAAiB,EAAAA,KAAC,MAAA,CACC,IAAKd,EACL,SAAUC,EACV,MAAOC,EACP,UAAWrB,EAAY,iBAAkBO,CAAc,EACvD,QAASqB,EACT,cAAaX,EAEZ,SAAA,CAAAY,SACE,MAAA,CAAI,UAAW7B,EAAY,kBAAmBS,CAAe,EAC5D,SAAA,CAAAsB,EAAAA,IAAC,MAAA,CAAI,UAAU,sBAAuB,SAAAD,EAAA,EAAc,EACnDhB,EACCiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS3B,EACT,aAAYW,EACZ,UAAU,wBAEV,eAAC,MAAA,CAAI,UAAU,UAAU,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAY,IACzF,SAAAgB,EAAAA,IAAC,OAAA,CAAK,EAAE,uBAAuB,CAAA,CACjC,CAAA,CAAA,EAEA,IAAA,CAAA,CACN,EACE,WACH,MAAA,CAAI,cAAab,EAAY,UAAWV,EACtC,SAAAH,CAAA,CACH,CAAA,CAAA,CAAA,CACF,CAAA,EAIJ,OAAI,OAAO,SAAa,IACf2B,EAEFE,eAAaF,EAAW,SAAS,IAAI,CAC9C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as a}from"./index-Cb4fQgom.js";function l({className:e="w-4 h-4"}){return a.jsx("span",{"aria-hidden":"true",className:`relative inline-block ${e}`,children:a.jsx("img",{src:"/loading-small.webp",alt:"",className:"absolute inset-0 h-full w-full object-contain",draggable:!1})})}function t(){return a.jsx("div",{className:"flex h-full min-h-[240px] w-full items-center justify-center","data-testid":"skills-loading-state","aria-label":"loading",children:a.jsx(l,{className:"h-4 w-4"})})}export{t as C,l as L};
|
|
2
|
+
//# sourceMappingURL=CenteredLoadingState-DHor-9vF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CenteredLoadingState-DHor-9vF.js","sources":["../../src/components/LoadingSmall.tsx","../../src/components/shared/CenteredLoadingState.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nexport function LoadingSmall({ className = 'w-4 h-4' }: { className?: string }) {\n return (\n <span aria-hidden=\"true\" className={`relative inline-block ${className}`}>\n <img\n src=\"/loading-small.webp\"\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-contain\"\n draggable={false}\n />\n </span>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { LoadingSmall } from '../LoadingSmall';\n\nexport function CenteredLoadingState() {\n return (\n <div\n className=\"flex h-full min-h-[240px] w-full items-center justify-center\"\n data-testid=\"skills-loading-state\"\n aria-label=\"loading\"\n >\n <LoadingSmall className=\"h-4 w-4\" />\n </div>\n );\n}\n"],"names":["LoadingSmall","className","jsx","CenteredLoadingState"],"mappings":"wCAQO,SAASA,EAAa,CAAE,UAAAC,EAAY,WAAqC,CAC9E,aACG,OAAA,CAAK,cAAY,OAAO,UAAW,yBAAyBA,CAAS,GACpE,SAAAC,EAAAA,IAAC,MAAA,CACC,IAAI,sBACJ,IAAI,GACJ,UAAU,gDACV,UAAW,EAAA,CAAA,EAEf,CAEJ,CCTO,SAASC,GAAuB,CACrC,OACED,EAAAA,IAAC,MAAA,CACC,UAAU,+DACV,cAAY,uBACZ,aAAW,UAEX,SAAAA,EAAAA,IAACF,EAAA,CAAa,UAAU,SAAA,CAAU,CAAA,CAAA,CAGxC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as a,j as e,B as F,u as D}from"./index-Cb4fQgom.js";import{a as E}from"./OverflowTooltip-CE5PjAb-.js";import{C as ne}from"./CenteredLoadingState-DHor-9vF.js";import{H as ae}from"./HelpPrompt-BPzDcC8F.js";import{P as re}from"./PasswordField-DmzjtnCg.js";function Y({open:t,title:n,message:i,confirmLabel:u="确认",cancelLabel:o="取消",confirmDisabled:l=!1,modalTestId:y,confirmTestId:h,cancelTestId:b,onConfirm:m,onCancel:k}){return a.useEffect(()=>{if(!t)return;const v=C=>{C.key==="Escape"&&k()};return window.addEventListener("keydown",v),()=>window.removeEventListener("keydown",v)},[t,k]),t?e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-[var(--overlay-backdrop-medium)]",children:e.jsx("div",{className:"w-[400px] rounded-[8px] border border-[var(--modal-border)] bg-[var(--modal-surface)] p-6 shadow-[var(--modal-shadow)]","data-testid":y,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-[16px] font-bold text-[var(--modal-title-text)]",children:n}),e.jsx("button",{type:"button",onClick:k,"aria-label":"close",className:"flex h-6 w-6 items-center justify-center rounded text-[var(--text-label-secondary)] transition-colors hover:text-[var(--text-primary)]",style:{transform:"translate(4px, -4px)"},children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12"})})})]}),e.jsx("div",{className:"space-y-1",children:e.jsx("p",{className:"text-sm text-[var(--modal-text-muted)]",children:i})}),e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx(F,{variant:"default",onClick:k,"data-testid":b,children:o}),e.jsx(F,{variant:"major",onClick:m,disabled:l,"data-testid":h,children:u})]})]})})}):null}const V={fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"},ie={feishu:{icon:e.jsx("img",{src:"/images/connectors/feishu.svg",alt:"飞书",className:"h-11 w-11"})},weixin:{icon:e.jsx("img",{src:"/images/connectors/weixin.svg",alt:"微信",className:"h-11 w-11"})},dingtalk:{icon:e.jsx("img",{src:"/images/connectors/dingtalk.svg",alt:"钉钉",className:"h-11 w-11"})},xiaoyi:{icon:e.jsx("img",{src:"/images/connectors/xiaoyi.svg",alt:"小艺",className:"h-11 w-11"})},"wecom-bot":{icon:e.jsx("img",{src:"/images/connectors/wecom-bot.png",alt:"WeCom",className:"h-11 w-11"})},"wecom-agent":{icon:e.jsx("img",{src:"/images/connectors/wecom-agent.png",alt:"WeCom Agent",className:"h-11 w-11"})}},ce={icon:e.jsx("svg",{className:"h-11 w-11",viewBox:"0 0 24 24",stroke:"currentColor",...V,children:e.jsx("path",{d:"M12 12m-10 0a10 10 0 1 0 20 0a10 10 0 1 0 -20 0"})})};function B({num:t}){return e.jsxs("span",{className:"text-[14px]",children:[t,"、"]})}function le(){return e.jsxs("svg",{className:"w-3.5 h-3.5",viewBox:"0 0 24 24",stroke:"currentColor",...V,children:[e.jsx("path",{d:"M15 3h6v6"}),e.jsx("path",{d:"M10 14 21 3"}),e.jsx("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"})]})}function oe(){return e.jsxs("svg",{className:"w-3.5 h-3.5 text-gray-500",viewBox:"0 0 24 24",stroke:"currentColor",...V,children:[e.jsx("path",{d:"M5 13a10 10 0 0 1 14 0"}),e.jsx("path",{d:"M8.5 16.5a5 5 0 0 1 7 0"}),e.jsx("path",{d:"M2 8.82a15 15 0 0 1 20 0"}),e.jsx("line",{x1:"12",x2:"12.01",y1:"20",y2:"20"})]})}function W(){return e.jsxs("svg",{className:"w-4 h-4 animate-spin",viewBox:"0 0 24 24",fill:"none",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",opacity:"0.25"}),e.jsx("path",{d:"M12 2a10 10 0 0 1 10 10",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round"})]})}function de(){return e.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",stroke:"currentColor",...V,children:[e.jsx("path",{d:"M22 11.08V12a10 10 0 1 1-5.93-9.14"}),e.jsx("path",{d:"m9 11 3 3L22 4"})]})}function ue({platformId:t}){return e.jsx("img",{src:"/icons/lock.svg",alt:"","aria-hidden":"true",className:"h-4 w-4"})}const me={userWhitelistEnabled:!0,allowedUsers:[],ownerOpenId:void 0};async function z(t,n){try{const i=await E(t,{...n,headers:{...n==null?void 0:n.headers,"Content-Type":"application/json"}});return i.ok?i.json():(console.error("[FeishuPermissionPanel] API error:",i.status,i.statusText),null)}catch(i){return console.error("[FeishuPermissionPanel] Network error:",i),null}}function xe(){const[t,n]=a.useState(me),[i,u]=a.useState(!0),[o,l]=a.useState(!1),[y,h]=a.useState(""),[b,m]=a.useState(""),k=a.useCallback(async()=>{u(!0);const r=await z("/api/connector/permissions/feishu");r&&n(r),u(!1)},[]);a.useEffect(()=>{k()},[k]);const v=async r=>{l(!0);const p=await z("/api/connector/permissions/feishu",{method:"PUT",body:JSON.stringify(r)});p&&n(p),l(!1)},C=()=>{if(!y.trim())return;const r=[...t.allowedUsers,{openId:y.trim(),name:b.trim()||void 0,addedAt:Date.now()}];v({allowedUsers:r}),h(""),m("")},T=r=>{const p=t.allowedUsers.filter(g=>g.openId!==r);v({allowedUsers:p})};return i?e.jsx("p",{className:"text-xs text-gray-400 py-2",children:"加载权限配置..."}):e.jsx("div",{className:"space-y-3 pt-4 border-t border-gray-100 dark:border-gray-800 mt-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-[14px] font-semibold",children:["个人白名单",t.userWhitelistEnabled&&e.jsx("span",{className:"text-gray-400 ml-1",children:"(建议开启)"})]}),e.jsx("button",{onClick:()=>v({userWhitelistEnabled:!t.userWhitelistEnabled}),disabled:o,className:`relative w-10 h-5 rounded-full transition-colors ${t.userWhitelistEnabled?"bg-blue-500":"bg-gray-300"}`,children:e.jsx("div",{className:`absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform ${t.userWhitelistEnabled?"translate-x-5":"translate-x-0.5"}`})})]}),!t.userWhitelistEnabled&&e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg text-xs",children:[e.jsx("svg",{className:"w-3.5 h-3.5 text-yellow-500",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5Zm0 9a1 1 0 100-2 1 1 0 000 2Z",clipRule:"evenodd"})}),e.jsx("span",{className:"text-yellow-700",children:"📢 未开启白名单,所有飞书用户均可 @bot"})]}),t.userWhitelistEnabled&&e.jsxs("div",{className:"space-y-1.5",children:[t.allowedUsers.length===0&&e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 rounded-lg text-xs",children:[e.jsx("svg",{className:"w-3.5 h-3.5 text-blue-500",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0Zm-7-4a1 1 0 11-2 0 1 1 0 012 0ZM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9Z",clipRule:"evenodd"})}),e.jsx("span",{className:"text-blue-700",children:"ℹ️ 白名单为空,当前仅扫码者可 @bot"})]}),t.ownerOpenId&&e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 bg-green-50 dark:bg-green-900/20 rounded-lg text-xs",children:[e.jsx("svg",{className:"w-3.5 h-3.5 text-green-500",fill:"currentColor",viewBox:"0 0 20 20",children:e.jsx("path",{fillRule:"evenodd",d:"M10 1a.75.75 0 0 1 .65.378l2.005 3.518 3.907.896a.75.75 0 0 1 .35 1.238l-2.634 2.87.363 3.964a.75.75 0 0 1-1.054.747L10 12.868l-3.587 1.743a.75.75 0 0 1-1.054-.747l.363-3.964L3.088 7.03a.75.75 0 0 1 .35-1.238l3.907-.896L9.35 1.378A.75.75 0 0 1 10 1Z",clipRule:"evenodd"})}),e.jsxs("span",{className:"flex-1 truncate text-green-700",children:["扫码者(豁免): ",t.ownerOpenId]})]}),t.allowedUsers.map(r=>e.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 bg-gray-50 rounded-lg text-xs",children:[e.jsx("svg",{className:"w-3.5 h-3.5 text-blue-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z"})}),e.jsxs("span",{className:"flex-1 truncate",children:[r.name||r.openId,r.name?e.jsx("span",{className:"text-gray-400 ml-1",children:r.openId.slice(-8)}):null]}),e.jsx("button",{onClick:()=>T(r.openId),className:"text-red-400 hover:text-red-600",children:"✕"})]},r.openId)),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{value:y,onChange:r=>h(r.target.value),placeholder:"open_id (ou_xxxx...)",className:"ui-input flex-1 px-2 py-1.5 text-xs rounded-lg"}),e.jsx("input",{value:b,onChange:r=>m(r.target.value),placeholder:"备注名(如:张三)",className:"ui-input flex-1 px-2 py-1.5 text-xs rounded-lg"}),e.jsx("button",{onClick:C,disabled:!y.trim()||o,className:"px-3 py-1.5 text-xs bg-blue-500 text-white rounded-lg disabled:opacity-40",children:"添加"})]}),e.jsx("p",{className:"text-xs text-gray-400",children:"💡 让用户在飞书中 @bot 发送 /myid 获取 open_id"})]})]})})}function X({label:t,disconnecting:n,onDisconnect:i,disconnectTestId:u,children:o}){const[l,y]=a.useState(!1),h=()=>{y(!1),i()},b=`${u}-confirm-modal`,m=`${u}-confirm-submit`,k=`${u}-confirm-cancel`;return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex h-[34px] w-1/2 items-center gap-2 rounded-[8px] border border-[var(--border-default)] bg-[var(--tag-bg)] px-3 text-xs text-[var(--text-primary)]","data-testid":"connector-connected-pill",children:[e.jsx("span",{className:"shrink-0 text-[var(--state-success-text)]",children:e.jsx(de,{})}),e.jsx("span",{className:"min-w-0 truncate",children:t}),e.jsx("button",{type:"button",onClick:()=>y(!0),disabled:n,className:"ml-auto shrink-0 font-medium text-[var(--text-accent)] disabled:opacity-50","data-testid":u,children:n?"断开中...":"断开连接"})]}),e.jsx(Y,{open:l,title:"断开连接",message:"是否确认断开连接?",confirmDisabled:n,modalTestId:b,confirmTestId:m,cancelTestId:k,onCancel:()=>y(!1),onConfirm:h}),o]})}function fe(t,n){return t==="expired"?"二维码已过期,请重新生成":t==="denied"?"授权已被拒绝,请重试并在飞书上确认":t==="error"?n??"获取二维码失败":null}function pe({configured:t,onConfirmed:n,onDisconnected:i}){const u=D(S=>S.addToast),[o,l]=a.useState(t?"confirmed":"idle"),[y,h]=a.useState(!1),[b,m]=a.useState(null),[k,v]=a.useState(null),C=a.useRef(null),T=a.useRef(!1),r=a.useRef(0),p=a.useCallback(()=>{C.current&&(clearTimeout(C.current),C.current=null)},[]);a.useEffect(()=>{T.current=t,l(t?"confirmed":"idle"),t&&(p(),m(null),v(null))},[t,p]),a.useEffect(()=>()=>p(),[p]);const g=a.useCallback((S,d)=>{p(),T.current=!1;const w=async()=>{if(T.current)return;const P=++r.current;try{const U=await E(`/api/connector/feishu/qrcode-status?qrPayload=${encodeURIComponent(S)}`);if(!U.ok){C.current=setTimeout(w,d);return}const $=await U.json();if(T.current||P!==r.current)return;if($.status==="waiting"){C.current=setTimeout(w,d);return}if(p(),T.current=!0,$.status==="confirmed"||$.status==="expired"||$.status==="denied"){l($.status),m(null),$.status==="confirmed"&&(v(null),n==null||n());return}l("error"),v("二维码状态异常"),m(null)}catch{if(T.current||P!==r.current)return;C.current=setTimeout(w,d)}};w()},[n,p]),f=async()=>{p(),T.current=!1,l("fetching"),v(null);try{const S=await E("/api/connector/feishu/qrcode",{method:"POST"});if(!S.ok){const w=await S.json().catch(()=>({}));l("error"),v(w.error??"获取二维码失败");return}const d=await S.json();m(d.qrUrl),l("waiting"),g(d.qrPayload,d.intervalMs??2500)}catch{l("error"),v("网络错误")}},M=async()=>{h(!0);try{const S=await E("/api/connector/feishu/disconnect",{method:"POST"});if(!S.ok){const d=await S.json().catch(()=>({}));u({type:"error",title:"断开连接失败",message:d.error??"断开失败",duration:5e3});return}l("idle"),u({type:"success",title:"断开连接成功",message:"已断开连接。",duration:3e3}),i==null||i()}catch{u({type:"error",title:"断开连接失败",message:"网络错误",duration:5e3})}finally{h(!1)}};if(o==="confirmed")return e.jsx("div",{"data-testid":"feishu-connected",children:e.jsx(X,{label:"飞书 已连接",disconnecting:y,onDisconnect:M,disconnectTestId:"feishu-disconnect"})});const L=fe(o,k);return e.jsxs("div",{className:"space-y-3","data-testid":"feishu-qr-panel",children:[(o==="idle"||o==="expired"||o==="error"||o==="denied")&&e.jsxs("div",{className:"space-y-2",children:[L&&e.jsx("p",{className:"text-xs text-red-600",children:L}),e.jsx(F,{variant:"major",onClick:f,"data-testid":"feishu-generate-qr",children:o==="idle"?"生成二维码":"重新生成二维码"})]}),o==="fetching"&&e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500",children:[e.jsx(W,{}),e.jsx("span",{children:"二维码生成中..."})]}),o==="waiting"&&b&&e.jsxs("div",{className:"flex flex-col gap-3",style:{width:"fit-content"},"data-testid":"feishu-qr-waiting-shell",children:[e.jsx("div",{className:"p-3 border-[#f0f0f0] bg-[#fff]",style:{boxShadow:"0 4px 16px 0 rgba(0,0,0,0.08)"},"data-testid":"feishu-qr-card",children:e.jsx("img",{src:b,alt:"飞书二维码",className:"w-48 h-48 rounded-lg","data-testid":"feishu-qr-image"})}),e.jsxs("div",{className:"flex items-center justify-center gap-2 text-gray-500 text-xs","data-testid":"feishu-qr-waiting-text",children:[e.jsx(W,{}),e.jsx("span",{children:"用飞书扫描二维码"})]})]})]})}const he=2500,ge=6e4;function je({configured:t,onConfigured:n,onDisconnected:i}){const u=D(d=>d.addToast),[o,l]=a.useState(t?"confirmed":"idle"),[y,h]=a.useState(null),[b,m]=a.useState(null),[k,v]=a.useState(!1),C=a.useRef(null),T=a.useRef(null),r=a.useRef(t),p=a.useRef(0),g=a.useRef(t),f=a.useCallback(()=>{C.current&&(clearTimeout(C.current),C.current=null),T.current&&(clearTimeout(T.current),T.current=null),p.current+=1},[]);a.useEffect(()=>()=>f(),[f]),a.useEffect(()=>{if(t){r.current=!0,g.current=!0,f(),l("confirmed"),h(null),m(null);return}r.current=!1,g.current=!1,l(d=>d==="confirmed"?"idle":d)},[t,f]);const M=a.useCallback(d=>{f(),r.current=!1,g.current=!1;const w=()=>{r.current||(C.current=setTimeout(()=>{P()},he))},P=async()=>{if(r.current)return;const U=++p.current;try{const $=await E(`/api/connector/weixin/qrcode-status?qrPayload=${encodeURIComponent(d)}`);if(!$.ok){w();return}const _=await $.json();if(r.current||U!==p.current)return;_.status==="scanned"?(l(O=>O==="scanned"?O:"scanned"),w()):_.status==="waiting"?(l(O=>O==="waiting"?O:"waiting"),w()):_.status==="confirmed"?(r.current=!0,f(),l("confirmed"),h(null),m(null),g.current||(g.current=!0,await(n==null?void 0:n()))):_.status==="expired"?(r.current=!0,f(),l("expired"),h(null)):w()}catch{if(r.current||U!==p.current)return;w()}};P(),T.current=setTimeout(()=>{r.current=!0,f(),l("expired"),h(null)},ge)},[n,f]),L=async()=>{f(),r.current=!1,g.current=!1,l("fetching"),m(null);try{const d=await E("/api/connector/weixin/qrcode",{method:"POST"});if(!d.ok){const P=await d.json().catch(()=>({}));l("error"),m(P.error??"获取二维码失败");return}const w=await d.json();h(w.qrUrl),l("waiting"),M(w.qrPayload)}catch{l("error"),m("网络错误")}},S=async()=>{v(!0),m(null);try{const d=await E("/api/connector/weixin/disconnect",{method:"POST"});if(!d.ok){const P=(await d.json().catch(()=>({}))).error??"解除绑定失败";m(P),u({type:"error",title:"断开连接失败",message:P,duration:5e3});return}f(),r.current=!1,g.current=!1,l("idle"),h(null),await(i==null?void 0:i()),u({type:"success",title:"断开连接成功",message:"已断开连接。",duration:3e3})}catch{m("网络错误"),u({type:"error",title:"断开连接失败",message:"网络错误",duration:5e3})}finally{v(!1)}};return o==="confirmed"?e.jsx("div",{"data-testid":"weixin-connected",children:e.jsx(X,{label:"微信已连接",disconnecting:k,onDisconnect:S,disconnectTestId:"weixin-disconnect",children:b&&e.jsx("p",{className:"text-xs text-red-600",children:b})})}):e.jsxs("div",{className:"space-y-3","data-testid":"weixin-qr-panel",children:[(o==="idle"||o==="expired"||o==="error")&&e.jsxs("div",{className:"space-y-2",children:[o==="expired"&&e.jsx("p",{className:"text-xs text-amber-600",children:"二维码已过期,请重新生成"}),o==="error"&&b&&e.jsx("p",{className:"text-xs text-red-600",children:b}),e.jsx(F,{onClick:L,"data-testid":"weixin-generate-qr",children:o==="expired"?"重新生成二维码":"生成二维码"})]}),o==="fetching"&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(W,{}),e.jsx("span",{children:"二维码生成中..."})]}),(o==="waiting"||o==="scanned")&&y&&e.jsxs("div",{className:"flex flex-col gap-3",style:{width:"fit-content"},children:[e.jsx("div",{className:"p-3 border-[#f0f0f0] bg-[#fff]",style:{boxShadow:"0 4px 16px 0 rgba(0,0,0,0.08)"},children:e.jsx("img",{src:y,alt:"WeChat login QR code",className:"w-48 h-48 rounded-lg","data-testid":"weixin-qr-image"})}),o==="waiting"&&e.jsxs("div",{className:"flex items-center justify-center gap-2 text-xs text-gray-500",children:[e.jsx(W,{}),e.jsx("span",{children:"用微信扫描二维码"})]}),o==="scanned"&&e.jsxs("div",{className:"flex items-center gap-2 text-xs font-medium text-green-600",children:[e.jsx(W,{}),e.jsx("span",{children:"已扫码,请在手机上确认..."})]})]})]})}const J=new Set(["feishu","weixin"]),ye={feishu:"https://support.huaweicloud.com/officeclaw-agentarts-pc/feishu.html",weixin:"https://support.huaweicloud.com/officeclaw-agentarts-pc/weixin.html",dingtalk:"https://support.huaweicloud.com/officeclaw-agentarts-pc/dingtalk.html",xiaoyi:"https://support.huaweicloud.com/officeclaw-agentarts-pc/xiaoyi.html"};function ve(t){if(typeof t=="string"){const u=t.trim();return u.length>0?u:null}if(!t||typeof t!="object")return null;const n=t.text??t.title??t.label;if(typeof n!="string")return null;const i=n.trim();return i.length>0?i:null}function we(t,n){if(!t||typeof t!="object")return null;const i=t,u=i.id,o=typeof u=="string"&&u.trim()?u.trim():`platform-${n}`,l=i.name,y=typeof l=="string"&&l.trim()?l.trim():o,h=i.nameEn,b=typeof h=="string"&&h.trim()?h.trim():y,m=i.docsUrl,k=typeof m=="string"?m.trim():"",v=!!i.configured,T=(Array.isArray(i.fields)?i.fields:[]).flatMap(g=>{if(!g||typeof g!="object")return[];const f=g,M=f.envName;if(typeof M!="string"||!M.trim())return[];const L=M.trim(),S=f.label,d=typeof S=="string"&&S.trim()?S.trim():L,w=f.currentValue,P=typeof w=="string"?w:null;return[{envName:L,label:d,sensitive:!!f.sensitive,currentValue:P}]}),p=(Array.isArray(i.steps)?i.steps:[]).flatMap(g=>{const f=ve(g);return f?[f]:[]});return{id:o,name:y,nameEn:b,configured:v,fields:T,docsUrl:k,steps:p}}function G(t){if(!t)return null;try{const n=new URL(t);return n.protocol!=="http:"&&n.protocol!=="https:"?null:{href:n.toString(),hostname:n.hostname}}catch{return null}}function Ne(t){const n=t==null?void 0:t.trim();return n||void 0}function K(t,n){return t.flatMap(i=>{const u=Ne(n[i.envName]);return u?[[i.envName,u]]:[]})}function be(){const t=D(s=>s.addToast),[n,i]=a.useState([]),[u,o]=a.useState(!1),[l,y]=a.useState(!1),[h,b]=a.useState(null),[m,k]=a.useState({}),[v,C]=a.useState(!1),[T,r]=a.useState(!1),[p,g]=a.useState(null),[f,M]=a.useState(null),[L,S]=a.useState(null),d=a.useCallback(async s=>{const j=(s==null?void 0:s.background)??!1;j?y(!0):o(!0);try{const R=await E("/api/connector/status");if(!R.ok)return;const N=await R.json(),c=Array.isArray(N==null?void 0:N.platforms)?N.platforms.map((x,q)=>we(x,q)).filter(x=>x!==null):[];i(c)}catch{}finally{j?y(!1):o(!1)}},[]);a.useEffect(()=>{d()},[d]),a.useEffect(()=>{if(n.length===0){b(null);return}b(s=>{var j;return s&&n.some(R=>R.id===s)?s:((j=n[0])==null?void 0:j.id)??null})},[n]);const w=s=>{b(s),k({}),g(null)},P=async s=>{const j=K(s.fields,m),R=j.map(([N,c])=>({name:N,value:c}));if(R.length===0){t({type:"error",title:"保存配置失败",message:"请至少填写一项配置",duration:5e3});return}if(C(!0),g(null),U.includes(s.id)){const N=Object.fromEntries(j),c=await E(`/api/connector/test/${s.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(N)}),x=await c.json().catch(()=>({}));if(!c.ok||!x.ok){C(!1),t({type:"error",title:"保存配置失败",message:"测试连接不成功,请检查配置是否正确",duration:5e3});return}}try{const N=await E("/api/config/env",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({updates:R})});if(!N.ok){const I=await N.json().catch(()=>({}));t({type:"error",title:"保存配置失败",message:I.error??"保存失败",duration:5e3});return}const c=await N.json().catch(()=>({})),x=c==null?void 0:c.runtime,q=Array.isArray(x==null?void 0:x.failedConnectors)?x.failedConnectors:[];t(x&&x.applied===!1?{type:"error",title:"保存配置成功",message:`配置已保存,但热生效失败:${q.map(I=>I.connectorId||"unknown").join("、")}。请查看 API 日志。`,duration:5e3}:{type:"success",title:"保存配置成功",message:"配置已保存并立即生效。",duration:3e3}),k({}),await d({background:!0})}catch{t({type:"error",title:"保存配置失败",message:"网络错误",duration:5e3})}finally{C(!1)}},U=["dingtalk","xiaoyi"],$=async s=>{var j,R,N,c;if(!U.includes(s.id)){t({type:"info",title:"测试连接即将上线",message:"该平台测试连接功能即将上线",duration:3e3});return}r(!0),g(null);try{const x=Object.fromEntries(K(s.fields,m)),q=await E(`/api/connector/test/${s.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(x)}),I=await q.json().catch(()=>({}));if(!q.ok||!I.ok){const se=I.error??I.details??"测试失败";t({type:"error",title:"测试连接失败",message:se,duration:5e3});return}const H=Array.isArray(I.warnings)?I.warnings.filter(Boolean):[],ee=H.length>0?`;${H.join(";")}`:"",Z=((R=(j=I.bot)==null?void 0:j.name)==null?void 0:R.trim())||((c=(N=I.bot)==null?void 0:N.openId)==null?void 0:c.trim()),te=Z?` 已识别 ${Z}`:"";t({type:"success",title:"测试连接成功",message:`${I.message??"连接测试成功"}${te}${ee}`,duration:3e3})}catch{t({type:"error",title:"测试连接失败",message:"网络错误",duration:5e3})}finally{r(!1)}},_=async s=>{M(s),g(null);try{const j=await E(`/api/connector/${s}/disconnect`,{method:"POST"});if(!j.ok){const c=await j.json().catch(()=>({}));t({type:"error",title:"断开连接失败",message:c.error??"断开失败",duration:5e3});return}const R=await j.json().catch(()=>({})),N=R==null?void 0:R.runtime;t((N==null?void 0:N.applied)===!1?{type:"error",title:"断开连接成功",message:"已断开连接,但热生效失败。请查看 API 日志。",duration:5e3}:{type:"success",title:"断开连接成功",message:"已断开连接。",duration:3e3}),await d({background:!0})}catch{t({type:"error",title:"断开连接失败",message:"网络错误",duration:5e3})}finally{M(null)}},O=()=>{if(!L)return;const s=L;S(null),_(s)};if(u)return e.jsx("div",{className:"flex h-full min-h-0 items-center justify-center",children:e.jsx(ne,{})});if(n.length===0)return e.jsx("p",{className:"py-8 text-center text-sm text-[var(--text-muted)]",children:"无法加载平台配置信息"});const A=n.find(s=>s.id===h)??n[0]??null,Q=A?G(ye[A.id]??""):null;return e.jsxs("div",{className:"ui-panel flex h-full min-h-0 overflow-hidden",children:[e.jsx("div",{className:"h-full w-[322px] shrink-0 space-y-2 overflow-y-auto border-r border-[#f0f0f0] px-4 py-6","data-testid":"connector-left-pane",children:n.map(s=>{const j=(A==null?void 0:A.id)===s.id,R=ie[s.id]??ce;return e.jsxs("button",{type:"button",onClick:()=>w(s.id),"data-testid":`platform-item-${s.id}`,className:"flex w-full items-center gap-3 border px-4 py-3.5 text-left transition-colors [border-radius:var(--connector-tab-radius)]",style:{borderColor:j?"var(--connector-tab-border-selected)":"var(--connector-tab-border-default)",backgroundColor:j?"var(--connector-tab-bg-selected)":"var(--connector-tab-bg-default)"},children:[e.jsx("span",{className:"flex h-11 w-11 shrink-0 items-center justify-center",children:R.icon}),e.jsxs("span",{className:"min-w-0 flex-1 text-left",children:[e.jsx("span",{className:"block text-[14px] font-semibold text-[var(--text-primary)]",children:s.name}),e.jsx("span",{className:`ui-status-badge ${s.configured?"ui-status-badge-configured":"ui-status-badge-unconfigured"}`,children:s.configured?"已启用":"未配置"})]})]},s.id)})}),e.jsxs("div",{className:"flex h-full min-w-0 flex-1 flex-col gap-6 overflow-auto px-12 py-6","data-testid":"connector-right-pane",children:[e.jsxs("div",{className:"flex items-center gap-[4px]",children:[e.jsx("p",{className:"text-[var(--text-primary)] font-semibold",children:"配置"}),Q&&e.jsx(ae,{href:Q.href,tooltip:"查看帮助文档",ariaLabel:"查看帮助文档",testId:`platform-help-link-${A==null?void 0:A.id}`})]}),A&&(()=>{const s=A,j=s.steps.slice(0,-1),R=G(s.docsUrl),N=j.length+2;return e.jsxs("div",{className:"space-y-3.5","data-testid":`platform-card-${s.id}`,children:[J.has(s.id)&&e.jsx("div",{className:"space-y-3.5",children:s.steps.map((c,x)=>e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(B,{num:x+1}),e.jsx("span",{className:"text-[14px]",children:c})]}),x===0&&e.jsxs("div",{className:"ml-[26px]",children:[s.id==="feishu"?e.jsx(pe,{configured:s.configured,onConfirmed:()=>void d({background:!0}),onDisconnected:()=>void d({background:!0})}):e.jsx(je,{configured:s.configured,onConfigured:()=>d({background:!0}),onDisconnected:()=>d({background:!0})}),s.id==="feishu"&&s.configured&&e.jsx(xe,{})]})]},x))}),!J.has(s.id)&&e.jsxs("div",{className:"space-y-3.5",children:[j.map((c,x)=>e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(B,{num:x+1}),e.jsx("span",{className:"text-[14px]",children:c})]}),x===0&&R&&e.jsxs("a",{href:R.href,target:"_blank",rel:"noopener noreferrer",className:"ui-button-default ml-[26px] inline-flex items-center gap-1.5",children:[e.jsx(le,{}),e.jsxs("span",{children:[R.hostname," ","->"," 查看官方文档"]})]})]},x)),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(B,{num:j.length+1}),e.jsx("span",{className:"text-[14px]",children:"填写应用凭证"})]}),e.jsx("div",{className:"ml-[26px] space-y-4",children:s.fields.map(c=>e.jsxs("div",{className:"w-1/2",children:[e.jsxs("label",{htmlFor:`config-${c.envName}`,className:"mb-1 block text-sm",children:[c.label,c.sensitive&&e.jsx("span",{className:"ml-1 inline-flex align-middle text-[var(--state-warning-text)]","data-testid":`connector-lock-${s.id}`,children:e.jsx(ue,{platformId:s.id})})]}),c.sensitive?e.jsx(re,{id:`config-${c.envName}`,name:`connector-${c.envName}`,placeholder:c.currentValue?"已设置(输入新值覆盖)":"未设置",value:m[c.envName]??"",onChange:x=>k(q=>({...q,[c.envName]:x.target.value})),autoComplete:"new-password",autoCapitalize:"off",autoCorrect:"off",spellCheck:!1,"data-form-type":"other","data-1p-ignore":"true","data-lpignore":"true",className:"ui-input","data-testid":`field-${c.envName}`,toggleTestId:`connector-password-toggle-${c.envName}`}):e.jsx("input",{id:`config-${c.envName}`,type:"text",name:`connector-${c.envName}`,placeholder:c.currentValue??"未设置",value:m[c.envName]??"",onChange:x=>k(q=>({...q,[c.envName]:x.target.value})),autoComplete:"off",autoCapitalize:"off",autoCorrect:"off",spellCheck:!1,"data-form-type":"other","data-1p-ignore":"true","data-lpignore":"true",className:"ui-input","data-testid":`field-${c.envName}`})]},c.envName))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(B,{num:N}),e.jsx("span",{className:"text-[14px]",children:"测试连接并保存"})]}),p&&e.jsx("div",{className:`ml-[26px] rounded-[var(--radius-md)] px-3 py-2 text-xs ${p.type==="success"?"ui-status-success":"ui-status-error"}`,"data-testid":"save-result",children:p.message}),e.jsxs("div",{className:"ml-[26px] flex items-center gap-2",children:[e.jsx(F,{variant:"default",onClick:()=>void $(s),disabled:T||l,children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(oe,{}),T?"测试中...":"测试连接"]})}),e.jsx(F,{variant:"major",onClick:()=>P(s),disabled:v||l,"data-testid":`save-${s.id}`,children:v?"保存中...":"保存配置"}),s.configured&&e.jsx(F,{variant:"default",onClick:()=>S(s.id),disabled:f===s.id||l,className:"text-red-500 hover:text-red-700","data-testid":`disconnect-${s.id}`,children:f===s.id?"断开中...":"断开连接"}),e.jsx(Y,{open:L===s.id,title:"断开连接",message:"是否确认断开连接?",confirmDisabled:f===s.id,modalTestId:`disconnect-${s.id}-confirm-modal`,confirmTestId:`disconnect-${s.id}-confirm-submit`,cancelTestId:`disconnect-${s.id}-confirm-cancel`,onCancel:()=>S(null),onConfirm:O})]})]})]})]})})()]})]})}function ke(){return e.jsxs("div",{className:"ui-page-shell",children:[e.jsx("div",{className:"ui-page-header",children:e.jsx("h1",{className:"ui-page-title",children:"渠道"})}),e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto",children:e.jsx(be,{})})]})}function Ie(){return e.jsx("div",{className:"h-full overflow-hidden ui-shell-surface px-8 py-8",children:e.jsx(ke,{})})}export{Ie as default};
|
|
2
|
+
//# sourceMappingURL=ChannelsPage-CbI0kqkd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChannelsPage-CbI0kqkd.js","sources":["../../src/components/shared/ActionConfirmModal.tsx","../../src/components/channels-panel/components/ConnectorConfigIcons.tsx","../../src/components/channels-panel/components/FeishuPermissionPanel.tsx","../../src/components/channels-panel/components/ConnectorConnectedState.tsx","../../src/components/channels-panel/components/FeishuQrPanel.tsx","../../src/components/channels-panel/components/WeixinQrPanel.tsx","../../src/components/channels-panel/components/ConnectorConfigTab.tsx","../../src/components/channels-panel/ChannelsPanel.tsx","../../src/pages/ChannelsPage.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useEffect } from 'react';\nimport { Button } from './Button';\n\ninterface ActionConfirmModalProps {\n open: boolean;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmDisabled?: boolean;\n modalTestId?: string;\n confirmTestId?: string;\n cancelTestId?: string;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function ActionConfirmModal({\n open,\n title,\n message,\n confirmLabel = '确认',\n cancelLabel = '取消',\n confirmDisabled = false,\n modalTestId,\n confirmTestId,\n cancelTestId,\n onConfirm,\n onCancel,\n}: ActionConfirmModalProps) {\n useEffect(() => {\n if (!open) return;\n const handleKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onCancel();\n };\n window.addEventListener('keydown', handleKey);\n return () => window.removeEventListener('keydown', handleKey);\n }, [open, onCancel]);\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--overlay-backdrop-medium)]\">\n <div\n className=\"w-[400px] rounded-[8px] border border-[var(--modal-border)] bg-[var(--modal-surface)] p-6 shadow-[var(--modal-shadow)]\"\n data-testid={modalTestId}\n >\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-[16px] font-bold text-[var(--modal-title-text)]\">{title}</h3>\n <button\n type=\"button\"\n onClick={onCancel}\n aria-label=\"close\"\n className=\"flex h-6 w-6 items-center justify-center rounded text-[var(--text-label-secondary)] transition-colors hover:text-[var(--text-primary)]\"\n style={{ transform: 'translate(4px, -4px)' }}\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n <div className=\"space-y-1\">\n <p className=\"text-sm text-[var(--modal-text-muted)]\">{message}</p>\n </div>\n\n <div className=\"flex items-center justify-end gap-2\">\n <Button variant=\"default\"\n onClick={onCancel}\n data-testid={cancelTestId}\n >\n {cancelLabel}\n </Button>\n <Button variant=\"major\"\n onClick={onConfirm}\n disabled={confirmDisabled}\n data-testid={confirmTestId}\n >\n {confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport type { ReactNode } from 'react';\nimport React from 'react';\n\n// ── Per-platform visual config (matches .pen wireframe Screen C) ──\n\nexport interface PlatformVisual {\n icon: ReactNode;\n}\n\nconst SVG_PROPS = {\n fill: 'none' as const,\n strokeWidth: 2,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n};\n\nexport const PLATFORM_VISUALS: Record<string, PlatformVisual> = {\n feishu: {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/feishu.svg\" alt=\"飞书\" className=\"h-11 w-11\" />\n ),\n },\n weixin: {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/weixin.svg\" alt=\"微信\" className=\"h-11 w-11\" />\n ),\n },\n dingtalk: {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/dingtalk.svg\" alt=\"钉钉\" className=\"h-11 w-11\" />\n ),\n },\n xiaoyi: {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/xiaoyi.svg\" alt=\"小艺\" className=\"h-11 w-11\" />\n ),\n },\n 'wecom-bot': {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/wecom-bot.png\" alt=\"WeCom\" className=\"h-11 w-11\" />\n ),\n },\n 'wecom-agent': {\n icon: (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/images/connectors/wecom-agent.png\" alt=\"WeCom Agent\" className=\"h-11 w-11\" />\n ),\n },\n};\n\nexport const DEFAULT_VISUAL: PlatformVisual = {\n icon: (\n <svg className=\"h-11 w-11\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" {...SVG_PROPS}>\n <path d=\"M12 12m-10 0a10 10 0 1 0 20 0a10 10 0 1 0 -20 0\" />\n </svg>\n ),\n};\n\nexport function StepBadge({ num }: { num: number }) {\n return <span className=\"text-[14px]\">{num}、</span>;\n}\n\nexport function ExternalLinkIcon() {\n return (\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" {...SVG_PROPS}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n );\n}\n\nexport function WifiIcon() {\n return (\n <svg className=\"w-3.5 h-3.5 text-gray-500\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" {...SVG_PROPS}>\n <path d=\"M5 13a10 10 0 0 1 14 0\" />\n <path d=\"M8.5 16.5a5 5 0 0 1 7 0\" />\n <path d=\"M2 8.82a15 15 0 0 1 20 0\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"20\" y2=\"20\" />\n </svg>\n );\n}\n\n/** Spinning loader indicator */\nexport function SpinnerIcon() {\n return (\n <svg className=\"w-4 h-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" opacity=\"0.25\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n\n/** Checkmark circle icon for success states */\nexport function CheckCircleIcon() {\n return (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" {...SVG_PROPS}>\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <path d=\"m9 11 3 3L22 4\" />\n </svg>\n );\n}\n\nexport function ConnectorLockIcon({ platformId }: { platformId: string }) {\n return (\n // eslint-disable-next-line @next/next/no-img-element\n <img src=\"/icons/lock.svg\" alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4\" />\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { apiFetch } from '@/utils/api-client';\n\ninterface UserWhitelistEntry {\n openId: string;\n name?: string;\n addedAt: number;\n addedBy?: string;\n}\n\ninterface PermissionConfig {\n userWhitelistEnabled: boolean;\n allowedUsers: UserWhitelistEntry[];\n ownerOpenId?: string;\n}\n\nconst EMPTY_CONFIG: PermissionConfig = {\n userWhitelistEnabled: true, // 默认开启(建议)\n allowedUsers: [],\n ownerOpenId: undefined,\n};\n\nasync function apiFetchJson<T>(url: string, init?: RequestInit): Promise<T | null> {\n try {\n const res = await apiFetch(url, {\n ...init,\n headers: { ...init?.headers, 'Content-Type': 'application/json' },\n });\n if (!res.ok) {\n console.error('[FeishuPermissionPanel] API error:', res.status, res.statusText);\n return null;\n }\n return res.json() as Promise<T>;\n } catch (err) {\n console.error('[FeishuPermissionPanel] Network error:', err);\n return null;\n }\n}\n\nexport function FeishuPermissionPanel() {\n const [config, setConfig] = useState<PermissionConfig>(EMPTY_CONFIG);\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [newUserOpenId, setNewUserOpenId] = useState('');\n const [newUserName, setNewUserName] = useState('');\n\n const fetchConfig = useCallback(async () => {\n setLoading(true);\n const data = await apiFetchJson<PermissionConfig>('/api/connector/permissions/feishu');\n if (data) setConfig(data);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n fetchConfig();\n }, [fetchConfig]);\n\n const saveConfig = async (patch: Partial<PermissionConfig>) => {\n setSaving(true);\n const data = await apiFetchJson<PermissionConfig>('/api/connector/permissions/feishu', {\n method: 'PUT',\n body: JSON.stringify(patch),\n });\n if (data) setConfig(data);\n setSaving(false);\n };\n\n const addUser = () => {\n if (!newUserOpenId.trim()) return;\n const updated = [\n ...config.allowedUsers,\n { openId: newUserOpenId.trim(), name: newUserName.trim() || undefined, addedAt: Date.now() },\n ];\n saveConfig({ allowedUsers: updated });\n setNewUserOpenId('');\n setNewUserName('');\n };\n\n const removeUser = (openId: string) => {\n const updated = config.allowedUsers.filter((u) => u.openId !== openId);\n saveConfig({ allowedUsers: updated });\n };\n\n if (loading) {\n return <p className=\"text-xs text-gray-400 py-2\">加载权限配置...</p>;\n }\n\n return (\n <div className=\"space-y-3 pt-4 border-t border-gray-100 dark:border-gray-800 mt-4\">\n {/* Personal User Whitelist */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[14px] font-semibold\">\n 个人白名单\n {config.userWhitelistEnabled && <span className=\"text-gray-400 ml-1\">(建议开启)</span>}\n </span>\n <button\n onClick={() => saveConfig({ userWhitelistEnabled: !config.userWhitelistEnabled })}\n disabled={saving}\n className={`relative w-10 h-5 rounded-full transition-colors ${config.userWhitelistEnabled ? 'bg-blue-500' : 'bg-gray-300'}`}\n >\n <div\n className={`absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform ${config.userWhitelistEnabled ? 'translate-x-5' : 'translate-x-0.5'}`}\n />\n </button>\n </div>\n\n {/* Disabled warning */}\n {!config.userWhitelistEnabled && (\n <div className=\"flex items-center gap-2 px-3 py-2 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg text-xs\">\n <svg className=\"w-3.5 h-3.5 text-yellow-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5Zm0 9a1 1 0 100-2 1 1 0 000 2Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-yellow-700\">📢 未开启白名单,所有飞书用户均可 @bot</span>\n </div>\n )}\n\n {/* Enabled section */}\n {config.userWhitelistEnabled && (\n <div className=\"space-y-1.5\">\n {/* Empty whitelist warning */}\n {config.allowedUsers.length === 0 && (\n <div className=\"flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 rounded-lg text-xs\">\n <svg className=\"w-3.5 h-3.5 text-blue-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0Zm-7-4a1 1 0 11-2 0 1 1 0 012 0ZM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"text-blue-700\">ℹ️ 白名单为空,当前仅扫码者可 @bot</span>\n </div>\n )}\n\n {/* Owner OpenId display */}\n {config.ownerOpenId && (\n <div className=\"flex items-center gap-2 px-3 py-2 bg-green-50 dark:bg-green-900/20 rounded-lg text-xs\">\n <svg className=\"w-3.5 h-3.5 text-green-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M10 1a.75.75 0 0 1 .65.378l2.005 3.518 3.907.896a.75.75 0 0 1 .35 1.238l-2.634 2.87.363 3.964a.75.75 0 0 1-1.054.747L10 12.868l-3.587 1.743a.75.75 0 0 1-1.054-.747l.363-3.964L3.088 7.03a.75.75 0 0 1 .35-1.238l3.907-.896L9.35 1.378A.75.75 0 0 1 10 1Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"flex-1 truncate text-green-700\">扫码者(豁免): {config.ownerOpenId}</span>\n </div>\n )}\n\n {/* Whitelist users */}\n {config.allowedUsers.map((u) => (\n <div key={u.openId} className=\"flex items-center gap-2 px-3 py-2 bg-gray-50 rounded-lg text-xs\">\n <svg\n className=\"w-3.5 h-3.5 text-blue-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z\"\n />\n </svg>\n <span className=\"flex-1 truncate\">\n {u.name || u.openId}\n {u.name ? <span className=\"text-gray-400 ml-1\">{u.openId.slice(-8)}</span> : null}\n </span>\n <button onClick={() => removeUser(u.openId)} className=\"text-red-400 hover:text-red-600\">\n ✕\n </button>\n </div>\n ))}\n\n {/* Add user */}\n <div className=\"flex gap-2\">\n <input\n value={newUserOpenId}\n onChange={(e) => setNewUserOpenId(e.target.value)}\n placeholder=\"open_id (ou_xxxx...)\"\n className=\"ui-input flex-1 px-2 py-1.5 text-xs rounded-lg\"\n />\n <input\n value={newUserName}\n onChange={(e) => setNewUserName(e.target.value)}\n placeholder=\"备注名(如:张三)\"\n className=\"ui-input flex-1 px-2 py-1.5 text-xs rounded-lg\"\n />\n <button\n onClick={addUser}\n disabled={!newUserOpenId.trim() || saving}\n className=\"px-3 py-1.5 text-xs bg-blue-500 text-white rounded-lg disabled:opacity-40\"\n >\n 添加\n </button>\n </div>\n <p className=\"text-xs text-gray-400\">💡 让用户在飞书中 @bot 发送 /myid 获取 open_id</p>\n </div>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { type ReactNode, useState } from 'react';\nimport { ActionConfirmModal } from '../../shared/ActionConfirmModal';\nimport { CheckCircleIcon } from './ConnectorConfigIcons';\n\ninterface ConnectorConnectedStateProps {\n label: string;\n disconnecting: boolean;\n onDisconnect: () => void | Promise<void>;\n disconnectTestId: string;\n children?: ReactNode;\n}\n\nexport function ConnectorConnectedState({\n label,\n disconnecting,\n onDisconnect,\n disconnectTestId,\n children,\n}: ConnectorConnectedStateProps) {\n const [confirmOpen, setConfirmOpen] = useState(false);\n\n const handleConfirmDisconnect = () => {\n setConfirmOpen(false);\n void onDisconnect();\n };\n\n const modalTestId = `${disconnectTestId}-confirm-modal`;\n const confirmTestId = `${disconnectTestId}-confirm-submit`;\n const cancelTestId = `${disconnectTestId}-confirm-cancel`;\n\n return (\n <div className=\"space-y-2\">\n <div\n className=\"flex h-[34px] w-1/2 items-center gap-2 rounded-[8px] border border-[var(--border-default)] bg-[var(--tag-bg)] px-3 text-xs text-[var(--text-primary)]\"\n data-testid=\"connector-connected-pill\"\n >\n <span className=\"shrink-0 text-[var(--state-success-text)]\">\n <CheckCircleIcon />\n </span>\n <span className=\"min-w-0 truncate\">{label}</span>\n <button\n type=\"button\"\n onClick={() => setConfirmOpen(true)}\n disabled={disconnecting}\n className=\"ml-auto shrink-0 font-medium text-[var(--text-accent)] disabled:opacity-50\"\n data-testid={disconnectTestId}\n >\n {disconnecting ? '断开中...' : '断开连接'}\n </button>\n </div>\n <ActionConfirmModal\n open={confirmOpen}\n title=\"断开连接\"\n message=\"是否确认断开连接?\"\n confirmDisabled={disconnecting}\n modalTestId={modalTestId}\n confirmTestId={confirmTestId}\n cancelTestId={cancelTestId}\n onCancel={() => setConfirmOpen(false)}\n onConfirm={handleConfirmDisconnect}\n />\n {children}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { Button } from '../../shared/Button';\nimport { SpinnerIcon } from './ConnectorConfigIcons';\nimport { ConnectorConnectedState } from './ConnectorConnectedState';\n\ntype QrState = 'idle' | 'fetching' | 'waiting' | 'confirmed' | 'error' | 'expired' | 'denied';\n\ninterface FeishuQrPanelProps {\n configured: boolean;\n onConfirmed?: () => void;\n onDisconnected?: () => void;\n}\n\nfunction statusMessage(status: QrState, errorMsg: string | null) {\n if (status === 'expired') return '二维码已过期,请重新生成';\n if (status === 'denied') return '授权已被拒绝,请重试并在飞书上确认';\n if (status === 'error') return errorMsg ?? '获取二维码失败';\n return null;\n}\n\nexport function FeishuQrPanel({ configured, onConfirmed, onDisconnected }: FeishuQrPanelProps) {\n const addToast = useToastStore((s) => s.addToast);\n const [qrState, setQrState] = useState<QrState>(configured ? 'confirmed' : 'idle');\n const [disconnecting, setDisconnecting] = useState(false);\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [errorMsg, setErrorMsg] = useState<string | null>(null);\n const pollRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const terminalRef = useRef(false);\n const requestSeqRef = useRef(0);\n\n const stopPolling = useCallback(() => {\n if (pollRef.current) {\n clearTimeout(pollRef.current);\n pollRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n terminalRef.current = configured;\n setQrState(configured ? 'confirmed' : 'idle');\n if (configured) {\n stopPolling();\n setQrUrl(null);\n setErrorMsg(null);\n }\n }, [configured, stopPolling]);\n\n useEffect(() => () => stopPolling(), [stopPolling]);\n\n const schedulePoll = useCallback(\n (payload: string, intervalMs: number) => {\n stopPolling();\n terminalRef.current = false;\n\n const poll = async () => {\n if (terminalRef.current) return;\n\n const requestId = ++requestSeqRef.current;\n try {\n const res = await apiFetch(`/api/connector/feishu/qrcode-status?qrPayload=${encodeURIComponent(payload)}`);\n if (!res.ok) {\n pollRef.current = setTimeout(poll, intervalMs);\n return;\n }\n const data = await res.json();\n if (terminalRef.current || requestId !== requestSeqRef.current) return;\n\n if (data.status === 'waiting') {\n pollRef.current = setTimeout(poll, intervalMs);\n return;\n }\n\n stopPolling();\n terminalRef.current = true;\n\n if (data.status === 'confirmed' || data.status === 'expired' || data.status === 'denied') {\n setQrState(data.status);\n setQrUrl(null);\n if (data.status === 'confirmed') {\n setErrorMsg(null);\n onConfirmed?.();\n }\n return;\n }\n\n setQrState('error');\n setErrorMsg('二维码状态异常');\n setQrUrl(null);\n } catch {\n if (terminalRef.current || requestId !== requestSeqRef.current) return;\n pollRef.current = setTimeout(poll, intervalMs);\n }\n };\n\n poll();\n },\n [onConfirmed, stopPolling],\n );\n\n const handleFetchQr = async () => {\n stopPolling();\n terminalRef.current = false;\n setQrState('fetching');\n setErrorMsg(null);\n\n try {\n const res = await apiFetch('/api/connector/feishu/qrcode', { method: 'POST' });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n setQrState('error');\n setErrorMsg(data.error ?? '获取二维码失败');\n return;\n }\n\n const data = await res.json();\n setQrUrl(data.qrUrl);\n setQrState('waiting');\n schedulePoll(data.qrPayload, data.intervalMs ?? 2500);\n } catch {\n setQrState('error');\n setErrorMsg('网络错误');\n }\n };\n\n const handleDisconnect = async () => {\n setDisconnecting(true);\n try {\n const res = await apiFetch('/api/connector/feishu/disconnect', { method: 'POST' });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n addToast({\n type: 'error',\n title: '断开连接失败',\n message: data.error ?? '断开失败',\n duration: 5000,\n });\n return;\n }\n setQrState('idle');\n addToast({\n type: 'success',\n title: '断开连接成功',\n message: '已断开连接。',\n duration: 3000,\n });\n onDisconnected?.();\n } catch {\n addToast({\n type: 'error',\n title: '断开连接失败',\n message: '网络错误',\n duration: 5000,\n });\n } finally {\n setDisconnecting(false);\n }\n };\n\n if (qrState === 'confirmed') {\n return (\n <div data-testid=\"feishu-connected\">\n <ConnectorConnectedState\n label=\"飞书 已连接\"\n disconnecting={disconnecting}\n onDisconnect={handleDisconnect}\n disconnectTestId=\"feishu-disconnect\"\n />\n </div>\n );\n }\n\n const message = statusMessage(qrState, errorMsg);\n\n return (\n <div className=\"space-y-3\" data-testid=\"feishu-qr-panel\">\n {(qrState === 'idle' || qrState === 'expired' || qrState === 'error' || qrState === 'denied') && (\n <div className=\"space-y-2\">\n {message && <p className=\"text-xs text-red-600\">{message}</p>}\n <Button variant=\"major\" onClick={handleFetchQr} data-testid=\"feishu-generate-qr\">\n {qrState === 'idle' ? '生成二维码' : '重新生成二维码'}\n </Button>\n </div>\n )}\n\n {qrState === 'fetching' && (\n <div className=\"flex items-center gap-2 text-sm text-gray-500\">\n <SpinnerIcon />\n <span>二维码生成中...</span>\n </div>\n )}\n\n {qrState === 'waiting' && qrUrl && (\n <div className=\"flex flex-col gap-3\" style={{ width: 'fit-content' }} data-testid=\"feishu-qr-waiting-shell\">\n <div\n className=\"p-3 border-[#f0f0f0] bg-[#fff]\"\n style={{ boxShadow: '0 4px 16px 0 rgba(0,0,0,0.08)' }}\n data-testid=\"feishu-qr-card\"\n >\n <img src={qrUrl} alt=\"飞书二维码\" className=\"w-48 h-48 rounded-lg\" data-testid=\"feishu-qr-image\" />\n </div>\n <div\n className=\"flex items-center justify-center gap-2 text-gray-500 text-xs\"\n data-testid=\"feishu-qr-waiting-text\"\n >\n <SpinnerIcon />\n <span>用飞书扫描二维码</span>\n </div>\n </div>\n )}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { Button } from '../../shared/Button';\nimport { SpinnerIcon } from './ConnectorConfigIcons';\nimport { ConnectorConnectedState } from './ConnectorConnectedState';\n\ntype QrState = 'idle' | 'fetching' | 'waiting' | 'scanned' | 'confirmed' | 'error' | 'expired';\n\nconst QR_POLL_INTERVAL_MS = 2500;\nconst QR_EXPIRE_MS = 60_000;\n\ninterface WeixinQrPanelProps {\n configured: boolean;\n onConfigured?: () => void | Promise<void>;\n onDisconnected?: () => void | Promise<void>;\n}\n\nexport function WeixinQrPanel({ configured, onConfigured, onDisconnected }: WeixinQrPanelProps) {\n const addToast = useToastStore((s) => s.addToast);\n const [qrState, setQrState] = useState<QrState>(configured ? 'confirmed' : 'idle');\n const [qrUrl, setQrUrl] = useState<string | null>(null);\n const [errorMsg, setErrorMsg] = useState<string | null>(null);\n const [disconnecting, setDisconnecting] = useState(false);\n const pollRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const expireRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const terminalRef = useRef(configured);\n const requestSeqRef = useRef(0);\n const confirmedNotifiedRef = useRef(configured);\n\n const stopPolling = useCallback(() => {\n if (pollRef.current) {\n clearTimeout(pollRef.current);\n pollRef.current = null;\n }\n if (expireRef.current) {\n clearTimeout(expireRef.current);\n expireRef.current = null;\n }\n requestSeqRef.current += 1;\n }, []);\n\n useEffect(() => () => stopPolling(), [stopPolling]);\n\n useEffect(() => {\n if (configured) {\n terminalRef.current = true;\n confirmedNotifiedRef.current = true;\n stopPolling();\n setQrState('confirmed');\n setQrUrl(null);\n setErrorMsg(null);\n return;\n }\n terminalRef.current = false;\n confirmedNotifiedRef.current = false;\n setQrState((prev) => (prev === 'confirmed' ? 'idle' : prev));\n }, [configured, stopPolling]);\n\n const startPolling = useCallback(\n (payload: string) => {\n stopPolling();\n terminalRef.current = false;\n confirmedNotifiedRef.current = false;\n\n const scheduleNextPoll = () => {\n if (terminalRef.current) return;\n pollRef.current = setTimeout(() => {\n void poll();\n }, QR_POLL_INTERVAL_MS);\n };\n\n const poll = async () => {\n if (terminalRef.current) return;\n const requestId = ++requestSeqRef.current;\n try {\n const res = await apiFetch(`/api/connector/weixin/qrcode-status?qrPayload=${encodeURIComponent(payload)}`);\n if (!res.ok) {\n scheduleNextPoll();\n return;\n }\n const data = await res.json();\n if (terminalRef.current || requestId !== requestSeqRef.current) return;\n\n if (data.status === 'scanned') {\n setQrState((prev) => (prev === 'scanned' ? prev : 'scanned'));\n scheduleNextPoll();\n } else if (data.status === 'waiting') {\n setQrState((prev) => (prev === 'waiting' ? prev : 'waiting'));\n scheduleNextPoll();\n } else if (data.status === 'confirmed') {\n terminalRef.current = true;\n stopPolling();\n setQrState('confirmed');\n setQrUrl(null);\n setErrorMsg(null);\n if (!confirmedNotifiedRef.current) {\n confirmedNotifiedRef.current = true;\n await onConfigured?.();\n }\n } else if (data.status === 'expired') {\n terminalRef.current = true;\n stopPolling();\n setQrState('expired');\n setQrUrl(null);\n } else {\n scheduleNextPoll();\n }\n } catch {\n if (terminalRef.current || requestId !== requestSeqRef.current) return;\n scheduleNextPoll();\n /* network hiccup — keep polling */\n }\n };\n\n void poll();\n\n expireRef.current = setTimeout(() => {\n terminalRef.current = true;\n stopPolling();\n setQrState('expired');\n setQrUrl(null);\n }, QR_EXPIRE_MS);\n },\n [onConfigured, stopPolling],\n );\n\n const handleFetchQr = async () => {\n stopPolling();\n terminalRef.current = false;\n confirmedNotifiedRef.current = false;\n setQrState('fetching');\n setErrorMsg(null);\n try {\n const res = await apiFetch('/api/connector/weixin/qrcode', { method: 'POST' });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n setQrState('error');\n setErrorMsg(data.error ?? '获取二维码失败');\n return;\n }\n const data = await res.json();\n setQrUrl(data.qrUrl);\n setQrState('waiting');\n startPolling(data.qrPayload);\n } catch {\n setQrState('error');\n setErrorMsg('网络错误');\n }\n };\n\n const handleDisconnect = async () => {\n setDisconnecting(true);\n setErrorMsg(null);\n try {\n const res = await apiFetch('/api/connector/weixin/disconnect', { method: 'POST' });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n const message = data.error ?? '解除绑定失败';\n setErrorMsg(message);\n addToast({\n type: 'error',\n title: '断开连接失败',\n message,\n duration: 5000,\n });\n return;\n }\n stopPolling();\n terminalRef.current = false;\n confirmedNotifiedRef.current = false;\n setQrState('idle');\n setQrUrl(null);\n await onDisconnected?.();\n addToast({\n type: 'success',\n title: '断开连接成功',\n message: '已断开连接。',\n duration: 3000,\n });\n } catch {\n setErrorMsg('网络错误');\n addToast({\n type: 'error',\n title: '断开连接失败',\n message: '网络错误',\n duration: 5000,\n });\n } finally {\n setDisconnecting(false);\n }\n };\n\n if (qrState === 'confirmed') {\n return (\n <div data-testid=\"weixin-connected\">\n <ConnectorConnectedState\n label=\"微信已连接\"\n disconnecting={disconnecting}\n onDisconnect={handleDisconnect}\n disconnectTestId=\"weixin-disconnect\"\n >\n {errorMsg && <p className=\"text-xs text-red-600\">{errorMsg}</p>}\n </ConnectorConnectedState>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-3\" data-testid=\"weixin-qr-panel\">\n {(qrState === 'idle' || qrState === 'expired' || qrState === 'error') && (\n <div className=\"space-y-2\">\n {qrState === 'expired' && <p className=\"text-xs text-amber-600\">二维码已过期,请重新生成</p>}\n {qrState === 'error' && errorMsg && <p className=\"text-xs text-red-600\">{errorMsg}</p>}\n <Button onClick={handleFetchQr} data-testid=\"weixin-generate-qr\">\n {qrState === 'expired' ? '重新生成二维码' : '生成二维码'}\n </Button>\n </div>\n )}\n\n {qrState === 'fetching' && (\n <div className=\"flex items-center gap-2 text-sm\">\n <SpinnerIcon />\n <span>二维码生成中...</span>\n </div>\n )}\n\n {(qrState === 'waiting' || qrState === 'scanned') && qrUrl && (\n <div className=\"flex flex-col gap-3\" style={{ width: 'fit-content' }}>\n <div className=\"p-3 border-[#f0f0f0] bg-[#fff]\" style={{ boxShadow: '0 4px 16px 0 rgba(0,0,0,0.08)' }}>\n <img\n src={qrUrl}\n alt=\"WeChat login QR code\"\n className=\"w-48 h-48 rounded-lg\"\n data-testid=\"weixin-qr-image\"\n />\n </div>\n {qrState === 'waiting' && (\n <div className=\"flex items-center justify-center gap-2 text-xs text-gray-500\">\n <SpinnerIcon />\n <span>用微信扫描二维码</span>\n </div>\n )}\n {qrState === 'scanned' && (\n <div className=\"flex items-center gap-2 text-xs font-medium text-green-600\">\n <SpinnerIcon />\n <span>已扫码,请在手机上确认...</span>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { ActionConfirmModal } from '../../shared/ActionConfirmModal';\nimport { Button } from '../../shared/Button';\nimport { CenteredLoadingState } from '../../shared/CenteredLoadingState';\nimport { HelpPrompt } from '../../shared/HelpPrompt';\nimport { PasswordField } from '../../shared/PasswordField';\nimport {\n ConnectorLockIcon,\n DEFAULT_VISUAL,\n ExternalLinkIcon,\n PLATFORM_VISUALS,\n StepBadge,\n WifiIcon,\n} from './ConnectorConfigIcons';\nimport { FeishuPermissionPanel } from './FeishuPermissionPanel';\nimport { FeishuQrPanel } from './FeishuQrPanel';\nimport { WeixinQrPanel } from './WeixinQrPanel';\n\ninterface PlatformFieldStatus {\n envName: string;\n label: string;\n sensitive: boolean;\n currentValue: string | null;\n}\n\ninterface PlatformStatus {\n id: string;\n name: string;\n nameEn: string;\n configured: boolean;\n fields: PlatformFieldStatus[];\n docsUrl: string;\n steps: string[];\n}\n\ninterface ConnectorTestResult {\n ok?: boolean;\n message?: string;\n error?: string;\n details?: string;\n warnings?: string[];\n bot?: {\n openId?: string | null;\n name?: string | null;\n };\n}\n\nconst QR_ONLY_PLATFORM_IDS = new Set(['feishu', 'weixin']);\nconst PLATFORM_HELP_LINKS: Record<string, string> = {\n feishu: 'https://support.huaweicloud.com/officeclaw-agentarts-pc/feishu.html',\n weixin: 'https://support.huaweicloud.com/officeclaw-agentarts-pc/weixin.html',\n dingtalk: 'https://support.huaweicloud.com/officeclaw-agentarts-pc/dingtalk.html',\n xiaoyi: 'https://support.huaweicloud.com/officeclaw-agentarts-pc/xiaoyi.html',\n};\n\nfunction readStepText(step: unknown): string | null {\n if (typeof step === 'string') {\n const trimmed = step.trim();\n return trimmed.length > 0 ? trimmed : null;\n }\n if (!step || typeof step !== 'object') return null;\n const candidate =\n (step as { text?: unknown; title?: unknown; label?: unknown }).text ??\n (step as { text?: unknown; title?: unknown; label?: unknown }).title ??\n (step as { text?: unknown; title?: unknown; label?: unknown }).label;\n if (typeof candidate !== 'string') return null;\n const trimmed = candidate.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction normalizePlatform(raw: unknown, index: number): PlatformStatus | null {\n if (!raw || typeof raw !== 'object') return null;\n const item = raw as Record<string, unknown>;\n const idRaw = item.id;\n const id = typeof idRaw === 'string' && idRaw.trim() ? idRaw.trim() : `platform-${index}`;\n const nameRaw = item.name;\n const name = typeof nameRaw === 'string' && nameRaw.trim() ? nameRaw.trim() : id;\n const nameEnRaw = item.nameEn;\n const nameEn = typeof nameEnRaw === 'string' && nameEnRaw.trim() ? nameEnRaw.trim() : name;\n const docsUrlRaw = item.docsUrl;\n const docsUrl = typeof docsUrlRaw === 'string' ? docsUrlRaw.trim() : '';\n const configured = Boolean(item.configured);\n\n const fieldsRaw = Array.isArray(item.fields) ? item.fields : [];\n const fields = fieldsRaw.flatMap((field) => {\n if (!field || typeof field !== 'object') return [];\n const current = field as Record<string, unknown>;\n const envNameRaw = current.envName;\n if (typeof envNameRaw !== 'string' || !envNameRaw.trim()) return [];\n const envName = envNameRaw.trim();\n const labelRaw = current.label;\n const label = typeof labelRaw === 'string' && labelRaw.trim() ? labelRaw.trim() : envName;\n const currentValueRaw = current.currentValue;\n const currentValue = typeof currentValueRaw === 'string' ? currentValueRaw : null;\n return [\n {\n envName,\n label,\n sensitive: Boolean(current.sensitive),\n currentValue,\n },\n ];\n });\n\n const stepsRaw = Array.isArray(item.steps) ? item.steps : [];\n const steps = stepsRaw.flatMap((step) => {\n const normalized = readStepText(step);\n return normalized ? [normalized] : [];\n });\n\n return {\n id,\n name,\n nameEn,\n configured,\n fields,\n docsUrl,\n steps,\n };\n}\n\nfunction parseDocsLink(rawUrl: string): { href: string; hostname: string } | null {\n if (!rawUrl) return null;\n try {\n const url = new URL(rawUrl);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return null;\n return { href: url.toString(), hostname: url.hostname };\n } catch {\n return null;\n }\n}\n\nfunction normalizeConnectorFieldValue(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction collectConfiguredFieldEntries(\n fields: PlatformFieldStatus[],\n fieldValues: Record<string, string>,\n): Array<[string, string]> {\n return fields.flatMap((field) => {\n const value = normalizeConnectorFieldValue(fieldValues[field.envName]);\n return value ? [[field.envName, value]] : [];\n });\n}\n\nexport function ConnectorConfigTab() {\n const addToast = useToastStore((s) => s.addToast);\n const [platforms, setPlatforms] = useState<PlatformStatus[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [selectedPlatformId, setSelectedPlatformId] = useState<string | null>(null);\n const [fieldValues, setFieldValues] = useState<Record<string, string>>({});\n const [saving, setSaving] = useState(false);\n const [testing, setTesting] = useState(false);\n const [saveResult, setSaveResult] = useState<{ type: 'success' | 'error'; message: string } | null>(null);\n const [disconnecting, setDisconnecting] = useState<string | null>(null);\n const [confirmDisconnectPlatformId, setConfirmDisconnectPlatformId] = useState<string | null>(null);\n\n const fetchStatus = useCallback(async (options?: { background?: boolean }) => {\n const background = options?.background ?? false;\n if (background) {\n setIsRefreshing(true);\n } else {\n setIsLoading(true);\n }\n try {\n const res = await apiFetch('/api/connector/status');\n if (!res.ok) return;\n const data = await res.json();\n const nextPlatforms = Array.isArray(data?.platforms)\n ? data.platforms\n .map((item: unknown, index: number) => normalizePlatform(item, index))\n .filter((item: unknown): item is PlatformStatus => item !== null)\n : [];\n setPlatforms(nextPlatforms);\n } catch {\n // fall through\n } finally {\n if (background) {\n setIsRefreshing(false);\n } else {\n setIsLoading(false);\n }\n }\n }, []);\n\n useEffect(() => {\n fetchStatus();\n }, [fetchStatus]);\n\n useEffect(() => {\n if (platforms.length === 0) {\n setSelectedPlatformId(null);\n return;\n }\n setSelectedPlatformId((prev) => {\n if (prev && platforms.some((platform) => platform.id === prev)) return prev;\n return platforms[0]?.id ?? null;\n });\n }, [platforms]);\n\n const handleSelect = (platformId: string) => {\n setSelectedPlatformId(platformId);\n setFieldValues({});\n setSaveResult(null);\n };\n\n const handleSave = async (platform: PlatformStatus) => {\n const fieldEntries = collectConfiguredFieldEntries(platform.fields, fieldValues);\n const updates = fieldEntries.map(([name, value]) => ({ name, value }));\n\n if (updates.length === 0) {\n addToast({\n type: 'error',\n title: '保存配置失败',\n message: '请至少填写一项配置',\n duration: 5000,\n });\n return;\n }\n\n setSaving(true);\n setSaveResult(null);\n\n if (TESTABLE_PLATFORMS.includes(platform.id)) {\n const payload = Object.fromEntries(fieldEntries);\n const testRes = await apiFetch(`/api/connector/test/${platform.id}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n const testData = (await testRes.json().catch(() => ({}))) as ConnectorTestResult;\n if (!testRes.ok || !testData.ok) {\n setSaving(false);\n addToast({\n type: 'error',\n title: '保存配置失败',\n message: '测试连接不成功,请检查配置是否正确',\n duration: 5000,\n });\n return;\n }\n }\n\n try {\n const res = await apiFetch('/api/config/env', {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ updates }),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n addToast({\n type: 'error',\n title: '保存配置失败',\n message: data.error ?? '保存失败',\n duration: 5000,\n });\n return;\n }\n const data = await res.json().catch(() => ({}));\n const runtime = data?.runtime as\n | {\n applied?: boolean;\n failedConnectors?: Array<{ connectorId?: string; message?: string }>;\n }\n | undefined;\n const failedConnectors = Array.isArray(runtime?.failedConnectors) ? runtime.failedConnectors : [];\n addToast(\n runtime && runtime.applied === false\n ? {\n type: 'error',\n title: '保存配置成功',\n message: `配置已保存,但热生效失败:${failedConnectors\n .map((item) => item.connectorId || 'unknown')\n .join('、')}。请查看 API 日志。`,\n duration: 5000,\n }\n : {\n type: 'success',\n title: '保存配置成功',\n message: '配置已保存并立即生效。',\n duration: 3000,\n },\n );\n setFieldValues({});\n await fetchStatus({ background: true });\n } catch {\n addToast({\n type: 'error',\n title: '保存配置失败',\n message: '网络错误',\n duration: 5000,\n });\n } finally {\n setSaving(false);\n }\n };\n\n const TESTABLE_PLATFORMS = ['dingtalk', 'xiaoyi'];\n\n const handleTestConnection = async (platform: PlatformStatus) => {\n if (!TESTABLE_PLATFORMS.includes(platform.id)) {\n addToast({\n type: 'info',\n title: '测试连接即将上线',\n message: '该平台测试连接功能即将上线',\n duration: 3000,\n });\n return;\n }\n\n setTesting(true);\n setSaveResult(null);\n try {\n const payload = Object.fromEntries(collectConfiguredFieldEntries(platform.fields, fieldValues));\n const res = await apiFetch(`/api/connector/test/${platform.id}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n const data = (await res.json().catch(() => ({}))) as ConnectorTestResult;\n if (!res.ok || !data.ok) {\n const pieces = data.error ?? data.details ?? '测试失败';\n addToast({\n type: 'error',\n title: '测试连接失败',\n message: pieces,\n duration: 5000,\n });\n return;\n }\n\n const warnings = Array.isArray(data.warnings) ? data.warnings.filter(Boolean) : [];\n const warningText = warnings.length > 0 ? `;${warnings.join(';')}` : '';\n // Feishu includes bot info in response\n const botSuffix = data.bot?.name?.trim() || data.bot?.openId?.trim();\n const botText = botSuffix ? ` 已识别 ${botSuffix}` : '';\n addToast({\n type: 'success',\n title: '测试连接成功',\n message: `${data.message ?? '连接测试成功'}${botText}${warningText}`,\n duration: 3000,\n });\n } catch {\n addToast({\n type: 'error',\n title: '测试连接失败',\n message: '网络错误',\n duration: 5000,\n });\n } finally {\n setTesting(false);\n }\n };\n\n // 断开连接处理\n const handleDisconnect = async (platformId: string) => {\n setDisconnecting(platformId);\n setSaveResult(null);\n try {\n const res = await apiFetch(`/api/connector/${platformId}/disconnect`, { method: 'POST' });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n addToast({\n type: 'error',\n title: '断开连接失败',\n message: data.error ?? '断开失败',\n duration: 5000,\n });\n return;\n }\n const data = await res.json().catch(() => ({}));\n const runtime = data?.runtime as { applied?: boolean } | undefined;\n addToast(\n runtime?.applied === false\n ? {\n type: 'error',\n title: '断开连接成功',\n message: '已断开连接,但热生效失败。请查看 API 日志。',\n duration: 5000,\n }\n : {\n type: 'success',\n title: '断开连接成功',\n message: '已断开连接。',\n duration: 3000,\n },\n );\n await fetchStatus({ background: true });\n } catch {\n addToast({\n type: 'error',\n title: '断开连接失败',\n message: '网络错误',\n duration: 5000,\n });\n } finally {\n setDisconnecting(null);\n }\n };\n\n const handleConfirmDisconnect = () => {\n if (!confirmDisconnectPlatformId) return;\n const platformId = confirmDisconnectPlatformId;\n setConfirmDisconnectPlatformId(null);\n void handleDisconnect(platformId);\n };\n\n if (isLoading) {\n return (\n <div className=\"flex h-full min-h-0 items-center justify-center\">\n <CenteredLoadingState />\n </div>\n );\n }\n if (platforms.length === 0) {\n return <p className=\"py-8 text-center text-sm text-[var(--text-muted)]\">无法加载平台配置信息</p>;\n }\n\n const selectedPlatform = platforms.find((platform) => platform.id === selectedPlatformId) ?? platforms[0] ?? null;\n const selectedPlatformHelpLink = selectedPlatform\n ? parseDocsLink(PLATFORM_HELP_LINKS[selectedPlatform.id] ?? '')\n : null;\n\n return (\n <div className=\"ui-panel flex h-full min-h-0 overflow-hidden\">\n <div\n className=\"h-full w-[322px] shrink-0 space-y-2 overflow-y-auto border-r border-[#f0f0f0] px-4 py-6\"\n data-testid=\"connector-left-pane\"\n >\n {platforms.map((platform) => {\n const isSelected = selectedPlatform?.id === platform.id;\n const v = PLATFORM_VISUALS[platform.id] ?? DEFAULT_VISUAL;\n return (\n <button\n key={platform.id}\n type=\"button\"\n onClick={() => handleSelect(platform.id)}\n data-testid={`platform-item-${platform.id}`}\n className=\"flex w-full items-center gap-3 border px-4 py-3.5 text-left transition-colors [border-radius:var(--connector-tab-radius)]\"\n style={{\n borderColor: isSelected\n ? 'var(--connector-tab-border-selected)'\n : 'var(--connector-tab-border-default)',\n backgroundColor: isSelected ? 'var(--connector-tab-bg-selected)' : 'var(--connector-tab-bg-default)',\n }}\n >\n <span className=\"flex h-11 w-11 shrink-0 items-center justify-center\">{v.icon}</span>\n <span className=\"min-w-0 flex-1 text-left\">\n <span className=\"block text-[14px] font-semibold text-[var(--text-primary)]\">{platform.name}</span>\n <span\n className={`ui-status-badge ${platform.configured ? 'ui-status-badge-configured' : 'ui-status-badge-unconfigured'}`}\n >\n {platform.configured ? '已启用' : '未配置'}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n\n <div\n className=\"flex h-full min-w-0 flex-1 flex-col gap-6 overflow-auto px-12 py-6\"\n data-testid=\"connector-right-pane\"\n >\n <div className=\"flex items-center gap-[4px]\">\n <p className=\"text-[var(--text-primary)] font-semibold\">配置</p>\n {selectedPlatformHelpLink && (\n <HelpPrompt\n href={selectedPlatformHelpLink.href}\n tooltip=\"查看帮助文档\"\n ariaLabel=\"查看帮助文档\"\n testId={`platform-help-link-${selectedPlatform?.id}`}\n />\n )}\n </div>\n {selectedPlatform &&\n (() => {\n const platform = selectedPlatform;\n const guideSteps = platform.steps.slice(0, -1);\n const docsLink = parseDocsLink(platform.docsUrl);\n const saveStepNum = guideSteps.length + 2;\n\n return (\n <div className=\"space-y-3.5\" data-testid={`platform-card-${platform.id}`}>\n {QR_ONLY_PLATFORM_IDS.has(platform.id) && (\n <div className=\"space-y-3.5\">\n {platform.steps.map((step, idx) => (\n <div key={idx} className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <StepBadge num={idx + 1} />\n <span className=\"text-[14px]\">{step}</span>\n </div>\n {idx === 0 && (\n <div className=\"ml-[26px]\">\n {platform.id === 'feishu' ? (\n <FeishuQrPanel\n configured={platform.configured}\n onConfirmed={() => void fetchStatus({ background: true })}\n onDisconnected={() => void fetchStatus({ background: true })}\n />\n ) : (\n <WeixinQrPanel\n configured={platform.configured}\n onConfigured={() => fetchStatus({ background: true })}\n onDisconnected={() => fetchStatus({ background: true })}\n />\n )}\n {/* F152: Feishu permission panel (whitelist) */}\n {platform.id === 'feishu' && platform.configured && <FeishuPermissionPanel />}\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {!QR_ONLY_PLATFORM_IDS.has(platform.id) && (\n <div className=\"space-y-3.5\">\n {guideSteps.map((step, idx) => (\n <div key={idx} className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <StepBadge num={idx + 1} />\n <span className=\"text-[14px]\">{step}</span>\n </div>\n {idx === 0 && docsLink && (\n <a\n href={docsLink.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"ui-button-default ml-[26px] inline-flex items-center gap-1.5\"\n >\n <ExternalLinkIcon />\n <span>\n {docsLink.hostname} {'->'} 查看官方文档\n </span>\n </a>\n )}\n </div>\n ))}\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <StepBadge num={guideSteps.length + 1} />\n <span className=\"text-[14px]\">填写应用凭证</span>\n </div>\n <div className=\"ml-[26px] space-y-4\">\n {platform.fields.map((field) => (\n <div key={field.envName} className=\"w-1/2\">\n <label htmlFor={`config-${field.envName}`} className=\"mb-1 block text-sm\">\n {field.label}\n {field.sensitive && (\n <span\n className=\"ml-1 inline-flex align-middle text-[var(--state-warning-text)]\"\n data-testid={`connector-lock-${platform.id}`}\n >\n <ConnectorLockIcon platformId={platform.id} />\n </span>\n )}\n </label>\n {field.sensitive ? (\n <PasswordField\n id={`config-${field.envName}`}\n name={`connector-${field.envName}`}\n placeholder={field.currentValue ? '已设置(输入新值覆盖)' : '未设置'}\n value={fieldValues[field.envName] ?? ''}\n onChange={(e) =>\n setFieldValues((prev) => ({ ...prev, [field.envName]: e.target.value }))\n }\n autoComplete=\"new-password\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n data-form-type=\"other\"\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n className=\"ui-input\"\n data-testid={`field-${field.envName}`}\n toggleTestId={`connector-password-toggle-${field.envName}`}\n />\n ) : (\n <input\n id={`config-${field.envName}`}\n type=\"text\"\n name={`connector-${field.envName}`}\n placeholder={field.currentValue ?? '未设置'}\n value={fieldValues[field.envName] ?? ''}\n onChange={(e) =>\n setFieldValues((prev) => ({ ...prev, [field.envName]: e.target.value }))\n }\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n data-form-type=\"other\"\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n className=\"ui-input\"\n data-testid={`field-${field.envName}`}\n />\n )}\n </div>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <StepBadge num={saveStepNum} />\n <span className=\"text-[14px]\">测试连接并保存</span>\n </div>\n {saveResult && (\n <div\n className={`ml-[26px] rounded-[var(--radius-md)] px-3 py-2 text-xs ${\n saveResult.type === 'success' ? 'ui-status-success' : 'ui-status-error'\n }`}\n data-testid=\"save-result\"\n >\n {saveResult.message}\n </div>\n )}\n <div className=\"ml-[26px] flex items-center gap-2\">\n <Button\n variant=\"default\"\n onClick={() => void handleTestConnection(platform)}\n disabled={testing || isRefreshing}\n >\n <span className=\"flex items-center gap-1\">\n <WifiIcon />\n {testing ? '测试中...' : '测试连接'}\n </span>\n </Button>\n <Button\n variant=\"major\"\n onClick={() => handleSave(platform)}\n disabled={saving || isRefreshing}\n data-testid={`save-${platform.id}`}\n >\n {saving ? '保存中...' : '保存配置'}\n </Button>\n {platform.configured && (\n <Button\n variant=\"default\"\n onClick={() => setConfirmDisconnectPlatformId(platform.id)}\n disabled={disconnecting === platform.id || isRefreshing}\n className=\"text-red-500 hover:text-red-700\"\n data-testid={`disconnect-${platform.id}`}\n >\n {disconnecting === platform.id ? '断开中...' : '断开连接'}\n </Button>\n )}\n <ActionConfirmModal\n open={confirmDisconnectPlatformId === platform.id}\n title=\"断开连接\"\n message=\"是否确认断开连接?\"\n confirmDisabled={disconnecting === platform.id}\n modalTestId={`disconnect-${platform.id}-confirm-modal`}\n confirmTestId={`disconnect-${platform.id}-confirm-submit`}\n cancelTestId={`disconnect-${platform.id}-confirm-cancel`}\n onCancel={() => setConfirmDisconnectPlatformId(null)}\n onConfirm={handleConfirmDisconnect}\n />\n </div>\n </div>\n </div>\n )}\n </div>\n );\n })()}\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { ConnectorConfigTab } from './components/ConnectorConfigTab';\n\nexport function ChannelsPanel() {\n return (\n <div className=\"ui-page-shell\">\n <div className=\"ui-page-header\">\n <h1 className=\"ui-page-title\">渠道</h1>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n <ConnectorConfigTab />\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { ChannelsPanel } from '@/components/channels-panel/ChannelsPanel';\n\nexport default function ChannelsPage() {\n return (\n <div className=\"h-full overflow-hidden ui-shell-surface px-8 py-8\">\n <ChannelsPanel />\n </div>\n );\n}\n"],"names":["ActionConfirmModal","open","title","message","confirmLabel","cancelLabel","confirmDisabled","modalTestId","confirmTestId","cancelTestId","onConfirm","onCancel","useEffect","handleKey","event","jsx","jsxs","Button","SVG_PROPS","PLATFORM_VISUALS","DEFAULT_VISUAL","StepBadge","num","ExternalLinkIcon","WifiIcon","SpinnerIcon","CheckCircleIcon","ConnectorLockIcon","platformId","EMPTY_CONFIG","apiFetchJson","url","init","res","apiFetch","err","FeishuPermissionPanel","config","setConfig","useState","loading","setLoading","saving","setSaving","newUserOpenId","setNewUserOpenId","newUserName","setNewUserName","fetchConfig","useCallback","data","saveConfig","patch","addUser","updated","removeUser","openId","u","e","ConnectorConnectedState","label","disconnecting","onDisconnect","disconnectTestId","children","confirmOpen","setConfirmOpen","handleConfirmDisconnect","statusMessage","status","errorMsg","FeishuQrPanel","configured","onConfirmed","onDisconnected","addToast","useToastStore","s","qrState","setQrState","setDisconnecting","qrUrl","setQrUrl","setErrorMsg","pollRef","useRef","terminalRef","requestSeqRef","stopPolling","schedulePoll","payload","intervalMs","poll","requestId","handleFetchQr","handleDisconnect","QR_POLL_INTERVAL_MS","QR_EXPIRE_MS","WeixinQrPanel","onConfigured","expireRef","confirmedNotifiedRef","prev","startPolling","scheduleNextPoll","QR_ONLY_PLATFORM_IDS","PLATFORM_HELP_LINKS","readStepText","step","trimmed","candidate","normalizePlatform","raw","index","item","idRaw","id","nameRaw","name","nameEnRaw","nameEn","docsUrlRaw","docsUrl","fields","field","current","envNameRaw","envName","labelRaw","currentValueRaw","currentValue","steps","normalized","parseDocsLink","rawUrl","normalizeConnectorFieldValue","value","collectConfiguredFieldEntries","fieldValues","ConnectorConfigTab","platforms","setPlatforms","isLoading","setIsLoading","isRefreshing","setIsRefreshing","selectedPlatformId","setSelectedPlatformId","setFieldValues","testing","setTesting","saveResult","setSaveResult","confirmDisconnectPlatformId","setConfirmDisconnectPlatformId","fetchStatus","options","background","nextPlatforms","platform","_a","handleSelect","handleSave","fieldEntries","updates","TESTABLE_PLATFORMS","testRes","testData","runtime","failedConnectors","handleTestConnection","pieces","warnings","warningText","botSuffix","_b","_d","_c","botText","CenteredLoadingState","selectedPlatform","selectedPlatformHelpLink","isSelected","v","HelpPrompt","guideSteps","docsLink","saveStepNum","idx","PasswordField","ChannelsPanel","ChannelsPage"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as t}from"./index-Cb4fQgom.js";const e="暂无数据";function i({title:a=e}){return t.jsxs("div",{className:"flex flex-col items-center text-center","data-testid":"empty-data-state",children:[t.jsx("img",{src:"/images/no-data.svg",alt:"","aria-hidden":"true","data-testid":"empty-data-image",className:"mb-[18px] h-[60px] w-[60px] shrink-0"}),t.jsx("p",{className:"text-sm font-medium text-[var(--text-primary)]","data-testid":"empty-data-title",children:a})]})}export{i as E};
|
|
2
|
+
//# sourceMappingURL=EmptyDataState-6mNx2Xhl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyDataState-6mNx2Xhl.js","sources":["../../src/components/shared/EmptyDataState.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nconst DEFAULT_EMPTY_TITLE = '暂无数据';\n\nexport function EmptyDataState({ title = DEFAULT_EMPTY_TITLE }: { title?: string }) {\n return (\n <div className=\"flex flex-col items-center text-center\" data-testid=\"empty-data-state\">\n <img\n src=\"/images/no-data.svg\"\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"empty-data-image\"\n className=\"mb-[18px] h-[60px] w-[60px] shrink-0\"\n />\n <p className=\"text-sm font-medium text-[var(--text-primary)]\" data-testid=\"empty-data-title\">\n {title}\n </p>\n </div>\n );\n}\n"],"names":["DEFAULT_EMPTY_TITLE","EmptyDataState","title","jsxs","jsx"],"mappings":"wCAQA,MAAMA,EAAsB,OAErB,SAASC,EAAe,CAAE,MAAAC,EAAQF,GAA2C,CAClF,OACEG,EAAAA,KAAC,MAAA,CAAI,UAAU,yCAAyC,cAAY,mBAClE,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,IAAI,sBACJ,IAAI,GACJ,cAAY,OACZ,cAAY,mBACZ,UAAU,sCAAA,CAAA,QAEX,IAAA,CAAE,UAAU,iDAAiD,cAAY,mBACvE,SAAAF,CAAA,CACH,CAAA,EACF,CAEJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./index-Cb4fQgom.js";import{O as h}from"./OverflowTooltip-CE5PjAb-.js";const p="查看帮助文档",k="inline-flex h-5 w-5 items-center justify-center text-[var(--help-prompt-icon)] transition-colors hover:text-[var(--help-prompt-icon-hover)]",f="h-4 w-4 shrink-0 bg-current [mask-image:url(/icons/userprofile/help.svg)] [mask-position:center] [mask-repeat:no-repeat] [mask-size:contain] [-webkit-mask-image:url(/icons/userprofile/help.svg)] [-webkit-mask-position:center] [-webkit-mask-repeat:no-repeat] [-webkit-mask-size:contain]";function d({tooltip:t=p,ariaLabel:r=t||p,href:n,target:l="_blank",rel:m="noopener noreferrer",onClick:i,className:o=k,iconClassName:u=f,testId:s}){const a=e.jsx("span",{"aria-hidden":"true",className:u}),c=n?e.jsx("a",{href:n,target:l,rel:m,"aria-label":r,onClick:i,className:o,"data-testid":s,children:a}):e.jsx("button",{type:"button","aria-label":r,onClick:i,className:o,"data-testid":s,children:a});return t?e.jsx(h,{content:t,forceShow:!0,className:"inline-flex",children:c}):c}export{d as H};
|
|
2
|
+
//# sourceMappingURL=HelpPrompt-BPzDcC8F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HelpPrompt-BPzDcC8F.js","sources":["../../src/components/shared/HelpPrompt.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { type MouseEventHandler } from 'react';\nimport { OverflowTooltip } from './OverflowTooltip';\n\ninterface HelpPromptProps {\n tooltip?: string;\n ariaLabel?: string;\n href?: string;\n target?: string;\n rel?: string;\n onClick?: MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;\n className?: string;\n iconClassName?: string;\n testId?: string;\n}\n\nconst DEFAULT_LABEL = '查看帮助文档';\nconst DEFAULT_TRIGGER_CLASS =\n 'inline-flex h-5 w-5 items-center justify-center text-[var(--help-prompt-icon)] transition-colors hover:text-[var(--help-prompt-icon-hover)]';\nconst DEFAULT_ICON_CLASS =\n 'h-4 w-4 shrink-0 bg-current [mask-image:url(/icons/userprofile/help.svg)] [mask-position:center] [mask-repeat:no-repeat] [mask-size:contain] [-webkit-mask-image:url(/icons/userprofile/help.svg)] [-webkit-mask-position:center] [-webkit-mask-repeat:no-repeat] [-webkit-mask-size:contain]';\n\nexport function HelpPrompt({\n tooltip = DEFAULT_LABEL,\n ariaLabel = tooltip || DEFAULT_LABEL,\n href,\n target = '_blank',\n rel = 'noopener noreferrer',\n onClick,\n className = DEFAULT_TRIGGER_CLASS,\n iconClassName = DEFAULT_ICON_CLASS,\n testId,\n}: HelpPromptProps) {\n const icon = <span aria-hidden=\"true\" className={iconClassName} />;\n\n const trigger = href ? (\n <a\n href={href}\n target={target}\n rel={rel}\n aria-label={ariaLabel}\n onClick={onClick}\n className={className}\n data-testid={testId}\n >\n {icon}\n </a>\n ) : (\n <button type=\"button\" aria-label={ariaLabel} onClick={onClick} className={className} data-testid={testId}>\n {icon}\n </button>\n );\n\n if (!tooltip) return trigger;\n\n return (\n <OverflowTooltip content={tooltip} forceShow className=\"inline-flex\">\n {trigger}\n </OverflowTooltip>\n );\n}\n"],"names":["DEFAULT_LABEL","DEFAULT_TRIGGER_CLASS","DEFAULT_ICON_CLASS","HelpPrompt","tooltip","ariaLabel","href","target","rel","onClick","className","iconClassName","testId","icon","jsx","trigger","OverflowTooltip"],"mappings":"0FAuBA,MAAMA,EAAgB,SAChBC,EACJ,8IACIC,EACJ,gSAEK,SAASC,EAAW,CACzB,QAAAC,EAAUJ,EACV,UAAAK,EAAYD,GAAWJ,EACvB,KAAAM,EACA,OAAAC,EAAS,SACT,IAAAC,EAAM,sBACN,QAAAC,EACA,UAAAC,EAAYT,EACZ,cAAAU,EAAgBT,EAChB,OAAAU,CACF,EAAoB,CAClB,MAAMC,EAAOC,EAAAA,IAAC,OAAA,CAAK,cAAY,OAAO,UAAWH,EAAe,EAE1DI,EAAUT,EACdQ,EAAAA,IAAC,IAAA,CACC,KAAAR,EACA,OAAAC,EACA,IAAAC,EACA,aAAYH,EACZ,QAAAI,EACA,UAAAC,EACA,cAAaE,EAEZ,SAAAC,CAAA,CAAA,EAGHC,EAAAA,IAAC,SAAA,CAAO,KAAK,SAAS,aAAYT,EAAW,QAAAI,EAAkB,UAAAC,EAAsB,cAAaE,EAC/F,SAAAC,CAAA,CACH,EAGF,OAAKT,EAGHU,MAACE,GAAgB,QAASZ,EAAS,UAAS,GAAC,UAAU,cACpD,SAAAW,CAAA,CACH,EALmBA,CAOvB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as U,c as w,u as z,r as t,j as m}from"./index-Cb4fQgom.js";import{u as B,M as L,C as X,a as G}from"./useSocket-y3-zWhVL.js";import{g as K}from"./thread-utils-Ct3yp4R3.js";import{a as C}from"./OverflowTooltip-CE5PjAb-.js";import"./useAgentData-D-k9cXfg.js";import"./chat-input-options-CpkOtPgQ.js";import"./helpers-CCilgpNy.js";import"./quick-actions-DzZE-zyP.js";import"./skill-options-cache-D1BJGTCU.js";import"./index-UBJEdbMO.js";import"./usePromptBlocks-5sz8Qh51.js";import"./Tab-FE0F2EQP.js";import"./SearchInput-tux8xXH1.js";const Q="__new__",I=200;function _(a){const o=a.replace(/[/\\]+$/,""),n=o.split(/[/\\]/).filter(Boolean);return n[n.length-1]??o}function V(a,o){return typeof o=="string"&&o.trim()?o:`Failed to create thread (HTTP ${a})`}function Y(a){return typeof a=="object"&&a!==null&&a.name==="AbortError"}function fe(){const a=U(),o=w(e=>e.setCurrentThread),n=w(e=>e.threads),b=w(e=>e.setPendingNewThreadSend),x=w(e=>e.attachPendingNewThreadTarget),N=w(e=>e.clearPendingNewThreadSend),{addToast:u}=z(),[k,j]=t.useState(!1),[s,E]=t.useState(null),[M,F]=t.useState(null),[W,v]=t.useState(null),h=t.useRef(null),D=t.useMemo(()=>({onMessage:()=>{},onThreadCreated:()=>{typeof window<"u"&&window.dispatchEvent(new CustomEvent("office-claw:threads-refresh"))}}),[]),R=t.useMemo(()=>n.map(e=>e.id),[n]);B(D,void 0,R);const H=t.useMemo(()=>K(n).map(e=>({path:e,name:_(e),title:e})),[n]),y=t.useCallback(e=>{E(e),F(_(e)),v(e)},[]),f=t.useCallback(()=>{var e;(e=h.current)==null||e.abort()},[]),O=t.useCallback(()=>{f(),E(null),F(null),v(null)},[f]),$=t.useCallback(e=>{f(),y(e)},[f,y]),J=t.useCallback(async()=>{f();const e=new AbortController;h.current=e;try{let c={method:"POST",signal:e.signal};if(s&&s.trim())c={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({initialPath:s}),signal:e.signal};else{const r=await C("/api/projects/cwd",{signal:e.signal});if(r.ok){const l=await r.json().catch(()=>null);typeof(l==null?void 0:l.workspacePath)=="string"&&l.workspacePath.trim()&&(c={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({initialDirectory:l.workspacePath}),signal:e.signal})}}const p=await C("/api/projects/pick-directory",c);if(p.status===204)return;if(!p.ok){const r=await p.json().catch(()=>null),l=typeof(r==null?void 0:r.error)=="string"&&r.error.trim()?r.error:"打开系统目录选择失败,请重试";u({type:"error",title:"选择文件夹失败",message:l,duration:3e3});return}const i=await p.json().catch(()=>null);if(typeof(i==null?void 0:i.path)=="string"&&i.path.trim()){y(i.path);return}u({type:"error",title:"选择文件夹失败",message:"系统目录选择未返回有效路径",duration:3e3})}catch(c){if(e.signal.aborted||Y(c))return;u({type:"error",title:"选择文件夹失败",message:"无法连接到后端服务,请稍后重试",duration:3e3})}finally{h.current===e&&(h.current=null)}},[f,u,y,s]);t.useEffect(()=>{o("default")},[o]),t.useEffect(()=>()=>{var e;(e=h.current)==null||e.abort(),h.current=null},[]);const q=t.useCallback(async(e,c,p,i,r)=>{var T,A;if(k)return;if(n.filter(d=>d.id!=="default").length>=I){u({type:"error",title:"会话数量已达上限",message:`当前会话数量已达到 ${I} 个上限,请删除一些会话后再创建新会话。`,duration:5e3});return}j(!0),b({requestId:((A=(T=globalThis.crypto)==null?void 0:T.randomUUID)==null?void 0:A.call(T))??`pending-${Date.now()}`,content:e,images:c,whisper:p,deliveryMode:i,createdAt:Date.now(),sendOptions:r});try{const d=typeof(r==null?void 0:r.workspacePathForNewThread)=="string"&&r.workspacePathForNewThread.trim()?r.workspacePathForNewThread.trim():null,P=await C("/api/threads",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s?{projectPath:s}:d?{projectPath:d}:{})});if(!P.ok){const S=await P.json().catch(()=>null);throw new Error(V(P.status,S==null?void 0:S.detail))}const g=await P.json();if(!(g!=null&&g.id))throw new Error("Failed to create thread");x(g.id),a(`/thread/${g.id}`)}catch(d){N(),console.error(d instanceof Error?d.message:"Failed to create thread")}finally{j(!1)}},[u,x,N,k,a,s,b,n]);return m.jsxs("div",{className:"chat-layout-container min-w-0 flex-1 h-full flex flex-col",style:{minWidth:L},children:[m.jsx("main",{className:"ui-shell-surface flex flex-1 min-h-0 flex-col overflow-y-auto px-0 py-4","data-testid":"new-thread-main",children:m.jsx("div",{className:"flex w-full flex-1 flex-col gap-4",children:m.jsx("div",{className:"flex flex-1 items-center justify-center",children:m.jsx(X,{onAgentsClick:()=>a("/agents"),onChannelsClick:()=>a("/channels"),fillAvailableHeight:!0})})})}),m.jsx(G,{threadId:Q,onSend:q,disabled:k,folderSelectionEnabled:!0,selectedFolderName:M,selectedFolderTitle:W,activeWorkspacePath:s,workspaceOptions:H,onSelectEmptyWorkspace:O,onSelectExistingWorkspace:$,onOpenFolderPicker:()=>void J()})]})}export{fe as default};
|
|
2
|
+
//# sourceMappingURL=HomePage-t78sDDUj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HomePage-t78sDDUj.js","sources":["../../src/pages/HomePage.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { useNavigate } from 'react-router-dom';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { ChatEmptyState } from '@/components/ChatEmptyState';\nimport { MAIN_PANEL_MIN_WIDTH } from '@/shared/constants';\nimport { ChatInput } from '@/components/chat-input/ChatInput';\nimport { getProjectPaths } from '@/components/thread-sidebar/thread-utils';\nimport type { SendMessageOptions, WhisperOptions } from '@/hooks/useSendMessage';\nimport { useSocket } from '@/hooks/useSocket';\nimport type { DeliveryMode } from '@/stores/chat-types';\nimport { useChatStore } from '@/stores/chatStore';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\n\nconst HOME_DRAFT_THREAD_ID = '__new__';\nconst MAX_SESSIONS = 200;\n\nfunction getFolderNameFromPath(path: string): string {\n const normalized = path.replace(/[/\\\\]+$/, '');\n const segments = normalized.split(/[/\\\\]/).filter(Boolean);\n return segments[segments.length - 1] ?? normalized;\n}\n\nfunction getCreateThreadErrorMessage(status: number, detail?: unknown): string {\n if (typeof detail === 'string' && detail.trim()) return detail;\n return `Failed to create thread (HTTP ${status})`;\n}\n\nfunction isAbortError(error: unknown): boolean {\n return typeof error === 'object' && error !== null && (error as { name?: unknown }).name === 'AbortError';\n}\n\nexport default function HomePage() {\n const navigate = useNavigate();\n const setCurrentThread = useChatStore((s) => s.setCurrentThread);\n const threads = useChatStore((s) => s.threads);\n const setPendingNewThreadSend = useChatStore((s) => s.setPendingNewThreadSend);\n const attachPendingNewThreadTarget = useChatStore((s) => s.attachPendingNewThreadTarget);\n const clearPendingNewThreadSend = useChatStore((s) => s.clearPendingNewThreadSend);\n const { addToast } = useToastStore();\n const [isCreatingThread, setIsCreatingThread] = useState(false);\n const [selectedFolderPath, setSelectedFolderPath] = useState<string | null>(null);\n const [selectedFolderName, setSelectedFolderName] = useState<string | null>(null);\n const [selectedFolderTitle, setSelectedFolderTitle] = useState<string | null>(null);\n const activeFolderPickerAbortRef = useRef<AbortController | null>(null);\n const socketCallbacks = useMemo(\n () => ({\n onMessage: () => {},\n onThreadCreated: () => {\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('office-claw:threads-refresh'));\n }\n },\n }),\n [],\n );\n const watchedThreadIds = useMemo(() => threads.map((thread) => thread.id), [threads]);\n useSocket(socketCallbacks, undefined, watchedThreadIds);\n\n const workspaceOptions = useMemo(\n () =>\n getProjectPaths(threads).map((path) => ({\n path,\n name: getFolderNameFromPath(path),\n title: path,\n })),\n [threads],\n );\n\n const handleFolderSelect = useCallback((path: string) => {\n setSelectedFolderPath(path);\n setSelectedFolderName(getFolderNameFromPath(path));\n setSelectedFolderTitle(path);\n }, []);\n\n const abortActiveFolderPicker = useCallback(() => {\n activeFolderPickerAbortRef.current?.abort();\n }, []);\n\n const handleSelectEmptyWorkspace = useCallback(() => {\n abortActiveFolderPicker();\n setSelectedFolderPath(null);\n setSelectedFolderName(null);\n setSelectedFolderTitle(null);\n }, [abortActiveFolderPicker]);\n\n const handleSelectExistingWorkspace = useCallback((path: string) => {\n abortActiveFolderPicker();\n handleFolderSelect(path);\n }, [abortActiveFolderPicker, handleFolderSelect]);\n\n const handleOpenFolderPicker = useCallback(async () => {\n abortActiveFolderPicker();\n const controller = new AbortController();\n activeFolderPickerAbortRef.current = controller;\n\n try {\n let pickerRequest: {\n method: 'POST';\n headers?: { 'Content-Type': 'application/json' };\n body?: string;\n signal: AbortSignal;\n } = {\n method: 'POST',\n signal: controller.signal,\n };\n\n if (selectedFolderPath && selectedFolderPath.trim()) {\n pickerRequest = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ initialPath: selectedFolderPath }),\n signal: controller.signal,\n };\n } else {\n const cwdRes = await apiFetch('/api/projects/cwd', { signal: controller.signal });\n if (cwdRes.ok) {\n const cwdData = await cwdRes.json().catch(() => null);\n if (typeof cwdData?.workspacePath === 'string' && cwdData.workspacePath.trim()) {\n pickerRequest = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ initialDirectory: cwdData.workspacePath }),\n signal: controller.signal,\n };\n }\n }\n }\n\n const res = await apiFetch('/api/projects/pick-directory', pickerRequest);\n if (res.status === 204) {\n return;\n }\n if (!res.ok) {\n const data = await res.json().catch(() => null);\n const message = typeof data?.error === 'string' && data.error.trim() ? data.error : '打开系统目录选择失败,请重试';\n addToast({\n type: 'error',\n title: '选择文件夹失败',\n message,\n duration: 3000,\n });\n return;\n }\n const data = await res.json().catch(() => null);\n if (typeof data?.path === 'string' && data.path.trim()) {\n handleFolderSelect(data.path);\n return;\n }\n addToast({\n type: 'error',\n title: '选择文件夹失败',\n message: '系统目录选择未返回有效路径',\n duration: 3000,\n });\n } catch (error) {\n if (controller.signal.aborted || isAbortError(error)) {\n return;\n }\n addToast({\n type: 'error',\n title: '选择文件夹失败',\n message: '无法连接到后端服务,请稍后重试',\n duration: 3000,\n });\n } finally {\n if (activeFolderPickerAbortRef.current === controller) {\n activeFolderPickerAbortRef.current = null;\n }\n }\n }, [abortActiveFolderPicker, addToast, handleFolderSelect, selectedFolderPath]);\n\n useEffect(() => {\n setCurrentThread('default');\n }, [setCurrentThread]);\n\n useEffect(() => {\n return () => {\n activeFolderPickerAbortRef.current?.abort();\n activeFolderPickerAbortRef.current = null;\n };\n }, []);\n\n const handleSend = useCallback(\n async (\n content: string,\n images?: File[],\n whisper?: WhisperOptions,\n deliveryMode?: DeliveryMode,\n sendOptions?: SendMessageOptions,\n ) => {\n if (isCreatingThread) return;\n\n const actualThreadCount = threads.filter((t) => t.id !== 'default').length;\n if (actualThreadCount >= MAX_SESSIONS) {\n addToast({\n type: 'error',\n title: '会话数量已达上限',\n message: `当前会话数量已达到 ${MAX_SESSIONS} 个上限,请删除一些会话后再创建新会话。`,\n duration: 5000,\n });\n return;\n }\n\n setIsCreatingThread(true);\n setPendingNewThreadSend({\n requestId: globalThis.crypto?.randomUUID?.() ?? `pending-${Date.now()}`,\n content,\n images,\n whisper,\n deliveryMode,\n createdAt: Date.now(),\n sendOptions,\n });\n\n try {\n const fallbackWorkspacePath =\n typeof sendOptions?.workspacePathForNewThread === 'string' && sendOptions.workspacePathForNewThread.trim()\n ? sendOptions.workspacePathForNewThread.trim()\n : null;\n const createThreadPayload = selectedFolderPath\n ? { projectPath: selectedFolderPath }\n : fallbackWorkspacePath\n ? { projectPath: fallbackWorkspacePath }\n : {};\n const response = await apiFetch('/api/threads', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(createThreadPayload),\n });\n\n if (!response.ok) {\n const data = await response.json().catch(() => null);\n throw new Error(getCreateThreadErrorMessage(response.status, data?.detail));\n }\n\n const thread = await response.json();\n if (!thread?.id) {\n throw new Error('Failed to create thread');\n }\n\n attachPendingNewThreadTarget(thread.id);\n navigate(`/thread/${thread.id}`);\n } catch (err) {\n clearPendingNewThreadSend();\n console.error(err instanceof Error ? err.message : 'Failed to create thread');\n } finally {\n setIsCreatingThread(false);\n }\n },\n [\n addToast,\n attachPendingNewThreadTarget,\n clearPendingNewThreadSend,\n isCreatingThread,\n navigate,\n selectedFolderPath,\n setPendingNewThreadSend,\n threads,\n ],\n );\n\n return (\n <div className=\"chat-layout-container min-w-0 flex-1 h-full flex flex-col\" style={{ minWidth: MAIN_PANEL_MIN_WIDTH }}>\n <main className=\"ui-shell-surface flex flex-1 min-h-0 flex-col overflow-y-auto px-0 py-4\" data-testid=\"new-thread-main\">\n <div className=\"flex w-full flex-1 flex-col gap-4\">\n <div className=\"flex flex-1 items-center justify-center\">\n <ChatEmptyState\n onAgentsClick={() => navigate('/agents')}\n onChannelsClick={() => navigate('/channels')}\n fillAvailableHeight\n />\n </div>\n </div>\n </main>\n <ChatInput\n threadId={HOME_DRAFT_THREAD_ID}\n onSend={handleSend}\n disabled={isCreatingThread}\n folderSelectionEnabled\n selectedFolderName={selectedFolderName}\n selectedFolderTitle={selectedFolderTitle}\n activeWorkspacePath={selectedFolderPath}\n workspaceOptions={workspaceOptions}\n onSelectEmptyWorkspace={handleSelectEmptyWorkspace}\n onSelectExistingWorkspace={handleSelectExistingWorkspace}\n onOpenFolderPicker={() => void handleOpenFolderPicker()}\n />\n </div>\n );\n}\n"],"names":["HOME_DRAFT_THREAD_ID","MAX_SESSIONS","getFolderNameFromPath","path","normalized","segments","getCreateThreadErrorMessage","status","detail","isAbortError","error","HomePage","navigate","useNavigate","setCurrentThread","useChatStore","s","threads","setPendingNewThreadSend","attachPendingNewThreadTarget","clearPendingNewThreadSend","addToast","useToastStore","isCreatingThread","setIsCreatingThread","useState","selectedFolderPath","setSelectedFolderPath","selectedFolderName","setSelectedFolderName","selectedFolderTitle","setSelectedFolderTitle","activeFolderPickerAbortRef","useRef","socketCallbacks","useMemo","watchedThreadIds","thread","useSocket","workspaceOptions","getProjectPaths","handleFolderSelect","useCallback","abortActiveFolderPicker","_a","handleSelectEmptyWorkspace","handleSelectExistingWorkspace","handleOpenFolderPicker","controller","pickerRequest","cwdRes","apiFetch","cwdData","res","data","message","useEffect","handleSend","content","images","whisper","deliveryMode","sendOptions","t","_b","fallbackWorkspacePath","response","err","jsxs","MAIN_PANEL_MIN_WIDTH","jsx","ChatEmptyState","ChatInput"],"mappings":"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"}
|