From bbe975c6bca3e3afb20de217deb67c0920b2bd6d Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:16:15 +0800 Subject: [PATCH] feat: enhance model plugin workflow checks and model provider management UX (#33289) Signed-off-by: yyh Signed-off-by: dependabot[bot] Co-authored-by: CodingOnStar Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: -LAN- Co-authored-by: statxc --- .github/workflows/web-tests.yml | 4 +- .../billing/pricing-modal-flow.test.tsx | 19 +- .../plugins/plugin-card-rendering.test.tsx | 17 +- .../account-page/AvatarWithEdit.tsx | 2 +- .../account-page/email-change-modal.tsx | 42 +- .../(commonLayout)/account-page/index.tsx | 28 +- .../csv-uploader.tsx | 2 +- .../warning-mask/has-not-set-api.spec.tsx | 22 +- .../base/warning-mask/has-not-set-api.tsx | 42 +- .../config-prompt/simple-prompt-input.tsx | 2 +- .../config/agent/prompt-editor.tsx | 2 +- .../code-generator/get-code-generator-res.tsx | 10 +- .../dataset-config/settings-modal/index.tsx | 10 +- .../model-parameter-trigger.spec.tsx | 139 ++- .../model-parameter-trigger.tsx | 138 ++- .../app/configuration/debug/index.spec.tsx | 1021 +++++++++++++++++ .../app/configuration/debug/index.tsx | 27 +- .../components/app/configuration/index.tsx | 8 +- .../tools/external-data-tool-modal.tsx | 2 +- .../app/create-from-dsl-modal/index.tsx | 10 +- .../app/create-from-dsl-modal/uploader.tsx | 2 +- web/app/components/app/log/list.tsx | 24 +- .../line/financeAndECommerce/credits-coin.svg | 4 + .../solid/general/arrow-down-round-fill.svg | 2 +- .../assets/vender/solid/general/x-circle.svg | 2 +- .../line/financeAndECommerce/CreditsCoin.json | 35 + .../line/financeAndECommerce/CreditsCoin.tsx | 20 + .../vender/line/financeAndECommerce/index.ts | 1 + .../__tests__/variable-block.spec.tsx | 2 +- .../workflow-variable-block/component.tsx | 24 +- .../use-llm-model-plugin-installed.spec.ts | 75 ++ .../use-llm-model-plugin-installed.ts | 23 + .../components/base/prompt-editor/types.ts | 6 +- .../base/tag-input/__tests__/interop.spec.tsx | 57 + web/app/components/base/tag-input/index.tsx | 6 +- web/app/components/base/ui/dialog/index.tsx | 4 + .../billing/pricing/__tests__/dialog.spec.tsx | 93 ++ .../billing/pricing/__tests__/footer.spec.tsx | 2 +- .../billing/pricing/__tests__/header.spec.tsx | 15 +- .../billing/pricing/__tests__/index.spec.tsx | 8 +- web/app/components/billing/pricing/footer.tsx | 7 +- web/app/components/billing/pricing/header.tsx | 3 +- web/app/components/billing/pricing/index.tsx | 73 +- .../plan-switcher/__tests__/index.spec.tsx | 2 +- .../billing/pricing/plan-switcher/index.tsx | 2 +- web/app/components/billing/pricing/types.ts | 6 + .../firecrawl/__tests__/index.spec.tsx | 53 +- .../create/website/firecrawl/index.tsx | 70 +- .../detail/batch-modal/csv-uploader.tsx | 2 +- .../detail/completed/new-child-segment.tsx | 6 +- .../datasets/documents/detail/new-segment.tsx | 6 +- .../__tests__/document-settings.spec.tsx | 4 +- .../detail/settings/document-settings.tsx | 14 +- .../external-api/external-api-modal/index.tsx | 12 +- .../settings/form/__tests__/index.spec.tsx | 44 + .../__tests__/indexing-section.spec.tsx | 584 +++++----- .../settings/summary-index-setting.tsx | 22 +- .../workplace-selector/index.tsx | 8 +- .../account-setting/__tests__/index.spec.tsx | 278 +++-- .../__tests__/menu-dialog.spec.tsx | 3 +- .../header/account-setting/index.tsx | 49 +- .../__tests__/index.spec.tsx | 84 +- .../edit-workspace-modal/dialog.spec.tsx | 57 + .../edit-workspace-modal/index.module.css | 0 .../edit-workspace-modal/index.tsx | 135 ++- .../account-setting/members-page/index.tsx | 35 +- .../members-page/operation/index.tsx | 10 +- .../menu-dialog.dialog.spec.tsx | 42 + .../header/account-setting/menu-dialog.tsx | 58 +- .../__tests__/hooks.spec.ts | 150 ++- .../__tests__/index.spec.tsx | 250 ++-- .../install-from-marketplace.spec.tsx | 9 +- .../__tests__/utils.spec.ts | 11 + .../model-provider-page/atoms.spec.tsx | 399 +++++++ .../model-provider-page/atoms.ts | 35 + .../derive-model-status.spec.ts | 160 +++ .../derive-model-status.ts | 72 ++ .../model-provider-page/hooks.ts | 62 +- .../index.non-cloud.spec.tsx | 89 ++ .../model-provider-page/index.tsx | 83 +- .../install-from-marketplace.tsx | 26 +- .../__tests__/credential-item.spec.tsx | 27 +- .../model-auth/authorized/credential-item.tsx | 82 +- .../__tests__/use-credential-status.spec.tsx | 10 + .../model-auth/hooks/use-credential-status.ts | 4 +- .../model-provider-page/model-badge/index.tsx | 2 +- .../model-modal/__tests__/index.spec.tsx | 354 +++--- .../model-modal/dialog.spec.tsx | 271 +++++ .../model-provider-page/model-modal/index.tsx | 343 +++--- .../model-provider-page/model-name/index.tsx | 2 +- .../__tests__/index.spec.tsx | 72 +- .../__tests__/parameter-item.spec.tsx | 2 +- .../__tests__/presets-parameter.spec.tsx | 5 +- .../__tests__/trigger.spec.tsx | 390 +++++-- .../derive-trigger-status.spec.ts | 112 ++ .../derive-trigger-status.ts | 12 + .../model-parameter-modal/index.tsx | 234 ++-- .../parameter-item.select.spec.tsx | 48 + .../model-parameter-modal/parameter-item.tsx | 50 +- .../presets-parameter.tsx | 83 +- .../model-parameter-modal/trigger.tsx | 178 +-- .../deprecated-model-trigger.spec.tsx | 61 - .../__tests__/empty-trigger.spec.tsx | 31 - .../model-selector/__tests__/index.spec.tsx | 68 +- .../__tests__/model-trigger.spec.tsx | 91 -- .../__tests__/popup-item.spec.tsx | 263 +++-- .../model-selector/__tests__/popup.spec.tsx | 509 +++++++- .../deprecated-model-trigger.tsx | 54 - .../model-selector/empty-trigger.tsx | 42 - .../model-selector/index.tsx | 120 +- .../model-selector-trigger.spec.tsx | 290 +++++ .../model-selector/model-selector-trigger.tsx | 175 +++ .../model-selector/model-trigger.tsx | 78 -- .../model-selector/popover.spec.tsx | 77 ++ .../model-selector/popup-item.tsx | 240 ++-- .../model-selector/popup.tsx | 283 ++++- .../__tests__/add-model-button.spec.tsx | 17 - .../__tests__/credential-panel.spec.tsx | 578 +++++++--- .../__tests__/index.spec.tsx | 220 ++-- .../__tests__/model-list-item.spec.tsx | 18 + .../__tests__/quota-panel.spec.tsx | 155 ++- .../provider-added-card/add-model-button.tsx | 27 - .../provider-added-card/credential-panel.tsx | 220 ++-- .../provider-added-card/index.tsx | 182 +-- .../api-key-section.spec.tsx | 142 +++ .../model-auth-dropdown/api-key-section.tsx | 91 ++ .../credits-exhausted-alert.spec.tsx | 104 ++ .../credits-exhausted-alert.stories.tsx | 78 ++ .../credits-exhausted-alert.tsx | 71 ++ .../credits-fallback-alert.tsx | 28 + .../model-auth-dropdown/dialog.spec.tsx | 152 +++ .../dropdown-content.spec.tsx | 435 +++++++ .../model-auth-dropdown/dropdown-content.tsx | 131 +++ .../model-auth-dropdown/index.spec.tsx | 211 ++++ .../model-auth-dropdown/index.tsx | 85 ++ .../usage-priority-section.spec.tsx | 66 ++ .../usage-priority-section.tsx | 70 ++ .../use-activate-credential.spec.tsx | 127 ++ .../use-activate-credential.ts | 52 + .../provider-added-card/model-list-item.tsx | 20 +- .../provider-card-actions.spec.tsx | 264 +++++ .../provider-card-actions.tsx | 149 +++ .../quota-panel.module.css | 8 + .../provider-added-card/quota-panel.tsx | 182 +-- .../system-quota-card.spec.tsx | 89 ++ .../provider-added-card/system-quota-card.tsx | 67 ++ .../use-change-provider-priority.spec.ts | 208 ++++ .../use-change-provider-priority.ts | 53 + .../use-credential-panel-state.spec.ts | 295 +++++ .../use-credential-panel-state.ts | 109 ++ .../use-trial-credits.spec.ts | 88 ++ .../provider-added-card/use-trial-credits.ts | 15 + .../provider-icon/__tests__/index.spec.tsx | 35 + .../provider-icon/index.tsx | 6 +- .../model-provider-page/status-mapping.ts | 9 + .../supports-credits.spec.ts | 42 + .../model-provider-page/supports-credits.ts | 14 + .../__tests__/index.spec.tsx | 159 +-- .../system-model-selector/index.tsx | 279 +++-- .../model-provider-page/utils.ts | 25 + web/app/components/header/index.tsx | 2 +- .../plugins/__tests__/utils.spec.ts | 39 +- .../plugins/card/__tests__/index.spec.tsx | 37 + web/app/components/plugins/card/index.tsx | 13 +- web/app/components/plugins/hooks.spec.ts | 128 +++ web/app/components/plugins/hooks.ts | 41 +- .../install-bundle/__tests__/index.spec.tsx | 10 +- .../__tests__/use-install-multi-state.spec.ts | 120 ++ .../steps/hooks/use-install-multi-state.ts | 133 ++- .../marketplace/__tests__/atoms.spec.tsx | 111 +- .../__tests__/plugin-type-switch.spec.tsx | 28 +- .../marketplace/__tests__/utils.spec.ts | 18 + .../components/plugins/marketplace/utils.ts | 2 +- .../plugins/plugin-auth/authorized/index.tsx | 4 +- .../__tests__/detail-header.spec.tsx | 49 +- .../__tests__/operation-dropdown.spec.tsx | 47 +- .../__tests__/header-modals.spec.tsx | 32 +- .../components/header-modals.tsx | 55 +- .../__tests__/use-plugin-operations.spec.ts | 34 + .../hooks/use-plugin-operations.ts | 24 +- .../detail-header/index.tsx | 56 +- .../model-selector/__tests__/index.spec.tsx | 165 ++- .../model-selector/index.tsx | 187 ++- .../operation-dropdown.tsx | 132 +-- .../plugin-tasks/__tests__/index.spec.tsx | 14 +- .../__tests__/error-plugin-item.spec.tsx | 380 ++++++ .../components/__tests__/plugin-item.spec.tsx | 221 ++++ .../__tests__/plugin-section.spec.tsx | 164 +++ .../__tests__/plugin-task-list.spec.tsx | 251 ++++ .../__tests__/task-status-indicator.spec.tsx | 237 ++++ .../components/error-plugin-item.tsx | 134 +++ .../plugin-tasks/components/plugin-item.tsx | 60 + .../components/plugin-section.tsx | 67 ++ .../components/plugin-task-list.tsx | 159 +-- .../plugins/plugin-page/plugins-panel.tsx | 21 +- web/app/components/plugins/types.ts | 3 + .../update-plugin/__tests__/index.spec.tsx | 100 +- .../update-plugin/downgrade-warning.tsx | 4 +- .../update-plugin/from-market-place.tsx | 149 ++- .../update-plugin/plugin-version-picker.tsx | 104 +- web/app/components/plugins/utils.ts | 26 + .../rag-pipeline-header/publisher/popup.tsx | 16 +- web/app/components/tools/types.ts | 47 +- .../workflow/__tests__/workflow-test-env.tsx | 18 +- web/app/components/workflow/block-icon.tsx | 23 +- .../components/workflow/header/checklist.tsx | 201 ---- .../workflow/header/checklist/index.spec.tsx | 131 +++ .../workflow/header/checklist/index.tsx | 151 +++ .../header/checklist/item-indicator.tsx | 21 + .../header/checklist/node-group.spec.tsx | 61 + .../workflow/header/checklist/node-group.tsx | 75 ++ .../header/checklist/plugin-group.spec.tsx | 96 ++ .../header/checklist/plugin-group.tsx | 99 ++ .../workflow/header/run-mode.spec.tsx | 150 +++ .../components/workflow/header/run-mode.tsx | 4 +- .../hooks/__tests__/use-checklist.spec.ts | 138 ++- .../use-node-plugin-installation.spec.ts | 253 ++++ .../workflow/hooks/use-checklist.ts | 266 +++-- .../hooks/use-node-plugin-installation.ts | 119 +- .../workflow/hooks/use-nodes-interactions.ts | 2 - .../nodes/_base/components/field.spec.tsx | 56 + .../workflow/nodes/_base/components/field.tsx | 7 +- .../components/layout/field-title.spec.tsx | 67 ++ .../_base/components/layout/field-title.tsx | 36 +- .../_base/components/node-control.spec.tsx | 137 +++ .../nodes/_base/components/node-control.tsx | 7 +- .../nodes/_base/components/prompt/editor.tsx | 7 +- .../variable-label/base/variable-label.tsx | 29 +- .../workflow-panel/last-run/use-last-run.ts | 8 +- .../components/workflow/nodes/_base/node.tsx | 11 +- .../workflow/nodes/data-source/node.tsx | 19 +- .../components/chunk-structure/index.spec.tsx | 77 ++ .../components/chunk-structure/index.tsx | 6 +- .../components/embedding-model.spec.tsx | 62 + .../components/embedding-model.tsx | 3 + .../reranking-model-selector.spec.tsx | 121 ++ .../reranking-model-selector.tsx | 8 +- .../nodes/knowledge-base/default.spec.ts | 74 ++ .../workflow/nodes/knowledge-base/default.ts | 88 +- .../hooks/use-embedding-model-status.ts | 61 + .../nodes/knowledge-base/node.spec.tsx | 233 ++++ .../workflow/nodes/knowledge-base/node.tsx | 218 +++- .../nodes/knowledge-base/panel.spec.tsx | 198 ++++ .../workflow/nodes/knowledge-base/panel.tsx | 69 ++ .../workflow/nodes/knowledge-base/types.ts | 3 +- .../nodes/knowledge-base/utils.spec.ts | 226 ++++ .../workflow/nodes/knowledge-base/utils.ts | 179 +++ .../workflow/nodes/llm/default.spec.ts | 47 + .../components/workflow/nodes/llm/default.ts | 4 +- .../workflow/nodes/llm/panel.spec.tsx | 248 ++++ .../components/workflow/nodes/llm/panel.tsx | 22 +- .../workflow/nodes/llm/utils.spec.ts | 43 + .../components/workflow/nodes/llm/utils.ts | 29 + .../nodes/tool/__tests__/auth.spec.ts | 33 + .../nodes/tool/__tests__/node.spec.tsx | 99 ++ .../nodes/tool/__tests__/panel.spec.tsx | 309 +++++ .../components/workflow/nodes/tool/auth.ts | 14 + .../tool/hooks/__tests__/use-config.spec.tsx | 194 ++++ .../use-current-tool-collection.spec.tsx | 84 ++ .../use-get-data-for-check-more.spec.ts | 49 + .../use-single-run-form-params.spec.ts | 206 ++++ .../nodes/tool/{ => hooks}/use-config.ts | 64 +- .../tool/hooks/use-current-tool-collection.ts | 47 + .../use-get-data-for-check-more.ts | 2 +- .../{ => hooks}/use-single-run-form-params.ts | 18 +- .../components/workflow/nodes/tool/node.tsx | 39 +- .../components/workflow/nodes/tool/panel.tsx | 2 +- .../workflow/nodes/trigger-plugin/node.tsx | 17 +- .../components/object-value-item.tsx | 4 +- .../components/variable-modal.tsx | 14 +- .../panel/env-panel/variable-modal.tsx | 22 +- web/app/components/workflow/run/index.tsx | 6 +- .../workflow/store/workflow/node-slice.ts | 3 + web/app/components/workflow/types.ts | 1 - .../components/workflow/update-dsl-modal.tsx | 10 +- .../utils/plugin-install-check.spec.ts | 195 ++++ .../workflow/utils/plugin-install-check.ts | 95 ++ web/app/components/workflow/utils/plugin.ts | 4 + web/app/components/workflow/utils/tool.ts | 4 +- .../education-apply/education-apply-page.tsx | 18 +- web/context/modal-context-provider.tsx | 4 +- web/contract/console/model-providers.ts | 33 + web/contract/console/plugins.ts | 27 + web/contract/router.ts | 10 + web/eslint-suppressions.json | 366 +----- web/i18n/ar-TN/common.json | 2 - web/i18n/de-DE/common.json | 2 - web/i18n/en-US/app-debug.json | 5 + web/i18n/en-US/common.json | 54 +- web/i18n/en-US/plugin.json | 10 +- web/i18n/en-US/workflow.json | 13 +- web/i18n/es-ES/common.json | 2 - web/i18n/fa-IR/common.json | 2 - web/i18n/fr-FR/common.json | 2 - web/i18n/hi-IN/common.json | 2 - web/i18n/id-ID/common.json | 2 - web/i18n/it-IT/common.json | 2 - web/i18n/ja-JP/app-debug.json | 5 + web/i18n/ja-JP/common.json | 27 +- web/i18n/ja-JP/workflow.json | 1 + web/i18n/ko-KR/common.json | 2 - web/i18n/nl-NL/common.json | 2 - web/i18n/pl-PL/common.json | 2 - web/i18n/pt-BR/common.json | 2 - web/i18n/ro-RO/common.json | 2 - web/i18n/ru-RU/common.json | 2 - web/i18n/sl-SI/common.json | 2 - web/i18n/th-TH/common.json | 2 - web/i18n/tr-TR/common.json | 2 - web/i18n/uk-UA/common.json | 2 - web/i18n/vi-VN/common.json | 2 - web/i18n/zh-Hans/app-debug.json | 5 + web/i18n/zh-Hans/common.json | 50 +- web/i18n/zh-Hans/plugin.json | 10 +- web/i18n/zh-Hans/workflow.json | 13 +- web/i18n/zh-Hant/common.json | 2 - web/service/use-common.ts | 2 +- web/service/use-plugins.ts | 42 +- web/service/use-tools.ts | 12 +- 319 files changed, 19582 insertions(+), 5541 deletions(-) create mode 100644 web/app/components/app/configuration/debug/index.spec.tsx create mode 100644 web/app/components/base/icons/assets/vender/line/financeAndECommerce/credits-coin.svg create mode 100644 web/app/components/base/icons/src/vender/line/financeAndECommerce/CreditsCoin.json create mode 100644 web/app/components/base/icons/src/vender/line/financeAndECommerce/CreditsCoin.tsx create mode 100644 web/app/components/base/prompt-editor/plugins/workflow-variable-block/use-llm-model-plugin-installed.spec.ts create mode 100644 web/app/components/base/prompt-editor/plugins/workflow-variable-block/use-llm-model-plugin-installed.ts create mode 100644 web/app/components/base/tag-input/__tests__/interop.spec.tsx create mode 100644 web/app/components/billing/pricing/__tests__/dialog.spec.tsx create mode 100644 web/app/components/billing/pricing/types.ts create mode 100644 web/app/components/header/account-setting/members-page/edit-workspace-modal/dialog.spec.tsx delete mode 100644 web/app/components/header/account-setting/members-page/edit-workspace-modal/index.module.css create mode 100644 web/app/components/header/account-setting/menu-dialog.dialog.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/atoms.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/atoms.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/derive-model-status.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/derive-model-status.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/index.non-cloud.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-modal/dialog.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/derive-trigger-status.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/derive-trigger-status.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.select.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/deprecated-model-trigger.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/empty-trigger.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/model-trigger.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/empty-trigger.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/popover.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/add-model-button.spec.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/add-model-button.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/api-key-section.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/api-key-section.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.stories.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-fallback-alert.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/dialog.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/dropdown-content.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/dropdown-content.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/index.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/index.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/use-activate-credential.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/use-activate-credential.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.module.css create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/system-quota-card.spec.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/system-quota-card.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/status-mapping.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/supports-credits.spec.ts create mode 100644 web/app/components/header/account-setting/model-provider-page/supports-credits.ts create mode 100644 web/app/components/plugins/hooks.spec.ts create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/error-plugin-item.spec.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-item.spec.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-section.spec.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-task-list.spec.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/task-status-indicator.spec.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/error-plugin-item.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/plugin-item.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/components/plugin-section.tsx delete mode 100644 web/app/components/workflow/header/checklist.tsx create mode 100644 web/app/components/workflow/header/checklist/index.spec.tsx create mode 100644 web/app/components/workflow/header/checklist/index.tsx create mode 100644 web/app/components/workflow/header/checklist/item-indicator.tsx create mode 100644 web/app/components/workflow/header/checklist/node-group.spec.tsx create mode 100644 web/app/components/workflow/header/checklist/node-group.tsx create mode 100644 web/app/components/workflow/header/checklist/plugin-group.spec.tsx create mode 100644 web/app/components/workflow/header/checklist/plugin-group.tsx create mode 100644 web/app/components/workflow/header/run-mode.spec.tsx create mode 100644 web/app/components/workflow/hooks/__tests__/use-node-plugin-installation.spec.ts create mode 100644 web/app/components/workflow/nodes/_base/components/field.spec.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/layout/field-title.spec.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/node-control.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/components/chunk-structure/index.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/components/embedding-model.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/reranking-model-selector.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/default.spec.ts create mode 100644 web/app/components/workflow/nodes/knowledge-base/hooks/use-embedding-model-status.ts create mode 100644 web/app/components/workflow/nodes/knowledge-base/node.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/panel.spec.tsx create mode 100644 web/app/components/workflow/nodes/knowledge-base/utils.spec.ts create mode 100644 web/app/components/workflow/nodes/llm/default.spec.ts create mode 100644 web/app/components/workflow/nodes/llm/panel.spec.tsx create mode 100644 web/app/components/workflow/nodes/llm/utils.spec.ts create mode 100644 web/app/components/workflow/nodes/tool/__tests__/auth.spec.ts create mode 100644 web/app/components/workflow/nodes/tool/__tests__/node.spec.tsx create mode 100644 web/app/components/workflow/nodes/tool/__tests__/panel.spec.tsx create mode 100644 web/app/components/workflow/nodes/tool/auth.ts create mode 100644 web/app/components/workflow/nodes/tool/hooks/__tests__/use-config.spec.tsx create mode 100644 web/app/components/workflow/nodes/tool/hooks/__tests__/use-current-tool-collection.spec.tsx create mode 100644 web/app/components/workflow/nodes/tool/hooks/__tests__/use-get-data-for-check-more.spec.ts create mode 100644 web/app/components/workflow/nodes/tool/hooks/__tests__/use-single-run-form-params.spec.ts rename web/app/components/workflow/nodes/tool/{ => hooks}/use-config.ts (83%) create mode 100644 web/app/components/workflow/nodes/tool/hooks/use-current-tool-collection.ts rename web/app/components/workflow/nodes/tool/{ => hooks}/use-get-data-for-check-more.ts (87%) rename web/app/components/workflow/nodes/tool/{ => hooks}/use-single-run-form-params.ts (85%) create mode 100644 web/app/components/workflow/utils/plugin-install-check.spec.ts create mode 100644 web/app/components/workflow/utils/plugin-install-check.ts create mode 100644 web/app/components/workflow/utils/plugin.ts create mode 100644 web/contract/console/model-providers.ts create mode 100644 web/contract/console/plugins.ts diff --git a/.github/workflows/web-tests.yml b/.github/workflows/web-tests.yml index 11222146cf..be2595a599 100644 --- a/.github/workflows/web-tests.yml +++ b/.github/workflows/web-tests.yml @@ -29,8 +29,8 @@ jobs: strategy: fail-fast: false matrix: - shardIndex: [1, 2, 3, 4] - shardTotal: [4] + shardIndex: [1, 2, 3, 4, 5, 6] + shardTotal: [6] defaults: run: shell: bash diff --git a/web/__tests__/billing/pricing-modal-flow.test.tsx b/web/__tests__/billing/pricing-modal-flow.test.tsx index 6b8fb57f83..7326ee3559 100644 --- a/web/__tests__/billing/pricing-modal-flow.test.tsx +++ b/web/__tests__/billing/pricing-modal-flow.test.tsx @@ -295,24 +295,7 @@ describe('Pricing Modal Flow', () => { }) }) - // ─── 6. Close Handling ─────────────────────────────────────────────────── - describe('Close handling', () => { - it('should call onCancel when pressing ESC key', () => { - render() - - // ahooks useKeyPress listens on document for keydown events - document.dispatchEvent(new KeyboardEvent('keydown', { - key: 'Escape', - code: 'Escape', - keyCode: 27, - bubbles: true, - })) - - expect(onCancel).toHaveBeenCalledTimes(1) - }) - }) - - // ─── 7. Pricing URL ───────────────────────────────────────────────────── + // ─── 6. Pricing URL ───────────────────────────────────────────────────── describe('Pricing page URL', () => { it('should render pricing link with correct URL', () => { render() diff --git a/web/__tests__/plugins/plugin-card-rendering.test.tsx b/web/__tests__/plugins/plugin-card-rendering.test.tsx index 7abcb01b49..5bd7f0c8bf 100644 --- a/web/__tests__/plugins/plugin-card-rendering.test.tsx +++ b/web/__tests__/plugins/plugin-card-rendering.test.tsx @@ -8,6 +8,8 @@ import { cleanup, render, screen } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' +let mockTheme = 'light' + vi.mock('#i18n', () => ({ useTranslation: () => ({ t: (key: string) => key, @@ -19,16 +21,16 @@ vi.mock('@/context/i18n', () => ({ })) vi.mock('@/hooks/use-theme', () => ({ - default: () => ({ theme: 'light' }), + default: () => ({ theme: mockTheme }), })) vi.mock('@/i18n-config', () => ({ renderI18nObject: (obj: Record, locale: string) => obj[locale] || obj.en_US || '', })) -vi.mock('@/types/app', () => ({ - Theme: { dark: 'dark', light: 'light' }, -})) +vi.mock('@/types/app', async () => { + return vi.importActual('@/types/app') +}) vi.mock('@/utils/classnames', () => ({ cn: (...args: unknown[]) => args.filter(a => typeof a === 'string' && a).join(' '), @@ -100,6 +102,7 @@ type CardPayload = Parameters[0]['payload'] describe('Plugin Card Rendering Integration', () => { beforeEach(() => { cleanup() + mockTheme = 'light' }) const makePayload = (overrides = {}) => ({ @@ -194,9 +197,7 @@ describe('Plugin Card Rendering Integration', () => { }) it('uses dark icon when theme is dark and icon_dark is provided', () => { - vi.doMock('@/hooks/use-theme', () => ({ - default: () => ({ theme: 'dark' }), - })) + mockTheme = 'dark' const payload = makePayload({ icon: 'https://example.com/icon-light.png', @@ -204,7 +205,7 @@ describe('Plugin Card Rendering Integration', () => { }) render() - expect(screen.getByTestId('card-icon')).toBeInTheDocument() + expect(screen.getByTestId('card-icon')).toHaveTextContent('https://example.com/icon-dark.png') }) it('shows loading placeholder when isLoading is true', () => { diff --git a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx index 9bd32d2576..3fc677d8d8 100644 --- a/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx +++ b/web/app/account/(commonLayout)/account-page/AvatarWithEdit.tsx @@ -160,7 +160,7 @@ const AvatarWithEdit = ({ onSave, ...props }: AvatarWithEditProps) => { isShow={isShowDeleteConfirm} onClose={() => setIsShowDeleteConfirm(false)} > -
{t('avatar.deleteTitle', { ns: 'common' })}
+
{t('avatar.deleteTitle', { ns: 'common' })}

{t('avatar.deleteDescription', { ns: 'common' })}

diff --git a/web/app/account/(commonLayout)/account-page/email-change-modal.tsx b/web/app/account/(commonLayout)/account-page/email-change-modal.tsx index 463c27294a..c146174ea9 100644 --- a/web/app/account/(commonLayout)/account-page/email-change-modal.tsx +++ b/web/app/account/(commonLayout)/account-page/email-change-modal.tsx @@ -209,14 +209,14 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => {
{step === STEP.start && ( <> -
{t('account.changeEmail.title', { ns: 'common' })}
+
{t('account.changeEmail.title', { ns: 'common' })}
-
{t('account.changeEmail.authTip', { ns: 'common' })}
-
+
{t('account.changeEmail.authTip', { ns: 'common' })}
+
}} + components={{ email: }} values={{ email }} />
@@ -241,19 +241,19 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => { )} {step === STEP.verifyOrigin && ( <> -
{t('account.changeEmail.verifyEmail', { ns: 'common' })}
+
{t('account.changeEmail.verifyEmail', { ns: 'common' })}
-
+
}} + components={{ email: }} values={{ email }} />
-
{t('account.changeEmail.codeLabel', { ns: 'common' })}
+
{t('account.changeEmail.codeLabel', { ns: 'common' })}
{ {t('operation.cancel', { ns: 'common' })}
-
+
{t('account.changeEmail.resendTip', { ns: 'common' })} {time > 0 && ( {t('account.changeEmail.resendCount', { ns: 'common', count: time })} )} {!time && ( - {t('account.changeEmail.resend', { ns: 'common' })} + {t('account.changeEmail.resend', { ns: 'common' })} )}
)} {step === STEP.newEmail && ( <> -
{t('account.changeEmail.newEmail', { ns: 'common' })}
+
{t('account.changeEmail.newEmail', { ns: 'common' })}
-
{t('account.changeEmail.content3', { ns: 'common' })}
+
{t('account.changeEmail.content3', { ns: 'common' })}
-
{t('account.changeEmail.emailLabel', { ns: 'common' })}
+
{t('account.changeEmail.emailLabel', { ns: 'common' })}
{ destructive={newEmailExited || unAvailableEmail} /> {newEmailExited && ( -
{t('account.changeEmail.existingEmail', { ns: 'common' })}
+
{t('account.changeEmail.existingEmail', { ns: 'common' })}
)} {unAvailableEmail && ( -
{t('account.changeEmail.unAvailableEmail', { ns: 'common' })}
+
{t('account.changeEmail.unAvailableEmail', { ns: 'common' })}
)}
@@ -331,19 +331,19 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => { )} {step === STEP.verifyNew && ( <> -
{t('account.changeEmail.verifyNew', { ns: 'common' })}
+
{t('account.changeEmail.verifyNew', { ns: 'common' })}
-
+
}} + components={{ email: }} values={{ email: mail }} />
-
{t('account.changeEmail.codeLabel', { ns: 'common' })}
+
{t('account.changeEmail.codeLabel', { ns: 'common' })}
{ {t('operation.cancel', { ns: 'common' })}
-
+
{t('account.changeEmail.resendTip', { ns: 'common' })} {time > 0 && ( {t('account.changeEmail.resendCount', { ns: 'common', count: time })} )} {!time && ( - {t('account.changeEmail.resend', { ns: 'common' })} + {t('account.changeEmail.resend', { ns: 'common' })} )}
diff --git a/web/app/account/(commonLayout)/account-page/index.tsx b/web/app/account/(commonLayout)/account-page/index.tsx index 58331e3a77..9a104619da 100644 --- a/web/app/account/(commonLayout)/account-page/index.tsx +++ b/web/app/account/(commonLayout)/account-page/index.tsx @@ -145,7 +145,7 @@ export default function AccountPage() { imageUrl={icon_url} />
-
{item.name}
+
{item.name}
) } @@ -153,12 +153,12 @@ export default function AccountPage() { return ( <>
-

{t('account.myAccount', { ns: 'common' })}

+

{t('account.myAccount', { ns: 'common' })}

-

+

{userProfile.name} {isEducationAccount && ( @@ -167,16 +167,16 @@ export default function AccountPage() { )}

-

{userProfile.email}

+

{userProfile.email}

{t('account.name', { ns: 'common' })}
-
+
{userProfile.name}
-
+
{t('operation.edit', { ns: 'common' })}
@@ -184,11 +184,11 @@ export default function AccountPage() {
{t('account.email', { ns: 'common' })}
-
+
{userProfile.email}
{systemFeatures.enable_change_email && ( -
setShowUpdateEmail(true)}> +
setShowUpdateEmail(true)}> {t('operation.change', { ns: 'common' })}
)} @@ -198,8 +198,8 @@ export default function AccountPage() { systemFeatures.enable_email_password_login && (
-
{t('account.password', { ns: 'common' })}
-
{t('account.passwordTip', { ns: 'common' })}
+
{t('account.password', { ns: 'common' })}
+
{t('account.passwordTip', { ns: 'common' })}
@@ -226,7 +226,7 @@ export default function AccountPage() { onClose={() => setEditNameModalVisible(false)} className="!w-[420px] !p-6" > -
{t('account.editName', { ns: 'common' })}
+
{t('account.editName', { ns: 'common' })}
{t('account.name', { ns: 'common' })}
-
{userProfile.is_password_set ? t('account.resetPassword', { ns: 'common' }) : t('account.setPassword', { ns: 'common' })}
+
{userProfile.is_password_set ? t('account.resetPassword', { ns: 'common' }) : t('account.setPassword', { ns: 'common' })}
{userProfile.is_password_set && ( <>
{t('account.currentPassword', { ns: 'common' })}
@@ -279,7 +279,7 @@ export default function AccountPage() {
)} -
+
{userProfile.is_password_set ? t('account.newPassword', { ns: 'common' }) : t('account.password', { ns: 'common' })}
@@ -298,7 +298,7 @@ export default function AccountPage() {
-
{t('account.confirmPassword', { ns: 'common' })}
+
{t('account.confirmPassword', { ns: 'common' })}
= ({ />
{!file && ( -
+
diff --git a/web/app/components/app/configuration/base/warning-mask/has-not-set-api.spec.tsx b/web/app/components/app/configuration/base/warning-mask/has-not-set-api.spec.tsx index be4377bfd9..abcf5795d0 100644 --- a/web/app/components/app/configuration/base/warning-mask/has-not-set-api.spec.tsx +++ b/web/app/components/app/configuration/base/warning-mask/has-not-set-api.spec.tsx @@ -2,25 +2,19 @@ import { fireEvent, render, screen } from '@testing-library/react' import * as React from 'react' import HasNotSetAPI from './has-not-set-api' -describe('HasNotSetAPI WarningMask', () => { - it('should show default title when trial not finished', () => { - render() +describe('HasNotSetAPI', () => { + it('should render the empty state copy', () => { + render() - expect(screen.getByText('appDebug.notSetAPIKey.title')).toBeInTheDocument() - expect(screen.getByText('appDebug.notSetAPIKey.description')).toBeInTheDocument() + expect(screen.getByText('appDebug.noModelProviderConfigured')).toBeInTheDocument() + expect(screen.getByText('appDebug.noModelProviderConfiguredTip')).toBeInTheDocument() }) - it('should show trail finished title when flag is true', () => { - render() - - expect(screen.getByText('appDebug.notSetAPIKey.trailFinished')).toBeInTheDocument() - }) - - it('should call onSetting when primary button clicked', () => { + it('should call onSetting when manage models button is clicked', () => { const onSetting = vi.fn() - render() + render() - fireEvent.click(screen.getByRole('button', { name: 'appDebug.notSetAPIKey.settingBtn' })) + fireEvent.click(screen.getByRole('button', { name: 'appDebug.manageModels' })) expect(onSetting).toHaveBeenCalledTimes(1) }) }) diff --git a/web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx b/web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx index 84323e64f5..2c5fc5ff2f 100644 --- a/web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx +++ b/web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx @@ -2,38 +2,38 @@ import type { FC } from 'react' import * as React from 'react' import { useTranslation } from 'react-i18next' -import Button from '@/app/components/base/button' -import WarningMask from '.' export type IHasNotSetAPIProps = { - isTrailFinished: boolean onSetting: () => void } -const icon = ( - - - - -) - const HasNotSetAPI: FC = ({ - isTrailFinished, onSetting, }) => { const { t } = useTranslation() return ( - - {t('notSetAPIKey.settingBtn', { ns: 'appDebug' })} - {icon} - - )} - /> +
+
+
+
+ +
+
+
+
{t('noModelProviderConfigured', { ns: 'appDebug' })}
+
{t('noModelProviderConfiguredTip', { ns: 'appDebug' })}
+
+ +
+
) } export default React.memo(HasNotSetAPI) diff --git a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx index c33d55873d..39a1699063 100644 --- a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx +++ b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx @@ -178,7 +178,7 @@ const Prompt: FC = ({ {!noTitle && (
-
{mode !== AppModeEnum.COMPLETION ? t('chatSubTitle', { ns: 'appDebug' }) : t('completionSubTitle', { ns: 'appDebug' })}
+
{mode !== AppModeEnum.COMPLETION ? t('chatSubTitle', { ns: 'appDebug' }) : t('completionSubTitle', { ns: 'appDebug' })}
{!readonly && ( = ({ )}
-
+
= (
-
{t('codegen.instruction', { ns: 'appDebug' })}
+
{t('codegen.instruction', { ns: 'appDebug' })}
= ( disabled={isLoading} > - {t('codegen.generate', { ns: 'appDebug' })} + {t('codegen.generate', { ns: 'appDebug' })}
diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx index c9c8d080f2..bc534599de 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx @@ -210,7 +210,7 @@ const SettingsModal: FC = ({
-
{t('form.name', { ns: 'datasetSettings' })}
+
{t('form.name', { ns: 'datasetSettings' })}
= ({
-
{t('form.desc', { ns: 'datasetSettings' })}
+
{t('form.desc', { ns: 'datasetSettings' })}