From 22189f69f6dd16071a19ffae242f72310ce1f04b Mon Sep 17 00:00:00 2001
From: yyh <92089059+lyzno1@users.noreply.github.com>
Date: Tue, 8 Sep 2026 02:04:41 +0000
Subject: [PATCH] refactor(console): unify environment-aware oRPC clients and
query policies (#41932)
---
.../how-to-write-component/references/data.md | 2 +-
web/AGENTS.md | 2 +-
.../billing/billing-integration.test.tsx | 2 +-
.../billing/cloud-plan-payment-flow.test.tsx | 4 +-
.../education-verification-flow.test.tsx | 2 +-
.../billing/pricing-modal-flow.test.tsx | 4 +-
.../__tests__/hydration-boundary.spec.tsx | 22 +-
.../(commonLayout)/external-service-sync.tsx | 2 +-
web/app/(commonLayout)/hydration-boundary.tsx | 15 +-
web/app/__tests__/layout.spec.tsx | 2 +
.../(commonLayout)/account-page/index.tsx | 2 +-
web/app/account/(commonLayout)/avatar.tsx | 2 +-
web/app/account/oauth/authorize/page.tsx | 2 +-
web/app/auth/refresh/route.ts | 2 +-
.../api-key/__tests__/api-key-modal.spec.tsx | 2 +-
web/app/components/api-key/api-key-modal.tsx | 2 +-
.../__tests__/use-app-info-actions.spec.ts | 2 +-
.../app-info/use-app-info-actions.ts | 2 +-
.../app/__tests__/use-export-app-dsl.spec.tsx | 2 +-
.../__tests__/api-secret-key-button.spec.tsx | 2 +-
.../environment-access-control.spec.tsx | 2 +-
.../environment-access-point-cards.spec.tsx | 159 ++-
.../app/access-point/__tests__/index.spec.tsx | 2 +-
.../access-point/__tests__/mcp-card.spec.tsx | 2 +-
.../__tests__/service-api-card.spec.tsx | 2 +-
.../__tests__/trigger-card.spec.tsx | 2 +-
.../use-access-point-actions.spec.ts | 2 +-
.../__tests__/web-app-card.spec.tsx | 2 +-
.../built-in-access-points/mcp-card.tsx | 2 +-
.../service-api-card.tsx | 2 +-
.../built-in-access-points/trigger-card.tsx | 2 +-
.../built-in-access-points/web-app-card.tsx | 2 +-
.../environment-access-control.tsx | 2 +-
.../environment-service-api-card.tsx | 2 +-
.../environment-web-app-card.tsx | 2 +-
.../shared/api-secret-key-button.tsx | 2 +-
.../shared/use-access-point-actions.ts | 2 +-
web/app/components/app/access-point/state.ts | 2 +-
.../annotation/add-annotation-modal/index.tsx | 2 +-
.../batch-add-annotation-modal/index.tsx | 2 +-
web/app/components/app/annotation/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../app/app-access-control/index.tsx | 2 +-
.../environment-deployment-flow.spec.tsx | 2 +-
.../app-publisher/__tests__/index.spec.tsx | 2 +-
.../app-publisher/__tests__/state.spec.tsx | 2 +-
...p-environments-after-deployment-polling.ts | 2 +-
.../use-publish-controller.ts | 2 +-
web/app/components/app/app-publisher/state.ts | 2 +-
.../config/automatic/get-automatic-res.tsx | 2 +-
.../code-generator/get-code-generator-res.tsx | 2 +-
.../settings-modal/__tests__/index.spec.tsx | 2 +-
.../__tests__/retrieval-section.spec.tsx | 2 +-
.../model-parameter-trigger.tsx | 2 +-
.../__tests__/use-configuration.spec.tsx | 2 +-
.../use-configuration-app-context.ts | 2 +-
.../app-list/__tests__/index.spec.tsx | 4 +-
.../app/create-app-dialog/app-list/index.tsx | 2 +-
.../create-app-modal/__tests__/index.spec.tsx | 4 +-
.../components/app/create-app-modal/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 4 +-
.../app/create-from-dsl-modal/index.tsx | 2 +-
.../app/deploy/__tests__/index.spec.tsx | 2 +-
.../app/deploy/__tests__/state.spec.tsx | 2 +-
.../app/deploy/hooks/use-deploy-workflow.ts | 2 +-
...p-environments-after-deployment-polling.ts | 2 +-
.../app/deploy/hooks/use-undeploy-workflow.ts | 2 +-
.../use-deployment-configuration-queries.ts | 2 +-
web/app/components/app/deploy/state.ts | 2 +-
.../duplicate-modal/__tests__/index.spec.tsx | 2 +-
.../components/app/duplicate-modal/index.tsx | 2 +-
.../__tests__/notification.spec.tsx | 2 +-
.../app/in-site-message/notification.tsx | 2 +-
.../app/log/__tests__/filter.spec.tsx | 2 +-
.../retention-upgrade-notice.spec.tsx | 2 +-
.../app/log/archived-logs-notice.tsx | 2 +-
.../app/log/cloud-sandbox-retention.ts | 2 +-
web/app/components/app/overview/app-chart.tsx | 2 +-
.../settings/__tests__/index.spec.tsx | 2 +-
.../app/overview/settings/index.tsx | 2 +-
.../components/app/switch-app-modal/index.tsx | 2 +-
web/app/components/app/use-export-app-dsl.ts | 2 +-
.../apps/__tests__/app-card.spec.tsx | 4 +-
.../components/apps/__tests__/list.spec.tsx | 2 +-
.../components/apps/app-card/interactions.tsx | 2 +-
web/app/components/apps/app-list-catalog.tsx | 2 +-
.../use-workflow-online-users.spec.ts | 2 +-
.../apps/hooks/use-workflow-online-users.ts | 2 +-
.../annotation-ctrl-button.tsx | 2 +-
.../annotation-reply/use-annotation-config.ts | 2 +-
.../text-to-speech/param-config-content.tsx | 2 +-
.../base/voice-input/__tests__/api.spec.ts | 4 +-
web/app/components/base/voice-input/api.ts | 2 +-
.../billing/__tests__/query-state.spec.tsx | 2 +-
.../billing/annotation-full/usage.tsx | 2 +-
.../billing/apps-full-in-dialog/index.tsx | 2 +-
.../billing-page/__tests__/index.spec.tsx | 2 +-
.../components/billing/billing-page/index.tsx | 2 +-
.../billing/hooks/use-education-discount.ts | 2 +-
.../billing/partner-stack/use-ps-info.ts | 2 +-
web/app/components/billing/plan/index.tsx | 2 +-
.../components/billing/pricing/content.tsx | 2 +-
.../pricing/plans/cloud-plan-item/index.tsx | 2 +-
.../billing/priority-label/index.tsx | 2 +-
.../billing/usage-info/vector-space-info.tsx | 2 +-
.../custom-page/__tests__/index.spec.tsx | 2 +-
.../components/custom/custom-page/index.tsx | 2 +-
.../__tests__/use-web-app-brand.spec.tsx | 4 +-
.../hooks/use-web-app-brand.ts | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../common/retrieval-method-config/index.tsx | 2 +-
.../create/embedding-process/index.tsx | 2 +-
.../create/step-one/__tests__/index.spec.tsx | 2 +-
.../datasets/create/step-one/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../documents/create-from-pipeline/index.tsx | 2 +-
.../processing/embedding-process/index.tsx | 2 +-
.../documents/detail/segment-add/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../external-api/external-api-panel/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../external-knowledge-api-card/index.tsx | 2 +-
.../connector/__tests__/index.spec.tsx | 2 +-
.../create/ExternalApiSelect.tsx | 2 +-
.../create/ExternalApiSelection.tsx | 2 +-
.../__tests__/ExternalApiSelect.spec.tsx | 2 +-
.../__tests__/ExternalApiSelection.spec.tsx | 2 +-
.../create/__tests__/index.spec.tsx | 2 +-
.../datasets/list/__tests__/index.spec.tsx | 4 +-
.../hooks/use-dataset-card-state.ts | 2 +-
.../explore/create-app-modal/index.tsx | 2 +-
.../installed-app/__tests__/index.spec.tsx | 2 +-
.../explore/installed-app/index.tsx | 2 +-
.../actions/__tests__/agent.spec.tsx | 2 +-
.../actions/__tests__/app.spec.ts | 2 +-
.../actions/__tests__/knowledge.spec.ts | 2 +-
.../actions/__tests__/plugin.spec.ts | 2 +-
.../actions/__tests__/skill.spec.tsx | 2 +-
.../goto-anything/actions/agent.tsx | 2 +-
.../components/goto-anything/actions/app.tsx | 2 +-
.../goto-anything/actions/knowledge.tsx | 2 +-
.../goto-anything/actions/plugin.tsx | 2 +-
.../goto-anything/actions/skill.tsx | 2 +-
.../header/account-dropdown/compliance.tsx | 2 +-
.../main-nav-menu-content.tsx | 2 +-
.../account-setting/__tests__/index.spec.tsx | 4 +-
.../__tests__/index.spec.tsx | 2 +-
.../permission-set-modal/hooks.ts | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../__tests__/item.spec.tsx | 2 +-
.../__tests__/modal.spec.tsx | 2 +-
.../__tests__/selector.spec.tsx | 2 +-
.../api-based-extension-page/index.tsx | 2 +-
.../api-based-extension-page/item.tsx | 2 +-
.../api-based-extension-page/modal.tsx | 2 +-
.../api-based-extension-page/selector.tsx | 2 +-
.../account-setting/members-page/index.tsx | 2 +-
.../invite-modal/__tests__/index.spec.tsx | 4 +-
.../members-page/invite-modal/index.tsx | 2 +-
.../__tests__/hooks.spec.ts | 2 +-
.../__tests__/index.non-cloud.spec.tsx | 4 +-
.../__tests__/index.spec.tsx | 4 +-
.../install-from-marketplace.spec.tsx | 2 +-
.../model-provider-page/hooks.ts | 2 +-
.../model-provider-page/index.tsx | 2 +-
.../install-from-marketplace.tsx | 2 +-
.../model-selector/__tests__/index.spec.tsx | 2 +-
.../model-selector/model-selector-trigger.tsx | 2 +-
.../model-selector/popup.tsx | 2 +-
.../__tests__/credential-panel.spec.tsx | 4 +-
.../__tests__/index.spec.tsx | 2 +-
.../__tests__/provider-card-actions.spec.tsx | 2 +-
.../use-change-provider-priority.spec.ts | 2 +-
.../__tests__/use-trial-credits.spec.ts | 2 +-
.../provider-added-card/index.tsx | 2 +-
.../credits-exhausted-alert.stories.tsx | 2 +-
.../provider-added-card/model-list-item.tsx | 2 +-
.../provider-card-actions.tsx | 2 +-
.../provider-added-card/quota-panel.tsx | 2 +-
.../use-change-provider-priority.ts | 2 +-
.../use-credential-panel-state.ts | 2 +-
.../provider-added-card/use-trial-credits.ts | 2 +-
.../role-modal/__tests__/index.spec.tsx | 2 +-
.../permissions-page/role-modal/hooks.ts | 2 +-
.../account-setting/preference-page/index.tsx | 2 +-
.../__tests__/index.spec.tsx | 2 +-
.../workflow-log-archives-page/index.tsx | 2 +-
.../license-badge/__tests__/index.spec.tsx | 2 +-
.../components/header/license-badge/index.tsx | 2 +-
.../main-nav/__tests__/index.spec.tsx | 6 +-
.../__tests__/support-menu.spec.tsx | 2 +-
.../__tests__/workspace-card.spec.tsx | 6 +-
.../main-nav/components/help-menu.tsx | 2 +-
.../main-nav/components/support-menu.tsx | 2 +-
.../main-nav/components/web-apps-section.tsx | 2 +-
.../main-nav/components/workspace-card.tsx | 2 +-
.../use-plugins-with-latest-version.spec.ts | 4 +-
web/app/components/plugins/hooks.ts | 2 +-
.../__tests__/hydration-server.spec.tsx | 2 +-
.../marketplace/__tests__/query.spec.tsx | 2 +-
.../marketplace/__tests__/state.spec.tsx | 2 +-
.../marketplace/__tests__/utils.spec.ts | 2 +-
.../__tests__/data.server.spec.ts | 2 +-
.../creator-profile/data.server.ts | 2 +-
.../marketplace/creator-profile/publisher.ts | 2 +-
.../embedded-marketplace-search.spec.tsx | 2 +-
...place-search-autocomplete.browser.spec.tsx | 4 +-
.../marketplace-search-autocomplete.spec.tsx | 2 +-
.../plugins/marketplace/home/banners.spec.ts | 4 +-
.../plugins/marketplace/home/banners.ts | 2 +-
.../home/marketplace-search-autocomplete.tsx | 2 +-
.../prefetch-marketplace-dehydrated-state.ts | 2 +-
.../plugins/marketplace/query-options.ts | 2 +-
.../components/plugins/marketplace/query.ts | 2 +-
.../components/plugins/marketplace/utils.ts | 2 +-
.../app-selector/__tests__/index.spec.tsx | 2 +-
.../hooks/use-app-inputs-form-schema.ts | 2 +-
.../app-selector/index.tsx | 2 +-
.../category-marketplace-panel.spec.tsx | 2 +-
.../category-marketplace-panel.tsx | 2 +-
.../snippet-list/__tests__/index.spec.tsx | 2 +-
.../__tests__/reflow.browser.spec.tsx | 2 +-
.../__tests__/snippet-create-button.spec.tsx | 2 +-
.../components/hooks/use-snippet-publish.ts | 2 +-
.../__tests__/use-create-snippet.spec.tsx | 2 +-
.../__tests__/use-nodes-sync-draft.spec.ts | 2 +-
.../snippets/hooks/use-create-snippet.ts | 2 +-
.../snippets/hooks/use-nodes-sync-draft.ts | 2 +-
.../__tests__/mount.spec.tsx | 2 +-
.../step-by-step-tour/__tests__/state.spec.ts | 2 +-
web/app/components/step-by-step-tour/state.ts | 2 +-
.../tools/marketplace/__tests__/hooks.spec.ts | 2 +-
web/app/components/tools/marketplace/hooks.ts | 2 +-
.../__tests__/features-trigger.spec.tsx | 2 +-
.../workflow-header/features-trigger.tsx | 2 +-
.../__tests__/agent-selector.spec.tsx | 2 +-
.../block-selector/agent-selector.tsx | 2 +-
.../__tests__/action.spec.tsx | 2 +-
.../marketplace-plugin/action.tsx | 2 +-
.../__tests__/snippet-tags-filter.spec.tsx | 2 +-
.../__tests__/use-insert-snippet.spec.tsx | 2 +-
.../snippets/snippet-tags-filter.tsx | 2 +-
.../snippets/use-insert-snippet.ts | 2 +-
.../workflow/comment/mention-input.spec.tsx | 2 +-
.../workflow/comment/mention-input.tsx | 2 +-
.../workflow/header/header-in-restoring.tsx | 2 +-
.../hooks/__tests__/use-checklist.spec.ts | 2 +-
.../__tests__/use-workflow-comment.spec.ts | 4 +-
.../workflow/hooks/use-checklist.ts | 2 +-
.../workflow/hooks/use-nodes-interactions.ts | 2 +-
.../workflow/hooks/use-panel-interactions.ts | 2 +-
.../workflow/hooks/use-workflow-comment.ts | 2 +-
.../nodes/agent-v2/__tests__/hooks.spec.tsx | 2 +-
.../nodes/agent-v2/agent-soul-config.ts | 2 +-
.../agent-orchestrate-panel-content.spec.tsx | 2 +-
...ave-inline-agent-to-roster-dialog.spec.tsx | 2 +-
.../agent-orchestrate-panel-content.tsx | 2 +-
.../save-inline-agent-to-roster-dialog.tsx | 2 +-
.../workflow/nodes/agent-v2/hooks.ts | 2 +-
.../workflow/nodes/agent-v2/panel.tsx | 2 +-
.../knowledge-base/__tests__/panel.spec.tsx | 2 +-
.../workflow/nodes/knowledge-base/node.tsx | 2 +-
.../workflow/nodes/knowledge-base/panel.tsx | 2 +-
.../action-menu/use-action-menu.ts | 2 +-
.../panel/version-history-panel/index.tsx | 2 +-
web/app/device/page.tsx | 2 +-
.../__tests__/institution-field.spec.tsx | 2 +-
.../education/apply/__tests__/page.spec.tsx | 2 +-
web/app/education/apply/application-entry.tsx | 2 +-
web/app/education/apply/application-form.tsx | 2 +-
web/app/education/apply/institution-field.tsx | 2 +-
.../expire-notice/use-expire-notice.ts | 2 +-
web/app/education/verify/verify-flow.tsx | 2 +-
web/app/install/installForm.tsx | 2 +-
web/app/layout.tsx | 1 +
.../components/mail-and-password-auth.tsx | 2 +-
web/app/signin/invite-settings/page.tsx | 2 +-
web/app/signin/one-more-step.tsx | 2 +-
web/app/signup/set-password/page.tsx | 2 +-
.../__tests__/console-bootstrap.spec.tsx | 2 +-
.../hooks/use-trigger-events-limit-modal.ts | 2 +-
web/context/permission-state.ts | 2 +-
web/context/provider-context-provider.tsx | 2 +-
web/context/workspace-state.ts | 2 +-
.../account-profile/__tests__/server.spec.ts | 2 +-
web/features/account-profile/client.ts | 2 +-
web/features/account-profile/server.ts | 6 +-
.../agent-detail/__tests__/layout.spec.tsx | 2 +-
.../__tests__/navigation.spec.tsx | 2 +-
.../__tests__/access-surface-cards.spec.tsx | 2 +-
.../workflow-references-table.spec.tsx | 2 +-
.../access/components/agent-api-key-modal.tsx | 2 +-
.../components/service-api-access-card.tsx | 2 +-
.../access/components/web-app-access-card.tsx | 2 +-
.../components/workflow-references-table.tsx | 2 +-
.../agent-v2/agent-detail/access/page.tsx | 2 +-
.../configure/__tests__/page.spec.tsx | 2 +-
.../use-agent-configure-sync.spec.tsx | 2 +-
.../configure/components/composer-session.tsx | 2 +-
.../__tests__/publish-bar.spec.tsx | 2 +-
.../components/orchestrate/config-context.ts | 2 +-
.../files/__tests__/index.spec.tsx | 2 +-
.../components/orchestrate/files/index.tsx | 2 +-
.../orchestrate/files/upload-dialog.tsx | 2 +-
.../orchestrate/publish-bar/index.tsx | 2 +-
.../skills/__tests__/index.spec.tsx | 2 +-
.../components/orchestrate/skills/index.tsx | 2 +-
.../components/orchestrate/skills/item.tsx | 2 +-
.../orchestrate/skills/upload-dialog.tsx | 2 +-
.../orchestrate/skills/use-skill-detail.ts | 2 +-
.../preview/__tests__/chat.spec.tsx | 4 +-
.../preview/__tests__/versions-panel.spec.tsx | 2 +-
.../working-directory-panel.spec.tsx | 2 +-
.../components/preview/chat-conversation.tsx | 2 +-
.../components/preview/chat-runtime.tsx | 2 +-
.../hook/use-working-directory-panel.tsx | 2 +-
.../preview/versions-panel/index.tsx | 2 +-
.../preview/working-directory-panel.tsx | 2 +-
.../agent-v2/agent-detail/configure/hooks.ts | 2 +-
.../configure/use-agent-build-draft-run.ts | 2 +-
.../use-agent-configure-build-draft.ts | 2 +-
.../configure/use-agent-configure-sync.ts | 2 +-
web/features/agent-v2/agent-detail/layout.tsx | 2 +-
.../logs/__tests__/log-detail-panel.spec.tsx | 2 +-
.../agent-detail/logs/__tests__/page.spec.tsx | 2 +-
.../logs/components/log-detail-panel.tsx | 2 +-
.../agent-v2/agent-detail/logs/page.tsx | 2 +-
.../monitoring/__tests__/page.spec.tsx | 2 +-
.../agent-v2/agent-detail/monitoring/page.tsx | 2 +-
.../agent-v2/agent-detail/navigation.tsx | 2 +-
.../agent-v2/roster/__tests__/page.spec.tsx | 4 +-
.../__tests__/agent-roster-list.spec.tsx | 2 +-
.../__tests__/create-agent-dialog.spec.tsx | 2 +-
.../__tests__/delete-agent-dialog.spec.tsx | 2 +-
.../__tests__/duplicate-agent-dialog.spec.tsx | 2 +-
.../__tests__/edit-agent-dialog.spec.tsx | 2 +-
.../roster/components/create-agent-dialog.tsx | 2 +-
.../roster/components/delete-agent-dialog.tsx | 2 +-
.../components/duplicate-agent-dialog.tsx | 2 +-
.../roster/components/edit-agent-dialog.tsx | 2 +-
.../roster/components/roster-create-menu.tsx | 2 +-
web/features/agent-v2/roster/page.tsx | 2 +-
web/features/home/banner/home-banner.tsx | 2 +-
.../__tests__/home-content.spec.tsx | 2 +-
.../home/home-content/home-content.tsx | 2 +-
web/features/home/page.tsx | 16 +-
.../__tests__/add-source-page.spec.tsx | 2 +-
.../__tests__/crawl-selection-form.spec.tsx | 2 +-
.../__tests__/create-knowledge-page.spec.tsx | 2 +-
.../__tests__/document-detail-page.spec.tsx | 2 +-
.../new-rag/__tests__/documents-page.spec.tsx | 2 +-
.../__tests__/knowledge-space-shell.spec.tsx | 4 +-
.../__tests__/new-knowledge-list.spec.tsx | 2 +-
.../__tests__/processing-task-events.spec.ts | 2 +-
.../new-rag/__tests__/sources-page.spec.tsx | 2 +-
.../__tests__/website-crawl-preview.spec.tsx | 2 +-
web/features/new-rag/add-source-page.tsx | 2 +-
web/features/new-rag/crawl-selection-form.tsx | 2 +-
.../new-rag/create-knowledge-page.tsx | 2 +-
.../new-rag/create-knowledge-workflow.ts | 2 +-
web/features/new-rag/document-detail-page.tsx | 2 +-
.../new-rag/document-detail-queries.ts | 2 +-
web/features/new-rag/documents-page.tsx | 2 +-
.../new-rag/knowledge-space-shell.tsx | 2 +-
web/features/new-rag/new-knowledge-list.tsx | 2 +-
.../new-rag/processing-tasks-drawer.tsx | 2 +-
.../services/processing-task-events.ts | 2 +-
web/features/new-rag/sources-page.tsx | 2 +-
web/features/new-rag/use-document-reindex.ts | 2 +-
.../new-rag/use-document-task-status.ts | 2 +-
.../new-rag/website-crawl-preview.tsx | 2 +-
.../skills/__tests__/detail-page.fixture.tsx | 2 +-
web/features/skills/__tests__/page.spec.tsx | 2 +-
.../skills/detail/__tests__/shared.spec.ts | 2 +-
web/features/skills/detail/file-editor.tsx | 2 +-
web/features/skills/detail/file-tree.tsx | 2 +-
web/features/skills/detail/page.tsx | 2 +-
web/features/skills/detail/shared.tsx | 2 +-
.../skills/detail/sidebar-actions.tsx | 2 +-
.../detail/skill-display-name-editor.tsx | 2 +-
web/features/skills/detail/skill-metadata.tsx | 2 +-
.../skill-publish-confirm-panel.stories.tsx | 2 +-
web/features/skills/detail/version-panel.tsx | 2 +-
web/features/skills/page.tsx | 2 +-
.../__tests__/bootstrap-boundary.spec.tsx | 4 +-
.../system-features/__tests__/server.spec.ts | 4 +-
web/features/system-features/client.ts | 2 +-
web/features/system-features/server.ts | 4 +-
.../__tests__/skill-card-tags.spec.tsx | 2 +-
.../__tests__/tag-item-editor.spec.tsx | 2 +-
.../__tests__/tag-management-modal.spec.tsx | 2 +-
.../__tests__/tag-selector.spec.tsx | 2 +-
.../components/skill-card-tags.tsx | 2 +-
.../tag-management/components/tag-filter.tsx | 2 +-
.../components/tag-item-editor.tsx | 2 +-
.../components/tag-management-modal.tsx | 2 +-
.../components/tag-selector.tsx | 2 +-
.../__tests__/use-tag-mutations.spec.tsx | 2 +-
.../tag-management/hooks/use-tag-mutations.ts | 2 +-
web/hooks/use-import-dsl.spec.tsx | 4 +-
web/hooks/use-import-dsl.ts | 2 +-
web/instrumentation.ts | 3 +
web/service/__tests__/server.spec.ts | 105 --
web/service/__tests__/use-plugins.spec.tsx | 2 +-
web/service/__tests__/use-snippets.spec.tsx | 2 +-
web/service/__tests__/use-tools.spec.tsx | 2 +-
web/service/__tests__/use-triggers.spec.ts | 2 +-
web/service/__tests__/use-workflow.spec.tsx | 2 +-
.../__tests__/resource-access-config.spec.tsx | 2 +-
.../__tests__/use-app-access-control.spec.tsx | 4 +-
.../access-control/use-app-access-config.ts | 2 +-
.../access-control/use-app-access-control.ts | 2 +-
.../use-dataset-access-config.ts | 2 +-
web/service/common.ts | 2 +-
web/service/console-link.ts | 30 -
web/service/console-openapi-url.ts | 69 --
web/service/console-router-loader.ts | 41 -
web/service/console/README.md | 26 +
web/service/console/browser.ts | 30 +
web/service/{ => console}/client.spec.ts | 690 ++++-------
web/service/console/contract-loader.ts | 50 +
web/service/console/hydration.spec.tsx | 86 ++
web/service/console/index.ts | 35 +
web/service/console/openapi-url.ts | 47 +
.../{client.ts => console/query-policies.ts} | 1087 ++++-------------
web/service/console/server.spec.ts | 167 +++
web/service/console/server.ts | 93 ++
web/service/explore.spec.ts | 2 +-
web/service/explore.ts | 2 +-
.../marketplace-template-discovery.spec.ts | 2 +-
web/service/marketplace-template-discovery.ts | 2 +-
web/service/marketplace-templates.ts | 2 +-
web/service/marketplace.ts | 51 +
web/service/plugins.spec.ts | 2 +-
web/service/plugins.ts | 2 +-
web/service/server.ts | 113 --
web/service/try-app.ts | 2 +-
web/service/use-common.ts | 2 +-
web/service/use-explore.ts | 2 +-
web/service/use-log.ts | 2 +-
web/service/use-plugins.ts | 2 +-
web/service/use-snippet-workflows.ts | 2 +-
web/service/use-snippets.ts | 2 +-
web/service/use-tools.ts | 2 +-
web/service/use-triggers.ts | 2 +-
web/service/use-try-app.ts | 2 +-
web/service/use-workflow.ts | 2 +-
web/service/workflow-generator.ts | 6 +-
web/service/workflow-queries.ts | 2 +-
web/service/workflow.spec.ts | 2 +-
web/service/workflow.ts | 2 +-
web/test/console/query-data.ts | 2 +-
web/utils/imported-app-redirection.spec.ts | 2 +-
web/utils/imported-app-redirection.ts | 2 +-
454 files changed, 1616 insertions(+), 2252 deletions(-)
create mode 100644 web/instrumentation.ts
delete mode 100644 web/service/__tests__/server.spec.ts
delete mode 100644 web/service/console-link.ts
delete mode 100644 web/service/console-openapi-url.ts
delete mode 100644 web/service/console-router-loader.ts
create mode 100644 web/service/console/README.md
create mode 100644 web/service/console/browser.ts
rename web/service/{ => console}/client.spec.ts (78%)
create mode 100644 web/service/console/contract-loader.ts
create mode 100644 web/service/console/hydration.spec.tsx
create mode 100644 web/service/console/index.ts
create mode 100644 web/service/console/openapi-url.ts
rename web/service/{client.ts => console/query-policies.ts} (55%)
create mode 100644 web/service/console/server.spec.ts
create mode 100644 web/service/console/server.ts
create mode 100644 web/service/marketplace.ts
delete mode 100644 web/service/server.ts
diff --git a/.agents/skills/how-to-write-component/references/data.md b/.agents/skills/how-to-write-component/references/data.md
index 57c23a8f284..009f14c5c52 100644
--- a/.agents/skills/how-to-write-component/references/data.md
+++ b/.agents/skills/how-to-write-component/references/data.md
@@ -28,7 +28,7 @@ Read this document when a component consumes generated contracts, nullable API v
- Use generated `mutationOptions()` directly for owner-local mutations.
- Do not introduce deprecated `useInvalid` or `useReset` APIs.
-- Put shared invalidation, retries, and cache behavior in `createTanstackQueryUtils(...experimental_defaults...)`. Local callbacks may own toast, close, and navigation effects but must not replace shared cache policy.
+- Put shared invalidation, retries, and cache behavior in `createTanstackQueryUtils(...experimental_defaults...)`. In oRPC v1, caller options override defaults, including callbacks. Local callbacks may own toast, close, and navigation effects but must preserve shared cache behavior.
- Prefer `mutate(...)`. Use `mutateAsync(...)` only when Promise composition is required, and catch awaited failures.
- Preserve intentional empty values and current list/detail ownership when updating data. Do not add optimistic updates without a verified owner contract.
diff --git a/web/AGENTS.md b/web/AGENTS.md
index 939bbcbe700..e87014aa21a 100644
--- a/web/AGENTS.md
+++ b/web/AGENTS.md
@@ -10,7 +10,7 @@ Web owns application-specific requirements and consumes shared architecture guid
- For truncated text disclosure and native `title` decisions, follow [Truncated Text Disclosure].
- User-facing strings must use `web/i18n/en-US/` keys. When adding or renaming a key, update every supported locale with the correct localized value.
-- For new backend calls and migrated surfaces, use generated `consoleQuery` / `consoleClient` APIs from `@/service/client`. Do not add handwritten REST helpers or DTO mirrors, mock-backed app state, or direct edits to generated contracts.
+- For new backend calls and migrated surfaces, use generated `consoleQuery` / `consoleClient` APIs from `@/service/console`. Do not add handwritten REST helpers or DTO mirrors, mock-backed app state, or direct edits to generated contracts.
- Prefer `@langgenius/dify-ui/*` primitives, data attributes, and design tokens. Use the [Dify UI package index] to find a primitive; read the relevant contract directly when it is already known. Preserve a visible focus indicator on the final focusable element.
- Reuse the Web `SearchInput` composite when its search, clear, and IME contract matches the feature; otherwise follow the canonical [Input Group contract].
- Give save and submit flows a real form boundary with visible labels and accessible errors. Use Dify UI `Form` when its structured submission and validation contract is the owner; otherwise use a native form. Follow the canonical [form contract].
diff --git a/web/__tests__/billing/billing-integration.test.tsx b/web/__tests__/billing/billing-integration.test.tsx
index a1b65898357..b3d28cf9c83 100644
--- a/web/__tests__/billing/billing-integration.test.tsx
+++ b/web/__tests__/billing/billing-integration.test.tsx
@@ -20,7 +20,7 @@ import PriorityLabel from '@/app/components/billing/priority-label'
import TriggerEventsLimitModal from '@/app/components/billing/trigger-events-limit-modal'
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
import VectorSpaceFull from '@/app/components/billing/vector-space-full'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
createConsoleQueryWrapper,
diff --git a/web/__tests__/billing/cloud-plan-payment-flow.test.tsx b/web/__tests__/billing/cloud-plan-payment-flow.test.tsx
index 7525f331796..eb8ea8da748 100644
--- a/web/__tests__/billing/cloud-plan-payment-flow.test.tsx
+++ b/web/__tests__/billing/cloud-plan-payment-flow.test.tsx
@@ -30,8 +30,8 @@ vi.mock('@/context/workspace-state', async () => {
return createWorkspaceStateModuleMock(() => mockConsoleState)
})
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleClient: new Proxy(actual.consoleClient, {
diff --git a/web/__tests__/billing/education-verification-flow.test.tsx b/web/__tests__/billing/education-verification-flow.test.tsx
index 061d8602903..23a57eb55e1 100644
--- a/web/__tests__/billing/education-verification-flow.test.tsx
+++ b/web/__tests__/billing/education-verification-flow.test.tsx
@@ -8,7 +8,7 @@ import type { DeepPartial } from '@/test/console/system-features'
import { cleanup, screen } from '@testing-library/react'
import * as React from 'react'
import PlanComp from '@/app/components/billing/plan'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
createConsoleQueryWrapper,
diff --git a/web/__tests__/billing/pricing-modal-flow.test.tsx b/web/__tests__/billing/pricing-modal-flow.test.tsx
index 9a77532723d..29c7d3db54b 100644
--- a/web/__tests__/billing/pricing-modal-flow.test.tsx
+++ b/web/__tests__/billing/pricing-modal-flow.test.tsx
@@ -49,8 +49,8 @@ vi.mock('@/context/i18n', () => ({
useGetPricingPageLanguage: () => 'en',
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleClient: new Proxy(actual.consoleClient, {
diff --git a/web/app/(commonLayout)/__tests__/hydration-boundary.spec.tsx b/web/app/(commonLayout)/__tests__/hydration-boundary.spec.tsx
index 2efd15cc830..3e8b05dbfab 100644
--- a/web/app/(commonLayout)/__tests__/hydration-boundary.spec.tsx
+++ b/web/app/(commonLayout)/__tests__/hydration-boundary.spec.tsx
@@ -11,7 +11,6 @@ const mocks = vi.hoisted(() => ({
workspaceQueryOptions: vi.fn(),
permissionQueryFn: vi.fn(),
permissionQueryOptions: vi.fn(),
- getServerConsoleClientContext: vi.fn(),
redirect: vi.fn((url: string) => {
throw new Error(`NEXT_REDIRECT:${url}`)
}),
@@ -48,10 +47,12 @@ vi.mock('@/features/account-profile/server', () => ({
}),
}))
-vi.mock('@/service/server', () => ({
- getServerConsoleClientContext: () => mocks.getServerConsoleClientContext(),
+vi.mock('@/service/console/server', () => ({
resolveServerConsoleApiUrl: (...args: unknown[]) => mocks.resolveServerConsoleApiUrl(...args),
- serverConsoleQuery: {
+}))
+
+vi.mock('@/service/console', () => ({
+ consoleQuery: {
workspaces: {
current: {
summary: {
@@ -111,10 +112,6 @@ describe('CommonLayoutHydrationBoundary', () => {
app: { default_permission_keys: [], overrides: [] },
dataset: { default_permission_keys: [], overrides: [] },
})
- mocks.getServerConsoleClientContext.mockResolvedValue({
- cookie: 'session=abc',
- csrfToken: 'csrf-token',
- })
mocks.workspaceQueryOptions.mockReturnValue({
queryKey: ['console', 'workspaces', 'current', 'summary', 'get'],
queryFn: mocks.workspaceQueryFn,
@@ -144,20 +141,11 @@ describe('CommonLayoutHydrationBoundary', () => {
)
expect(screen.getByText('Common shell')).toBeInTheDocument()
expect(mocks.profileQueryFn).toHaveBeenCalledTimes(1)
- expect(mocks.getServerConsoleClientContext).toHaveBeenCalledTimes(1)
expect(mocks.workspaceQueryOptions).toHaveBeenCalledWith({
- context: {
- cookie: 'session=abc',
- csrfToken: 'csrf-token',
- },
retry: false,
})
expect(mocks.workspaceQueryFn).toHaveBeenCalledTimes(1)
expect(mocks.permissionQueryOptions).toHaveBeenCalledWith({
- context: {
- cookie: 'session=abc',
- csrfToken: 'csrf-token',
- },
retry: false,
})
expect(mocks.permissionQueryFn).toHaveBeenCalledTimes(1)
diff --git a/web/app/(commonLayout)/external-service-sync.tsx b/web/app/(commonLayout)/external-service-sync.tsx
index 82a988953a0..6316fa41437 100644
--- a/web/app/(commonLayout)/external-service-sync.tsx
+++ b/web/app/(commonLayout)/external-service-sync.tsx
@@ -20,7 +20,7 @@ import { getLangGeniusVersionInfo } from '@/context/app-context-normalizers'
import { currentWorkspaceAtom } from '@/context/workspace-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type AmplitudeProperties = Record
diff --git a/web/app/(commonLayout)/hydration-boundary.tsx b/web/app/(commonLayout)/hydration-boundary.tsx
index b7da5353bbe..dcd8c05ed0e 100644
--- a/web/app/(commonLayout)/hydration-boundary.tsx
+++ b/web/app/(commonLayout)/hydration-boundary.tsx
@@ -4,11 +4,8 @@ import { getQueryClient } from '@/app/get-query-client'
import { serverUserProfileQueryOptions } from '@/features/account-profile/server'
import { headers } from '@/next/headers'
import { redirect } from '@/next/navigation'
-import {
- getServerConsoleClientContext,
- resolveServerConsoleApiUrl,
- serverConsoleQuery,
-} from '@/service/server'
+import { consoleQuery } from '@/service/console'
+import { resolveServerConsoleApiUrl } from '@/service/console/server'
const CURRENT_PATHNAME_HEADER = 'x-dify-pathname'
const CURRENT_SEARCH_HEADER = 'x-dify-search'
@@ -60,22 +57,18 @@ export async function CommonLayoutHydrationBoundary({ children }: { children: Re
if (accountProfileUrl) {
try {
- const context = await getServerConsoleClientContext()
-
await Promise.all([
queryClient.query(serverUserProfileQueryOptions()),
queryClient
.query(
- serverConsoleQuery.workspaces.current.summary.get.queryOptions({
- context,
+ consoleQuery.workspaces.current.summary.get.queryOptions({
retry: false,
}),
)
.catch(noop),
queryClient
.query(
- serverConsoleQuery.workspaces.current.rbac.myPermissions.get.queryOptions({
- context,
+ consoleQuery.workspaces.current.rbac.myPermissions.get.queryOptions({
retry: false,
}),
)
diff --git a/web/app/__tests__/layout.spec.tsx b/web/app/__tests__/layout.spec.tsx
index ca67d22f92c..cee0bd121ed 100644
--- a/web/app/__tests__/layout.spec.tsx
+++ b/web/app/__tests__/layout.spec.tsx
@@ -4,6 +4,8 @@ const mocks = vi.hoisted(() => ({
headers: vi.fn(async () => new Headers()),
}))
+vi.mock('@/service/console/server', () => ({}))
+
vi.mock('@/features/system-features/server', () => ({
dehydrateSystemFeatures: mocks.dehydrateSystemFeatures,
getOptionalSystemFeatures: mocks.getOptionalSystemFeatures,
diff --git a/web/app/account/(commonLayout)/account-page/index.tsx b/web/app/account/(commonLayout)/account-page/index.tsx
index 2c21ef117c5..95d8891ab3e 100644
--- a/web/app/account/(commonLayout)/account-page/index.tsx
+++ b/web/app/account/(commonLayout)/account-page/index.tsx
@@ -19,8 +19,8 @@ import { validPassword } from '@/config'
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
import { updateUserProfile } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import DeleteAccount from '../delete-account'
import AvatarWithEdit from './AvatarWithEdit'
import EmailChangeModal from './email-change-modal'
diff --git a/web/app/account/(commonLayout)/avatar.tsx b/web/app/account/(commonLayout)/avatar.tsx
index dc62b7931d4..8989f7fa695 100644
--- a/web/app/account/(commonLayout)/avatar.tsx
+++ b/web/app/account/(commonLayout)/avatar.tsx
@@ -14,7 +14,7 @@ import PremiumBadge from '@/app/components/base/premium-badge'
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useLogout } from '@/service/use-common'
export default function AppSelector() {
diff --git a/web/app/account/oauth/authorize/page.tsx b/web/app/account/oauth/authorize/page.tsx
index 215d9d2f5b5..7853316aa0c 100644
--- a/web/app/account/oauth/authorize/page.tsx
+++ b/web/app/account/oauth/authorize/page.tsx
@@ -20,7 +20,7 @@ import { isLegacyBase401, userProfileQueryOptions } from '@/features/account-pro
import useDocumentTitle from '@/hooks/use-document-title'
import Link from '@/next/link'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useLogout } from '@/service/use-common'
import { buildOAuthCallbackUrl, buildReturnUrl, useSilentAuthorize } from './use-silent-authorize'
diff --git a/web/app/auth/refresh/route.ts b/web/app/auth/refresh/route.ts
index 698ca6df24c..350492315cd 100644
--- a/web/app/auth/refresh/route.ts
+++ b/web/app/auth/refresh/route.ts
@@ -1,5 +1,5 @@
import type { LoginRedirectTarget } from '@/utils/login-redirect'
-import { resolveServerConsoleApiUrl } from '@/service/server'
+import { resolveServerConsoleApiUrl } from '@/service/console/server'
import { getServerLoginFallback, resolveLoginRedirectTarget } from '@/utils/login-redirect'
import { basePath } from '@/utils/var'
diff --git a/web/app/components/api-key/__tests__/api-key-modal.spec.tsx b/web/app/components/api-key/__tests__/api-key-modal.spec.tsx
index 6b8c7eb26f3..9c033af232f 100644
--- a/web/app/components/api-key/__tests__/api-key-modal.spec.tsx
+++ b/web/app/components/api-key/__tests__/api-key-modal.spec.tsx
@@ -25,7 +25,7 @@ const apiMocks = vi.hoisted(() => ({
deleteEnvironment: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byResourceId: {
diff --git a/web/app/components/api-key/api-key-modal.tsx b/web/app/components/api-key/api-key-modal.tsx
index d3317469041..d9cabd605f2 100644
--- a/web/app/components/api-key/api-key-modal.tsx
+++ b/web/app/components/api-key/api-key-modal.tsx
@@ -24,7 +24,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { currentWorkspaceAtom } from '@/context/workspace-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ApiKeyTable } from './api-key-table'
import { CreatedApiKeyDialog } from './created-api-key-dialog'
import { DatasetScopeDialog } from './dataset-scope-dialog'
diff --git a/web/app/components/app-sidebar/app-info/__tests__/use-app-info-actions.spec.ts b/web/app/components/app-sidebar/app-info/__tests__/use-app-info-actions.spec.ts
index e5265af1c4c..a07aae99ba1 100644
--- a/web/app/components/app-sidebar/app-info/__tests__/use-app-info-actions.spec.ts
+++ b/web/app/components/app-sidebar/app-info/__tests__/use-app-info-actions.spec.ts
@@ -1,5 +1,5 @@
import { act, renderHook } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { useAppInfoActions } from '../use-app-info-actions'
diff --git a/web/app/components/app-sidebar/app-info/use-app-info-actions.ts b/web/app/components/app-sidebar/app-info/use-app-info-actions.ts
index ed8da814d36..6936882a1b1 100644
--- a/web/app/components/app-sidebar/app-info/use-app-info-actions.ts
+++ b/web/app/components/app-sidebar/app-info/use-app-info-actions.ts
@@ -20,7 +20,7 @@ import {
markAppDeletionSucceeded,
} from '@/service/app-deletion'
import { fetchAppDetail, updateAppInfo } from '@/service/apps'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
diff --git a/web/app/components/app/__tests__/use-export-app-dsl.spec.tsx b/web/app/components/app/__tests__/use-export-app-dsl.spec.tsx
index c581748c520..315b6adb42c 100644
--- a/web/app/components/app/__tests__/use-export-app-dsl.spec.tsx
+++ b/web/app/components/app/__tests__/use-export-app-dsl.spec.tsx
@@ -11,7 +11,7 @@ const mocks = vi.hoisted(() => ({
toastPromise: vi.fn((promise: Promise) => promise),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
apps: {
byAppId: {
diff --git a/web/app/components/app/access-point/__tests__/api-secret-key-button.spec.tsx b/web/app/components/app/access-point/__tests__/api-secret-key-button.spec.tsx
index 6a70fe9e4c0..a26df699c62 100644
--- a/web/app/components/app/access-point/__tests__/api-secret-key-button.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/api-secret-key-button.spec.tsx
@@ -1,7 +1,7 @@
import type { ReactElement } from 'react'
import { screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { ApiSecretKeyButton } from '../shared/api-secret-key-button'
diff --git a/web/app/components/app/access-point/__tests__/environment-access-control.spec.tsx b/web/app/components/app/access-point/__tests__/environment-access-control.spec.tsx
index 8c805d69980..a3e5376086b 100644
--- a/web/app/components/app/access-point/__tests__/environment-access-control.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/environment-access-control.spec.tsx
@@ -12,7 +12,7 @@ const mocks = vi.hoisted(() => ({
updateAccessMode: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
enterprise: {
appDeploy: {
diff --git a/web/app/components/app/access-point/__tests__/environment-access-point-cards.spec.tsx b/web/app/components/app/access-point/__tests__/environment-access-point-cards.spec.tsx
index 8a9f11c2444..210dd6b189a 100644
--- a/web/app/components/app/access-point/__tests__/environment-access-point-cards.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/environment-access-point-cards.spec.tsx
@@ -19,65 +19,6 @@ const mocks = vi.hoisted(() => ({
apiKeyButtonProps: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
- consoleQuery: {
- enterprise: {
- appDeploy: {
- accessService: {
- getEnvironmentApi: {
- queryOptions: ({
- input,
- }: {
- input: { params: { app_id: string; environment_id: string } }
- }) => ({
- queryKey: ['environment-api', input.params.app_id, input.params.environment_id],
- queryFn: () => mocks.getApi(input),
- }),
- },
- getEnvironmentSite: {
- queryOptions: ({
- input,
- }: {
- input: { params: { app_id: string; environment_id: string } }
- }) => ({
- queryKey: ['environment-site', input.params.app_id, input.params.environment_id],
- queryFn: () => mocks.getSite(input),
- }),
- },
- getEnvironmentWebAppSubjects: {
- queryOptions: ({
- input,
- }: {
- input: { params: { app_id: string; environment_id: string } }
- }) => ({
- queryKey: ['environment-subjects', input.params.app_id, input.params.environment_id],
- queryFn: () => mocks.getSubjects(input),
- }),
- },
- resetEnvironmentSiteAccessToken: {
- mutationOptions: (options = {}) => ({
- mutationFn: mocks.resetSite,
- ...options,
- }),
- },
- updateEnvironmentApi: {
- mutationOptions: (options = {}) => ({
- mutationFn: mocks.updateApi,
- ...options,
- }),
- },
- updateEnvironmentSite: {
- mutationOptions: (options = {}) => ({
- mutationFn: mocks.updateSite,
- ...options,
- }),
- },
- },
- },
- },
- },
-}))
-
vi.mock('@/features/system-features/client', () => ({
systemFeaturesQueryOptions: () => ({
queryKey: ['system-features'],
@@ -189,8 +130,7 @@ const api = {
enabled: true,
}
-function renderCard(ui: ReactElement) {
- const queryClient = createTestQueryClient()
+function renderCard(ui: ReactElement, queryClient = createTestQueryClient()) {
queryClient.setQueryData(['system-features'], {
webapp_auth: {
enabled: true,
@@ -211,9 +151,46 @@ function createDeferredPromise() {
return { promise, reject, resolve }
}
+// Keep HTTP mocked through Testing Library's asynchronous cleanup.
+afterAll(() => vi.unstubAllGlobals())
+
describe('environment access point cards', () => {
beforeEach(() => {
vi.clearAllMocks()
+ mockAppMode = 'workflow'
+ vi.stubGlobal('fetch', async (input: RequestInfo | URL, init?: RequestInit) => {
+ const request = new Request(input, init)
+ const path = new URL(request.url).pathname
+ const match = /\/enterprise\/app-deploy\/apps\/([^/]+)\/environments\/([^/]+)\/(.+)$/.exec(
+ path,
+ )
+ if (!match) throw new Error(`Unexpected request: ${request.method} ${path}`)
+ const params = { app_id: match[1], environment_id: match[2] }
+ let data: unknown
+ switch (`${request.method} ${match[3]}`) {
+ case 'GET api':
+ data = await mocks.getApi({ params })
+ break
+ case 'GET site':
+ data = await mocks.getSite({ params })
+ break
+ case 'GET webapp/subjects':
+ data = await mocks.getSubjects({ params })
+ break
+ case 'POST site/access-token-reset':
+ data = await mocks.resetSite({ params })
+ break
+ case 'PATCH api':
+ data = await mocks.updateApi({ params, body: await request.json() })
+ break
+ case 'PATCH site':
+ data = await mocks.updateSite({ params, body: await request.json() })
+ break
+ default:
+ throw new Error(`Unexpected request: ${request.method} ${path}`)
+ }
+ return Response.json(data)
+ })
mocks.getApi.mockResolvedValue(api)
mocks.getSite.mockResolvedValue(site)
mocks.getSubjects.mockResolvedValue({
@@ -243,6 +220,45 @@ describe('environment access point cards', () => {
})
})
+ it.each(['site', 'api'] as const)(
+ 'keeps the saved %s status when reopening an environment without changing another environment',
+ async (target) => {
+ const user = userEvent.setup()
+ const queryClient = createTestQueryClient()
+ const card = (environmentId: string) =>
+ target === 'site' ? (
+
+ ) : (
+
+ )
+
+ const staging = renderCard(card('staging'), queryClient)
+ const toggle = await screen.findByRole('switch')
+ expect(toggle).toHaveAttribute('aria-checked', 'true')
+ await user.click(toggle)
+ await waitFor(() =>
+ expect(target === 'site' ? mocks.updateSite : mocks.updateApi).toHaveBeenCalled(),
+ )
+ staging.unmount()
+
+ const production = renderCard(card('production'), queryClient)
+ expect(await screen.findByRole('switch')).toHaveAttribute('aria-checked', 'true')
+ production.unmount()
+
+ renderCard(card('staging'), queryClient)
+ expect(await screen.findByRole('switch')).toHaveAttribute('aria-checked', 'false')
+ },
+ )
+
it('sends a chatflow app to the chat web app shell', async () => {
mockAppMode = 'advanced-chat'
@@ -258,8 +274,6 @@ describe('environment access point cards', () => {
expect(await screen.findByText(/environment\/chat\/site-code/)).toHaveTextContent(
'https://site.example.test/environment/chat/site-code',
)
-
- mockAppMode = 'workflow'
})
it('renders the real environment Web app URL and workflow actions without Embed', async () => {
@@ -281,7 +295,9 @@ describe('environment access point cards', () => {
}),
).toBeEnabled()
expect(screen.queryByRole('button', { name: /embedIntoSite/ })).not.toBeInTheDocument()
- expect(screen.getByRole('button', { name: /customize\.entry/ })).toBeEnabled()
+ await waitFor(() =>
+ expect(screen.getByRole('button', { name: /customize\.entry/ })).toBeEnabled(),
+ )
expect(screen.getByRole('button', { name: /settings\.settings/ })).toBeEnabled()
})
@@ -307,8 +323,9 @@ describe('environment access point cards', () => {
).toBeEnabled()
})
- it('shows the environment Web app query as loading instead of failed', () => {
- mocks.getSite.mockImplementation(() => new Promise(() => {}))
+ it('shows loading until the environment Web app becomes available', async () => {
+ const pending = createDeferredPromise()
+ mocks.getSite.mockReturnValue(pending.promise)
renderCard(
{
expect(
screen.queryByText('deployments.health.ENVIRONMENT_STATUS_FAILED'),
).not.toBeInTheDocument()
+ pending.resolve(site)
+ expect(await screen.findByRole('link', { name: /studio\.accessPoint\.open/ })).toBeEnabled()
+ expect(card).not.toHaveAttribute('aria-busy', 'true')
})
it('does not announce the access control placeholder as loading after the Site query fails', async () => {
@@ -446,6 +466,9 @@ describe('environment access point cards', () => {
)
await screen.findByText(/environment\/workflow\/site-code/)
+ await waitFor(() =>
+ expect(screen.getByRole('button', { name: /customize\.entry/ })).toBeEnabled(),
+ )
await user.click(screen.getByRole('button', { name: /customize\.entry/ }))
expect(screen.getByRole('dialog', { name: 'environment customize' })).toHaveTextContent(
'https://api.example.test/v1',
@@ -487,7 +510,9 @@ describe('environment access point cards', () => {
expect(await screen.findByRole('switch')).toBeEnabled()
expect(screen.getByRole('button', { name: /regenerate/ })).toBeEnabled()
- expect(screen.getByRole('button', { name: /customize\.entry/ })).toBeEnabled()
+ await waitFor(() =>
+ expect(screen.getByRole('button', { name: /customize\.entry/ })).toBeEnabled(),
+ )
expect(screen.getByRole('button', { name: /settings\.settings/ })).toBeEnabled()
expect(
screen.getByRole('button', { name: /accessControlDialog\.accessItems\.specific/ }),
diff --git a/web/app/components/app/access-point/__tests__/index.spec.tsx b/web/app/components/app/access-point/__tests__/index.spec.tsx
index 493216c0316..ee234efb99f 100644
--- a/web/app/components/app/access-point/__tests__/index.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/index.spec.tsx
@@ -5,7 +5,7 @@ import { EnvironmentStatus } from '@dify/contracts/enterprise-app-deploy/types.g
import { screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { NuqsTestingAdapter } from 'nuqs/adapters/testing'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { QueryClientTestProvider } from '@/test/console/query-provider'
import { render } from '@/test/console/render'
diff --git a/web/app/components/app/access-point/__tests__/mcp-card.spec.tsx b/web/app/components/app/access-point/__tests__/mcp-card.spec.tsx
index 1f96c4a5429..2e47e1084bd 100644
--- a/web/app/components/app/access-point/__tests__/mcp-card.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/mcp-card.spec.tsx
@@ -27,7 +27,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
},
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/app/access-point/__tests__/service-api-card.spec.tsx b/web/app/components/app/access-point/__tests__/service-api-card.spec.tsx
index 3fac29c2f3d..f317ef8880a 100644
--- a/web/app/components/app/access-point/__tests__/service-api-card.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/service-api-card.spec.tsx
@@ -21,7 +21,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
},
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/app/access-point/__tests__/trigger-card.spec.tsx b/web/app/components/app/access-point/__tests__/trigger-card.spec.tsx
index aeac874d8ba..c07e7592f70 100644
--- a/web/app/components/app/access-point/__tests__/trigger-card.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/trigger-card.spec.tsx
@@ -39,7 +39,7 @@ vi.mock('@/context/i18n', () => ({
useDocLink: () => (path: string) => `https://docs.example.test/en${path}`,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/app/access-point/__tests__/use-access-point-actions.spec.ts b/web/app/components/app/access-point/__tests__/use-access-point-actions.spec.ts
index 3d192055cce..b0b169bbc0b 100644
--- a/web/app/components/app/access-point/__tests__/use-access-point-actions.spec.ts
+++ b/web/app/components/app/access-point/__tests__/use-access-point-actions.spec.ts
@@ -23,7 +23,7 @@ vi.mock('@/service/apps', () => ({
updateAppSiteConfig: mocks.updateAppSiteConfig,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
get: { key: () => ['apps'] },
diff --git a/web/app/components/app/access-point/__tests__/web-app-card.spec.tsx b/web/app/components/app/access-point/__tests__/web-app-card.spec.tsx
index aa96922b3d6..4115a40e206 100644
--- a/web/app/components/app/access-point/__tests__/web-app-card.spec.tsx
+++ b/web/app/components/app/access-point/__tests__/web-app-card.spec.tsx
@@ -25,7 +25,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
},
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/app/access-point/built-in-access-points/mcp-card.tsx b/web/app/components/app/access-point/built-in-access-points/mcp-card.tsx
index a3cd201d887..eff1bf597fe 100644
--- a/web/app/components/app/access-point/built-in-access-points/mcp-card.tsx
+++ b/web/app/components/app/access-point/built-in-access-points/mcp-card.tsx
@@ -19,7 +19,7 @@ import { AccessPointCard } from '@/app/components/base/access-point/card'
import { AccessPointUrl } from '@/app/components/base/access-point/url'
import MCPServerModal from '@/app/components/tools/mcp/mcp-server-modal'
import { BlockEnum } from '@/app/components/workflow/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
useInvalidateMCPServerDetail,
useMCPServerDetail,
diff --git a/web/app/components/app/access-point/built-in-access-points/service-api-card.tsx b/web/app/components/app/access-point/built-in-access-points/service-api-card.tsx
index fb47f578ea3..09f1506ce88 100644
--- a/web/app/components/app/access-point/built-in-access-points/service-api-card.tsx
+++ b/web/app/components/app/access-point/built-in-access-points/service-api-card.tsx
@@ -7,7 +7,7 @@ import { useMutation } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
import { getAccessPointStatus } from '@/app/components/base/access-point/status'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ServiceApiCardView } from '../shared/service-api-card-view'
import { getBuiltInAccessUrls } from '../shared/utils'
diff --git a/web/app/components/app/access-point/built-in-access-points/trigger-card.tsx b/web/app/components/app/access-point/built-in-access-points/trigger-card.tsx
index ad57d3252fe..a5850a1f8ca 100644
--- a/web/app/components/app/access-point/built-in-access-points/trigger-card.tsx
+++ b/web/app/components/app/access-point/built-in-access-points/trigger-card.tsx
@@ -15,7 +15,7 @@ import { useTriggerStatusStore } from '@/app/components/workflow/store/trigger-s
import { BlockEnum } from '@/app/components/workflow/types'
import { useDocLink } from '@/context/i18n'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useAppTriggers, useInvalidateAppTriggers } from '@/service/use-tools'
import { useAllTriggerPlugins } from '@/service/use-triggers'
import { canFindTool } from '@/utils'
diff --git a/web/app/components/app/access-point/built-in-access-points/web-app-card.tsx b/web/app/components/app/access-point/built-in-access-points/web-app-card.tsx
index 787db1dc263..6f7e09de87c 100644
--- a/web/app/components/app/access-point/built-in-access-points/web-app-card.tsx
+++ b/web/app/components/app/access-point/built-in-access-points/web-app-card.tsx
@@ -30,7 +30,7 @@ import { AccessPointUrl } from '@/app/components/base/access-point/url'
import AppIcon from '@/app/components/base/app-icon'
import { AccessMode } from '@/models/access-control'
import { useAppWhiteListSubjects } from '@/service/access-control/use-app-access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { useAccessPointStatusLabel } from '../shared/use-access-point-status-label'
import { getBuiltInAccessUrls, getHiddenStartInputs } from '../shared/utils'
diff --git a/web/app/components/app/access-point/deployed-environment-access-points/environment-access-control.tsx b/web/app/components/app/access-point/deployed-environment-access-points/environment-access-control.tsx
index 64637ef4afd..3213bcb5afc 100644
--- a/web/app/components/app/access-point/deployed-environment-access-points/environment-access-control.tsx
+++ b/web/app/components/app/access-point/deployed-environment-access-points/environment-access-control.tsx
@@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next'
import { AccessControlForm } from '@/app/components/app/app-access-control/access-control-form'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AccessMode, SubjectType } from '@/models/access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const EMPTY_SUBJECTS: AccessControlSubjects = {
groups: [],
diff --git a/web/app/components/app/access-point/deployed-environment-access-points/environment-service-api-card.tsx b/web/app/components/app/access-point/deployed-environment-access-points/environment-service-api-card.tsx
index 9641b96b81a..bcc25889b07 100644
--- a/web/app/components/app/access-point/deployed-environment-access-points/environment-service-api-card.tsx
+++ b/web/app/components/app/access-point/deployed-environment-access-points/environment-service-api-card.tsx
@@ -4,7 +4,7 @@ import { toast } from '@langgenius/dify-ui/toast'
import { useMutation, useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ServiceApiCardView } from '../shared/service-api-card-view'
type EnvironmentServiceApiCardProps = {
diff --git a/web/app/components/app/access-point/deployed-environment-access-points/environment-web-app-card.tsx b/web/app/components/app/access-point/deployed-environment-access-points/environment-web-app-card.tsx
index cf6651a67ab..0e8ce4ca6e6 100644
--- a/web/app/components/app/access-point/deployed-environment-access-points/environment-web-app-card.tsx
+++ b/web/app/components/app/access-point/deployed-environment-access-points/environment-web-app-card.tsx
@@ -23,7 +23,7 @@ import { AccessPointUrl } from '@/app/components/base/access-point/url'
import AppIcon from '@/app/components/base/app-icon'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AccessMode, isAccessMode } from '@/models/access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useAccessPointActions } from '../shared/use-access-point-actions'
import { useAccessPointStatusLabel } from '../shared/use-access-point-status-label'
import {
diff --git a/web/app/components/app/access-point/shared/api-secret-key-button.tsx b/web/app/components/app/access-point/shared/api-secret-key-button.tsx
index c640e5ca51d..2341797888e 100644
--- a/web/app/components/app/access-point/shared/api-secret-key-button.tsx
+++ b/web/app/components/app/access-point/shared/api-secret-key-button.tsx
@@ -6,7 +6,7 @@ import { skipToken, useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ApiKeyModal } from '@/app/components/api-key/api-key-modal'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type ApiSecretKeyButtonProps = {
appId: string
diff --git a/web/app/components/app/access-point/shared/use-access-point-actions.ts b/web/app/components/app/access-point/shared/use-access-point-actions.ts
index c82373dea0b..eb82d3d5743 100644
--- a/web/app/components/app/access-point/shared/use-access-point-actions.ts
+++ b/web/app/components/app/access-point/shared/use-access-point-actions.ts
@@ -9,7 +9,7 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
import { fetchAppDetail, updateAppSiteConfig } from '@/service/apps'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { asyncRunSafe } from '@/utils'
export function useAccessPointActions(appId: string, canManageAccessPoint: boolean) {
diff --git a/web/app/components/app/access-point/state.ts b/web/app/components/app/access-point/state.ts
index e83e759b670..410c7c4d761 100644
--- a/web/app/components/app/access-point/state.ts
+++ b/web/app/components/app/access-point/state.ts
@@ -5,7 +5,7 @@ import { skipToken } from '@tanstack/react-query'
import { atom } from 'jotai'
import { atomWithQuery } from 'jotai-tanstack-query'
import { selectAtom, useHydrateAtoms } from 'jotai/utils'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const BUILT_IN_ENVIRONMENT_ID = 'built-in'
diff --git a/web/app/components/app/annotation/add-annotation-modal/index.tsx b/web/app/components/app/annotation/add-annotation-modal/index.tsx
index fc44d0285bc..f42400f84d0 100644
--- a/web/app/components/app/annotation/add-annotation-modal/index.tsx
+++ b/web/app/components/app/annotation/add-annotation-modal/index.tsx
@@ -21,7 +21,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import AnnotationFull from '@/app/components/billing/annotation-full'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import EditItem, { EditItemType } from './edit-item'
type Props = Readonly<{
diff --git a/web/app/components/app/annotation/batch-add-annotation-modal/index.tsx b/web/app/components/app/annotation/batch-add-annotation-modal/index.tsx
index 4d6348e817e..ff4d2ba0242 100644
--- a/web/app/components/app/annotation/batch-add-annotation-modal/index.tsx
+++ b/web/app/components/app/annotation/batch-add-annotation-modal/index.tsx
@@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next'
import AnnotationFull from '@/app/components/billing/annotation-full'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { annotationBatchImport, checkAnnotationBatchImportProgress } from '@/service/annotation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import CSVDownloader from './csv-downloader'
import CSVUploader from './csv-uploader'
diff --git a/web/app/components/app/annotation/index.tsx b/web/app/components/app/annotation/index.tsx
index a42f2e7440e..6a3297f7b2a 100644
--- a/web/app/components/app/annotation/index.tsx
+++ b/web/app/components/app/annotation/index.tsx
@@ -34,7 +34,7 @@ import {
updateAnnotationScore,
updateAnnotationStatus,
} from '@/service/annotation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { sleep } from '@/utils'
import PageTitle from '../log-annotation/page-title'
diff --git a/web/app/components/app/app-access-control/__tests__/index.spec.tsx b/web/app/components/app/app-access-control/__tests__/index.spec.tsx
index 4a3463896f0..5e41e3cd594 100644
--- a/web/app/components/app/app-access-control/__tests__/index.spec.tsx
+++ b/web/app/components/app/app-access-control/__tests__/index.spec.tsx
@@ -32,7 +32,7 @@ vi.mock('@/service/access-control', () => ({
mockUseSearchForWhiteListCandidates(...args),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/app/app-access-control/index.tsx b/web/app/components/app/app-access-control/index.tsx
index 24b1fe341da..b6fddfe41d4 100644
--- a/web/app/components/app/app-access-control/index.tsx
+++ b/web/app/components/app/app-access-control/index.tsx
@@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AccessMode, isAccessMode, SubjectType } from '@/models/access-control'
import { useAppWhiteListSubjects } from '@/service/access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AccessControlForm } from './access-control-form'
const EMPTY_SUBJECTS: AccessControlSubjects = {
diff --git a/web/app/components/app/app-publisher/__tests__/environment-deployment-flow.spec.tsx b/web/app/components/app/app-publisher/__tests__/environment-deployment-flow.spec.tsx
index e151473db72..96642b8c1fe 100644
--- a/web/app/components/app/app-publisher/__tests__/environment-deployment-flow.spec.tsx
+++ b/web/app/components/app/app-publisher/__tests__/environment-deployment-flow.spec.tsx
@@ -14,7 +14,7 @@ import userEvent from '@testing-library/user-event'
import { createStore, Provider, useAtomValue, useSetAtom } from 'jotai'
import { queryClientAtom } from 'jotai-tanstack-query'
import { useEffect } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
renderWithConsoleQuery as render,
diff --git a/web/app/components/app/app-publisher/__tests__/index.spec.tsx b/web/app/components/app/app-publisher/__tests__/index.spec.tsx
index 00b556e018c..e174dc0674e 100644
--- a/web/app/components/app/app-publisher/__tests__/index.spec.tsx
+++ b/web/app/components/app/app-publisher/__tests__/index.spec.tsx
@@ -5,7 +5,7 @@ import userEvent from '@testing-library/user-event'
import * as React from 'react'
import { WorkflowContext } from '@/app/components/workflow/context'
import { AccessMode } from '@/models/access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { appWorkflowVersionsInfiniteQueryOptions } from '@/service/workflow-queries'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { AppModeEnum } from '@/types/app'
diff --git a/web/app/components/app/app-publisher/__tests__/state.spec.tsx b/web/app/components/app/app-publisher/__tests__/state.spec.tsx
index 624205f869a..2652e4f7ebd 100644
--- a/web/app/components/app/app-publisher/__tests__/state.spec.tsx
+++ b/web/app/components/app/app-publisher/__tests__/state.spec.tsx
@@ -51,7 +51,7 @@ const queryMocks = vi.hoisted(() => ({
environmentRequest: vi.fn(),
}))
-vi.mock('@/service/client', async () => {
+vi.mock('@/service/console', async () => {
const { skipToken } = await import('@tanstack/react-query')
return {
diff --git a/web/app/components/app/app-publisher/hooks/use-refresh-app-environments-after-deployment-polling.ts b/web/app/components/app/app-publisher/hooks/use-refresh-app-environments-after-deployment-polling.ts
index de262d0263d..e8cf084b3f6 100644
--- a/web/app/components/app/app-publisher/hooks/use-refresh-app-environments-after-deployment-polling.ts
+++ b/web/app/components/app/app-publisher/hooks/use-refresh-app-environments-after-deployment-polling.ts
@@ -5,7 +5,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useRef } from 'react'
import { shouldPollEnvironmentDeployment } from '@/app/components/app/deploy/utils/environment-deployment'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
appPublisherOpenAtom,
finishPublisherEnvironmentDeploymentPollingAtom,
diff --git a/web/app/components/app/app-publisher/publisher-content/use-publish-controller.ts b/web/app/components/app/app-publisher/publisher-content/use-publish-controller.ts
index 67b280867f2..6f7052cd4b0 100644
--- a/web/app/components/app/app-publisher/publisher-content/use-publish-controller.ts
+++ b/web/app/components/app/app-publisher/publisher-content/use-publish-controller.ts
@@ -12,7 +12,7 @@ import { trackEvent } from '@/app/components/base/amplitude'
import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager'
import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager'
import { WorkflowContext } from '@/app/components/workflow/context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useAppWorkflow, useInvalidateAppWorkflow } from '@/service/use-workflow'
import {
appWorkflowQueryOptions,
diff --git a/web/app/components/app/app-publisher/state.ts b/web/app/components/app/app-publisher/state.ts
index 87bbf47eb44..190e79d2b88 100644
--- a/web/app/components/app/app-publisher/state.ts
+++ b/web/app/components/app/app-publisher/state.ts
@@ -7,7 +7,7 @@ import { atom } from 'jotai'
import { atomWithQuery } from 'jotai-tanstack-query'
import { selectAtom, useHydrateAtoms } from 'jotai/utils'
import { shouldPollEnvironmentDeployment } from '@/app/components/app/deploy/utils/environment-deployment'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const BUILT_IN_ENVIRONMENT_ID = 'built-in'
const PUBLISHER_DEPLOYMENT_POLLING_INTERVAL = 3000
diff --git a/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx b/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx
index 083e6fafc7f..ea078771e37 100644
--- a/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx
+++ b/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx
@@ -25,7 +25,7 @@ import Loading from '@/app/components/base/loading'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { generateBasicAppFirstTimeRule, generateRule } from '@/service/debug'
import { useAutoGenModel } from '../auto-gen-model-storage'
import IdeaOutput from './idea-output'
diff --git a/web/app/components/app/configuration/config/code-generator/get-code-generator-res.tsx b/web/app/components/app/configuration/config/code-generator/get-code-generator-res.tsx
index 7d015e4501e..ce0a57b76d9 100644
--- a/web/app/components/app/configuration/config/code-generator/get-code-generator-res.tsx
+++ b/web/app/components/app/configuration/config/code-generator/get-code-generator-res.tsx
@@ -24,7 +24,7 @@ import Loading from '@/app/components/base/loading'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { generateRule } from '@/service/debug'
import { languageMap } from '../../../../workflow/nodes/_base/components/editor/code-editor/index'
import { useAutoGenModel } from '../auto-gen-model-storage'
diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx
index acd85b398ce..250031dea3c 100644
--- a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx
+++ b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/index.spec.tsx
@@ -13,7 +13,7 @@ import {
DataSourceType,
RerankingModeEnum,
} from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { updateDatasetSetting } from '@/service/datasets'
import { useMembers } from '@/service/use-common'
import { seedAccountProfileQuery } from '@/test/console/account-profile'
diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx
index 16c60ea0038..3f2681a1de2 100644
--- a/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx
+++ b/web/app/components/app/configuration/dataset-config/settings-modal/__tests__/retrieval-section.spec.tsx
@@ -12,7 +12,7 @@ import {
DataSourceType,
RerankingModeEnum,
} from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { withSelectorKey } from '@/test/i18n-mock'
import { RETRIEVE_METHOD } from '@/types/app'
diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx
index 886b2a41a43..3a6ec1662ac 100644
--- a/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx
+++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx
@@ -17,7 +17,7 @@ import ModelName from '@/app/components/header/account-setting/model-provider-pa
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
import { useCredentialPanelState } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state'
import { useDebugConfigurationContext } from '@/context/debug-configuration'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useDebugWithMultipleModelContext } from './context'
type ModelParameterTriggerProps = {
diff --git a/web/app/components/app/configuration/hooks/__tests__/use-configuration.spec.tsx b/web/app/components/app/configuration/hooks/__tests__/use-configuration.spec.tsx
index 4781627325e..55a52e81086 100644
--- a/web/app/components/app/configuration/hooks/__tests__/use-configuration.spec.tsx
+++ b/web/app/components/app/configuration/hooks/__tests__/use-configuration.spec.tsx
@@ -1,7 +1,7 @@
/* oxlint-disable typescript/no-explicit-any */
import { act, waitFor } from '@testing-library/react'
import { updateAppModelConfig } from '@/service/apps'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { createQueryClientWrapper } from '@/test/console/query-client'
import { renderHook as renderHookWithConsoleState } from '@/test/console/render'
diff --git a/web/app/components/app/configuration/hooks/configuration-lifecycle/use-configuration-app-context.ts b/web/app/components/app/configuration/hooks/configuration-lifecycle/use-configuration-app-context.ts
index fb6ff9256b8..aee4a24f53c 100644
--- a/web/app/components/app/configuration/hooks/configuration-lifecycle/use-configuration-app-context.ts
+++ b/web/app/components/app/configuration/hooks/configuration-lifecycle/use-configuration-app-context.ts
@@ -8,7 +8,7 @@ import { currentWorkspaceAtom, currentWorkspaceLoadingAtom } from '@/context/wor
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { usePathname } from '@/next/navigation'
import { updateAppModelConfig } from '@/service/apps'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getAppACLCapabilities } from '@/utils/permission'
export function useConfigurationAppContext() {
diff --git a/web/app/components/app/create-app-dialog/app-list/__tests__/index.spec.tsx b/web/app/components/app/create-app-dialog/app-list/__tests__/index.spec.tsx
index 3cf0c9f285f..4c36c5d6990 100644
--- a/web/app/components/app/create-app-dialog/app-list/__tests__/index.spec.tsx
+++ b/web/app/components/app/create-app-dialog/app-list/__tests__/index.spec.tsx
@@ -131,8 +131,8 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
vi.mock('@/utils/create-app-tracking', () => ({
trackCreateApp: (...args: unknown[]) => mockTrackCreateApp(...args),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
diff --git a/web/app/components/app/create-app-dialog/app-list/index.tsx b/web/app/components/app/create-app-dialog/app-list/index.tsx
index cf4aa352e2b..691a97eac43 100644
--- a/web/app/components/app/create-app-dialog/app-list/index.tsx
+++ b/web/app/components/app/create-app-dialog/app-list/index.tsx
@@ -21,7 +21,7 @@ import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchAppDetail } from '@/service/explore'
import { useExploreAppList } from '@/service/use-explore'
import { AppModeEnum } from '@/types/app'
diff --git a/web/app/components/app/create-app-modal/__tests__/index.spec.tsx b/web/app/components/app/create-app-modal/__tests__/index.spec.tsx
index 938c1526445..3bbe0d7c8a1 100644
--- a/web/app/components/app/create-app-modal/__tests__/index.spec.tsx
+++ b/web/app/components/app/create-app-modal/__tests__/index.spec.tsx
@@ -41,8 +41,8 @@ vi.mock('@/next/navigation', () => ({
vi.mock('@/utils/create-app-tracking', () => ({
trackCreateApp: vi.fn(),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
diff --git a/web/app/components/app/create-app-modal/index.tsx b/web/app/components/app/create-app-modal/index.tsx
index 278b9be4689..47f2810f4ea 100644
--- a/web/app/components/app/create-app-modal/index.tsx
+++ b/web/app/components/app/create-app-modal/index.tsx
@@ -23,7 +23,7 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import useTheme from '@/hooks/use-theme'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { trackCreateApp } from '@/utils/create-app-tracking'
diff --git a/web/app/components/app/create-from-dsl-modal/__tests__/index.spec.tsx b/web/app/components/app/create-from-dsl-modal/__tests__/index.spec.tsx
index 0b6550197ae..91c86dd84d9 100644
--- a/web/app/components/app/create-from-dsl-modal/__tests__/index.spec.tsx
+++ b/web/app/components/app/create-from-dsl-modal/__tests__/index.spec.tsx
@@ -63,8 +63,8 @@ vi.mock('@/utils/create-app-tracking', () => ({
trackCreateApp: (...args: unknown[]) => mockTrackCreateApp(...args),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleClient: {
diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx
index 5971c98be32..5959ac3f7d6 100644
--- a/web/app/components/app/create-from-dsl-modal/index.tsx
+++ b/web/app/components/app/create-from-dsl-modal/index.tsx
@@ -29,7 +29,7 @@ import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum as AppMode } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { trackCreateApp } from '@/utils/create-app-tracking'
diff --git a/web/app/components/app/deploy/__tests__/index.spec.tsx b/web/app/components/app/deploy/__tests__/index.spec.tsx
index 9a60a3b97b3..956e7dc3592 100644
--- a/web/app/components/app/deploy/__tests__/index.spec.tsx
+++ b/web/app/components/app/deploy/__tests__/index.spec.tsx
@@ -22,7 +22,7 @@ import {
import { toast } from '@langgenius/dify-ui/toast'
import { act, screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
appWorkflowQueryOptions,
appWorkflowVersionsInfiniteQueryOptions,
diff --git a/web/app/components/app/deploy/__tests__/state.spec.tsx b/web/app/components/app/deploy/__tests__/state.spec.tsx
index 553b365ac79..558cde89557 100644
--- a/web/app/components/app/deploy/__tests__/state.spec.tsx
+++ b/web/app/components/app/deploy/__tests__/state.spec.tsx
@@ -27,7 +27,7 @@ const queryOptionsMocks = vi.hoisted(() => ({
versions: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/app/deploy/hooks/use-deploy-workflow.ts b/web/app/components/app/deploy/hooks/use-deploy-workflow.ts
index 9fb87df2e80..3d98e25446b 100644
--- a/web/app/components/app/deploy/hooks/use-deploy-workflow.ts
+++ b/web/app/components/app/deploy/hooks/use-deploy-workflow.ts
@@ -2,7 +2,7 @@
import type { DeployWorkflowResponse } from '@dify/contracts/enterprise-app-deploy/types.gen'
import { useMutation, useQueryClient } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function useDeployWorkflow({
appId,
diff --git a/web/app/components/app/deploy/hooks/use-refresh-app-environments-after-deployment-polling.ts b/web/app/components/app/deploy/hooks/use-refresh-app-environments-after-deployment-polling.ts
index b3b02c37f3e..01747fb24b9 100644
--- a/web/app/components/app/deploy/hooks/use-refresh-app-environments-after-deployment-polling.ts
+++ b/web/app/components/app/deploy/hooks/use-refresh-app-environments-after-deployment-polling.ts
@@ -3,7 +3,7 @@
import type { ListEnvironmentDeploymentsResponse } from '@dify/contracts/enterprise-app-deploy/types.gen'
import { hashKey, useQueryClient } from '@tanstack/react-query'
import { useEffect } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasDeploymentsRequiringPolling } from '../utils/environment-deployment'
export function useRefreshAppEnvironmentsAfterDeploymentPolling(appId: string) {
diff --git a/web/app/components/app/deploy/hooks/use-undeploy-workflow.ts b/web/app/components/app/deploy/hooks/use-undeploy-workflow.ts
index 1dbf3a7705b..7666906fd34 100644
--- a/web/app/components/app/deploy/hooks/use-undeploy-workflow.ts
+++ b/web/app/components/app/deploy/hooks/use-undeploy-workflow.ts
@@ -5,7 +5,7 @@ import { toast } from '@langgenius/dify-ui/toast'
import { useMutation } from '@tanstack/react-query'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function useUndeployWorkflow(appId: string) {
const { t } = useTranslation('deployments')
diff --git a/web/app/components/app/deploy/shared/deployment-configuration/use-deployment-configuration-queries.ts b/web/app/components/app/deploy/shared/deployment-configuration/use-deployment-configuration-queries.ts
index 2a95046cbda..5481e8c24de 100644
--- a/web/app/components/app/deploy/shared/deployment-configuration/use-deployment-configuration-queries.ts
+++ b/web/app/components/app/deploy/shared/deployment-configuration/use-deployment-configuration-queries.ts
@@ -2,7 +2,7 @@
import type { QueryFunction } from '@tanstack/react-query'
import { skipToken, useQuery } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { normalizeDeploymentError } from './utils/deployment-error'
function withNormalizedDeploymentError(queryFn: QueryFunction): QueryFunction {
diff --git a/web/app/components/app/deploy/state.ts b/web/app/components/app/deploy/state.ts
index e634cba9839..789889a54f5 100644
--- a/web/app/components/app/deploy/state.ts
+++ b/web/app/components/app/deploy/state.ts
@@ -6,7 +6,7 @@ import { atom } from 'jotai'
import { atomWithInfiniteQuery, atomWithQuery } from 'jotai-tanstack-query'
import { selectAtom, useHydrateAtoms } from 'jotai/utils'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
appWorkflowQueryOptions,
appWorkflowVersionsInfiniteQueryOptions,
diff --git a/web/app/components/app/duplicate-modal/__tests__/index.spec.tsx b/web/app/components/app/duplicate-modal/__tests__/index.spec.tsx
index 1244a97777a..1f5adc98622 100644
--- a/web/app/components/app/duplicate-modal/__tests__/index.spec.tsx
+++ b/web/app/components/app/duplicate-modal/__tests__/index.spec.tsx
@@ -1,7 +1,7 @@
import type { ReactElement } from 'react'
import { act, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
renderWithConsoleQuery,
diff --git a/web/app/components/app/duplicate-modal/index.tsx b/web/app/components/app/duplicate-modal/index.tsx
index 093e842f7ac..85e6cab976b 100644
--- a/web/app/components/app/duplicate-modal/index.tsx
+++ b/web/app/components/app/duplicate-modal/index.tsx
@@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import AppIconPicker from '../../base/app-icon-picker'
export type DuplicateAppModalProps = {
diff --git a/web/app/components/app/in-site-message/__tests__/notification.spec.tsx b/web/app/components/app/in-site-message/__tests__/notification.spec.tsx
index 15d750be46a..813166e71e0 100644
--- a/web/app/components/app/in-site-message/__tests__/notification.spec.tsx
+++ b/web/app/components/app/in-site-message/__tests__/notification.spec.tsx
@@ -16,7 +16,7 @@ vi.mock('@/context/i18n', () => ({
useLocale: () => mockLocale.value,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/app/in-site-message/notification.tsx b/web/app/components/app/in-site-message/notification.tsx
index cee2b2a9137..f18e4bc87d0 100644
--- a/web/app/components/app/in-site-message/notification.tsx
+++ b/web/app/components/app/in-site-message/notification.tsx
@@ -5,7 +5,7 @@ import { useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { useLocale } from '@/context/i18n'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import InSiteMessage from './index'
type NotificationBodyPayload = {
diff --git a/web/app/components/app/log/__tests__/filter.spec.tsx b/web/app/components/app/log/__tests__/filter.spec.tsx
index b06f5bce7c1..fda389b312f 100644
--- a/web/app/components/app/log/__tests__/filter.spec.tsx
+++ b/web/app/components/app/log/__tests__/filter.spec.tsx
@@ -3,7 +3,7 @@ import type { DeploymentEdition } from '@dify/contracts/api/console/system-featu
import type { ReactElement } from 'react'
import type { QueryParam } from '../index'
import { act, fireEvent, screen, waitFor, within } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
renderWithConsoleQuery,
diff --git a/web/app/components/app/log/__tests__/retention-upgrade-notice.spec.tsx b/web/app/components/app/log/__tests__/retention-upgrade-notice.spec.tsx
index a27bce8618c..52027ad8e20 100644
--- a/web/app/components/app/log/__tests__/retention-upgrade-notice.spec.tsx
+++ b/web/app/components/app/log/__tests__/retention-upgrade-notice.spec.tsx
@@ -3,7 +3,7 @@ import type { DeploymentEdition } from '@dify/contracts/api/console/system-featu
import { screen, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryWrapper, seedFeatures } from '@/test/console/query-data'
import { render } from '@/test/console/render'
import { RetentionUpgradeNotice } from '../retention-upgrade-notice'
diff --git a/web/app/components/app/log/archived-logs-notice.tsx b/web/app/components/app/log/archived-logs-notice.tsx
index 2d3a8f596d3..760de397b88 100644
--- a/web/app/components/app/log/archived-logs-notice.tsx
+++ b/web/app/components/app/log/archived-logs-notice.tsx
@@ -11,7 +11,7 @@ import {
} from '@/app/components/header/account-setting/query-params'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function ArchivedLogsNotice() {
const { t } = useTranslation()
diff --git a/web/app/components/app/log/cloud-sandbox-retention.ts b/web/app/components/app/log/cloud-sandbox-retention.ts
index 0938009169d..249aabcbc37 100644
--- a/web/app/components/app/log/cloud-sandbox-retention.ts
+++ b/web/app/components/app/log/cloud-sandbox-retention.ts
@@ -2,7 +2,7 @@
import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const CLOUD_SANDBOX_TIME_PERIOD_KEYS = new Set(['1', '2', '3'])
export const CLOUD_SANDBOX_CLEARED_TIME_PERIOD = '1'
diff --git a/web/app/components/app/overview/app-chart.tsx b/web/app/components/app/overview/app-chart.tsx
index 72f881a71c3..17dad0ef55e 100644
--- a/web/app/components/app/overview/app-chart.tsx
+++ b/web/app/components/app/overview/app-chart.tsx
@@ -11,7 +11,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { Infotip } from '@/app/components/base/infotip'
import Loading from '@/app/components/base/loading'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
buildChartOptions,
CHART_TYPE_CONFIG,
diff --git a/web/app/components/app/overview/settings/__tests__/index.spec.tsx b/web/app/components/app/overview/settings/__tests__/index.spec.tsx
index 9ccffe22e42..760b47c7d59 100644
--- a/web/app/components/app/overview/settings/__tests__/index.spec.tsx
+++ b/web/app/components/app/overview/settings/__tests__/index.spec.tsx
@@ -3,7 +3,7 @@ import type { ModalContextState } from '@/context/modal-context'
import type { AppDetailResponse } from '@/models/app'
import type { AppSSO } from '@/types/app'
import { fireEvent, screen, waitFor } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { AppModeEnum } from '@/types/app'
import SettingsModal from '../index'
diff --git a/web/app/components/app/overview/settings/index.tsx b/web/app/components/app/overview/settings/index.tsx
index 5db38dd9225..f112427a6ba 100644
--- a/web/app/components/app/overview/settings/index.tsx
+++ b/web/app/components/app/overview/settings/index.tsx
@@ -41,7 +41,7 @@ import { useModalContext } from '@/context/modal-context'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { languages } from '@/i18n-config/language'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
type ISettingsModalProps = {
diff --git a/web/app/components/app/switch-app-modal/index.tsx b/web/app/components/app/switch-app-modal/index.tsx
index 9d28d705372..ba56025dbf8 100644
--- a/web/app/components/app/switch-app-modal/index.tsx
+++ b/web/app/components/app/switch-app-modal/index.tsx
@@ -25,7 +25,7 @@ import AppIcon from '@/app/components/base/app-icon'
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import AppIconPicker from '../../base/app-icon-picker'
diff --git a/web/app/components/app/use-export-app-dsl.ts b/web/app/components/app/use-export-app-dsl.ts
index f6f873fe126..5d1975d2c18 100644
--- a/web/app/components/app/use-export-app-dsl.ts
+++ b/web/app/components/app/use-export-app-dsl.ts
@@ -5,7 +5,7 @@ import { toast } from '@langgenius/dify-ui/toast'
import { useMutation } from '@tanstack/react-query'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { downloadBlob } from '@/utils/download'
type ExportAppDslInput = {
diff --git a/web/app/components/apps/__tests__/app-card.spec.tsx b/web/app/components/apps/__tests__/app-card.spec.tsx
index cd93f052ab1..2ebd6354a65 100644
--- a/web/app/components/apps/__tests__/app-card.spec.tsx
+++ b/web/app/components/apps/__tests__/app-card.spec.tsx
@@ -48,8 +48,8 @@ const mockUnstarAppMutation = vi.hoisted(() =>
vi.fn((_variables: unknown): Promise => Promise.resolve()),
)
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const withMutation = (operation: object, mutationFn: typeof mockCopyApp) =>
new Proxy(operation, {
get(target, property, receiver) {
diff --git a/web/app/components/apps/__tests__/list.spec.tsx b/web/app/components/apps/__tests__/list.spec.tsx
index fbc72fcf045..545e29974ca 100644
--- a/web/app/components/apps/__tests__/list.spec.tsx
+++ b/web/app/components/apps/__tests__/list.spec.tsx
@@ -79,7 +79,7 @@ vi.mock('@/next/navigation', () => ({
useSearchParams: () => mockSearchParams,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
systemFeatures: {
get: vi.fn(),
diff --git a/web/app/components/apps/app-card/interactions.tsx b/web/app/components/apps/app-card/interactions.tsx
index df7288420cf..23713d5439f 100644
--- a/web/app/components/apps/app-card/interactions.tsx
+++ b/web/app/components/apps/app-card/interactions.tsx
@@ -58,7 +58,7 @@ import { AccessMode } from '@/models/access-control'
import dynamic from '@/next/dynamic'
import { useRouter } from '@/next/navigation'
import { useGetUserCanAccessApp } from '@/service/access-control/use-app-access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchInstalledAppList } from '@/service/explore'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
diff --git a/web/app/components/apps/app-list-catalog.tsx b/web/app/components/apps/app-list-catalog.tsx
index 1330fe8d3b1..48bad5404eb 100644
--- a/web/app/components/apps/app-list-catalog.tsx
+++ b/web/app/components/apps/app-list-catalog.tsx
@@ -17,7 +17,7 @@ import { useTranslation } from 'react-i18next'
import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-sentinel'
import { STEP_BY_STEP_TOUR_TARGETS } from '@/app/components/step-by-step-tour/target-registry'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { AppCard } from './app-card'
import { AppCardSkeleton } from './app-card-skeleton'
diff --git a/web/app/components/apps/hooks/__tests__/use-workflow-online-users.spec.ts b/web/app/components/apps/hooks/__tests__/use-workflow-online-users.spec.ts
index 3781ff57dc9..3d776b11a58 100644
--- a/web/app/components/apps/hooks/__tests__/use-workflow-online-users.spec.ts
+++ b/web/app/components/apps/hooks/__tests__/use-workflow-online-users.spec.ts
@@ -22,7 +22,7 @@ vi.mock('@tanstack/react-query', () => ({
useQuery: mockUseQuery,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
workflows: {
diff --git a/web/app/components/apps/hooks/use-workflow-online-users.ts b/web/app/components/apps/hooks/use-workflow-online-users.ts
index 998f89896fa..5420d91e6d9 100644
--- a/web/app/components/apps/hooks/use-workflow-online-users.ts
+++ b/web/app/components/apps/hooks/use-workflow-online-users.ts
@@ -1,6 +1,6 @@
import type { WorkflowOnlineUser, WorkflowOnlineUsersResponse } from '@/models/app'
import { useQuery } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type WorkflowOnlineUsersMap = Record
diff --git a/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx b/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx
index a0d4ffd71f0..a1a09a71167 100644
--- a/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx
+++ b/web/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button.tsx
@@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next'
import { useModalContext } from '@/context/modal-context'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { addAnnotation } from '@/service/annotation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type Props = Readonly<{
appId: string
diff --git a/web/app/components/base/features/new-feature-panel/annotation-reply/use-annotation-config.ts b/web/app/components/base/features/new-feature-panel/annotation-reply/use-annotation-config.ts
index 002670989c9..58e4b238979 100644
--- a/web/app/components/base/features/new-feature-panel/annotation-reply/use-annotation-config.ts
+++ b/web/app/components/base/features/new-feature-panel/annotation-reply/use-annotation-config.ts
@@ -9,7 +9,7 @@ import { AnnotationEnableStatus, JobStatus } from '@/app/components/app/annotati
import { ANNOTATION_DEFAULT } from '@/config'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { queryAnnotationJobStatus, updateAnnotationStatus } from '@/service/annotation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { sleep } from '@/utils'
type Params = {
diff --git a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
index 588b4f9836d..7eb99ac4095 100644
--- a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
+++ b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
@@ -22,7 +22,7 @@ import { useFeatures, useFeaturesStore } from '@/app/components/base/features/ho
import { Infotip } from '@/app/components/base/infotip'
import { languages } from '@/i18n-config/language'
import { usePathname } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { TtsAutoPlay } from '@/types/app'
type SelectOption = {
diff --git a/web/app/components/base/voice-input/__tests__/api.spec.ts b/web/app/components/base/voice-input/__tests__/api.spec.ts
index 3f155c6ae33..30ccf7db2eb 100644
--- a/web/app/components/base/voice-input/__tests__/api.spec.ts
+++ b/web/app/components/base/voice-input/__tests__/api.spec.ts
@@ -1,4 +1,4 @@
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { AppSourceType, audioToText } from '@/service/share'
import { transcribeAudio } from '../api'
@@ -10,7 +10,7 @@ vi.mock('@/service/share', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
apps: {
byAppId: {
diff --git a/web/app/components/base/voice-input/api.ts b/web/app/components/base/voice-input/api.ts
index 13e31eefdba..3d1cc8f6193 100644
--- a/web/app/components/base/voice-input/api.ts
+++ b/web/app/components/base/voice-input/api.ts
@@ -7,7 +7,7 @@ export async function transcribeAudio(
signal?: AbortSignal,
): Promise<{ text: string }> {
if (target.type === 'agent' || target.type === 'consoleApp') {
- const { consoleClient } = await import('@/service/client')
+ const { consoleClient } = await import('@/service/console')
if (target.type === 'agent') {
return consoleClient.agent.byAgentId.audioToText.post(
{
diff --git a/web/app/components/billing/__tests__/query-state.spec.tsx b/web/app/components/billing/__tests__/query-state.spec.tsx
index 1f26eba6520..68571d5989b 100644
--- a/web/app/components/billing/__tests__/query-state.spec.tsx
+++ b/web/app/components/billing/__tests__/query-state.spec.tsx
@@ -1,7 +1,7 @@
import { act, render, screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { ModalContextProvider } from '@/context/modal-context-provider'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
createConsoleQueryWrapper,
diff --git a/web/app/components/billing/annotation-full/usage.tsx b/web/app/components/billing/annotation-full/usage.tsx
index be6ee035737..3ec5817599d 100644
--- a/web/app/components/billing/annotation-full/usage.tsx
+++ b/web/app/components/billing/annotation-full/usage.tsx
@@ -3,7 +3,7 @@ import type { FC } from 'react'
import { useQuery } from '@tanstack/react-query'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { MessageFastPlus } from '../../base/icons/src/vender/line/communication'
import UsageInfo from '../usage-info'
import { parseLimit } from '../utils'
diff --git a/web/app/components/billing/apps-full-in-dialog/index.tsx b/web/app/components/billing/apps-full-in-dialog/index.tsx
index 8e8f55407f1..92fe2e606ef 100644
--- a/web/app/components/billing/apps-full-in-dialog/index.tsx
+++ b/web/app/components/billing/apps-full-in-dialog/index.tsx
@@ -9,7 +9,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { mailToSupport } from '@/app/components/header/utils/util'
import { userProfileQueryOptions } from '@/features/account-profile/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import UpgradeBtn from '../upgrade-btn'
import s from './style.module.css'
diff --git a/web/app/components/billing/billing-page/__tests__/index.spec.tsx b/web/app/components/billing/billing-page/__tests__/index.spec.tsx
index a89d05fd2d9..47196cbd184 100644
--- a/web/app/components/billing/billing-page/__tests__/index.spec.tsx
+++ b/web/app/components/billing/billing-page/__tests__/index.spec.tsx
@@ -1,6 +1,6 @@
import { screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, createConsoleQueryWrapper } from '@/test/console/query-data'
import { render } from '@/test/console/render'
import Billing from '../index'
diff --git a/web/app/components/billing/billing-page/index.tsx b/web/app/components/billing/billing-page/index.tsx
index 8da90b3831d..0fd7a891dd3 100644
--- a/web/app/components/billing/billing-page/index.tsx
+++ b/web/app/components/billing/billing-page/index.tsx
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import PlanComp from '../plan'
const Billing: FC = () => {
diff --git a/web/app/components/billing/hooks/use-education-discount.ts b/web/app/components/billing/hooks/use-education-discount.ts
index 2fec57d41fd..10dbd209ec8 100644
--- a/web/app/components/billing/hooks/use-education-discount.ts
+++ b/web/app/components/billing/hooks/use-education-discount.ts
@@ -4,7 +4,7 @@ import { useAtomValue } from 'jotai'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
export function useEducationDiscount() {
const { t } = useTranslation()
diff --git a/web/app/components/billing/partner-stack/use-ps-info.ts b/web/app/components/billing/partner-stack/use-ps-info.ts
index 7fdeb260f21..d961569de99 100644
--- a/web/app/components/billing/partner-stack/use-ps-info.ts
+++ b/web/app/components/billing/partner-stack/use-ps-info.ts
@@ -4,7 +4,7 @@ import Cookies from 'js-cookie'
import { useCallback } from 'react'
import { PARTNER_STACK_CONFIG } from '@/config'
import { useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const usePSInfo = () => {
const searchParams = useSearchParams()
diff --git a/web/app/components/billing/plan/index.tsx b/web/app/components/billing/plan/index.tsx
index 6a4b83aadc0..5f82f145834 100644
--- a/web/app/components/billing/plan/index.tsx
+++ b/web/app/components/billing/plan/index.tsx
@@ -12,7 +12,7 @@ import UsageInfo from '@/app/components/billing/usage-info'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getDaysUntilEndOfMonth } from '@/utils/time'
import Loading from '../../base/icons/src/public/thought/Loading'
import { NUM_INFINITE } from '../config'
diff --git a/web/app/components/billing/pricing/content.tsx b/web/app/components/billing/pricing/content.tsx
index 45f93415d0d..1db55c4eefc 100644
--- a/web/app/components/billing/pricing/content.tsx
+++ b/web/app/components/billing/pricing/content.tsx
@@ -8,7 +8,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import Divider from '@/app/components/base/divider'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import Cloud from './assets/cloud'
import NoiseBottom from './assets/noise-bottom'
import NoiseTop from './assets/noise-top'
diff --git a/web/app/components/billing/pricing/plans/cloud-plan-item/index.tsx b/web/app/components/billing/pricing/plans/cloud-plan-item/index.tsx
index 15800b60505..c225cf4b1e7 100644
--- a/web/app/components/billing/pricing/plans/cloud-plan-item/index.tsx
+++ b/web/app/components/billing/pricing/plans/cloud-plan-item/index.tsx
@@ -16,7 +16,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
import { useAsyncWindowOpen } from '@/hooks/use-async-window-open'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { ALL_PLANS } from '../../../config'
import { useEducationDiscount } from '../../../hooks/use-education-discount'
import Professional from '../../assets/professional'
diff --git a/web/app/components/billing/priority-label/index.tsx b/web/app/components/billing/priority-label/index.tsx
index f3a8a035f36..6586183b350 100644
--- a/web/app/components/billing/priority-label/index.tsx
+++ b/web/app/components/billing/priority-label/index.tsx
@@ -5,7 +5,7 @@ import { useQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { useTranslation } from 'react-i18next'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type PriorityLabelProps = {
className?: string
diff --git a/web/app/components/billing/usage-info/vector-space-info.tsx b/web/app/components/billing/usage-info/vector-space-info.tsx
index 7ad3096964f..b6c0df571a8 100644
--- a/web/app/components/billing/usage-info/vector-space-info.tsx
+++ b/web/app/components/billing/usage-info/vector-space-info.tsx
@@ -4,7 +4,7 @@ import { RiHardDrive3Line } from '@remixicon/react'
import { useSuspenseQueries } from '@tanstack/react-query'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import UsageInfo from '../usage-info'
import { getPlanVectorSpaceLimitMB } from '../utils'
diff --git a/web/app/components/custom/custom-page/__tests__/index.spec.tsx b/web/app/components/custom/custom-page/__tests__/index.spec.tsx
index 5982869cc74..28d77862fa5 100644
--- a/web/app/components/custom/custom-page/__tests__/index.spec.tsx
+++ b/web/app/components/custom/custom-page/__tests__/index.spec.tsx
@@ -6,7 +6,7 @@ import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { contactSalesUrl } from '@/app/components/billing/config'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import CustomPage from '../index'
diff --git a/web/app/components/custom/custom-page/index.tsx b/web/app/components/custom/custom-page/index.tsx
index c5e08cfa964..a663bb2c968 100644
--- a/web/app/components/custom/custom-page/index.tsx
+++ b/web/app/components/custom/custom-page/index.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
import { contactSalesUrl } from '@/app/components/billing/config'
import { useModalContext } from '@/context/modal-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import CustomWebAppBrand from '../custom-web-app-brand'
const CustomPage = () => {
diff --git a/web/app/components/custom/custom-web-app-brand/hooks/__tests__/use-web-app-brand.spec.tsx b/web/app/components/custom/custom-web-app-brand/hooks/__tests__/use-web-app-brand.spec.tsx
index d5e37b52ca3..a8eb5060e94 100644
--- a/web/app/components/custom/custom-web-app-brand/hooks/__tests__/use-web-app-brand.spec.tsx
+++ b/web/app/components/custom/custom-web-app-brand/hooks/__tests__/use-web-app-brand.spec.tsx
@@ -57,8 +57,8 @@ const mockUpdateCustomConfig = vi.hoisted(() => vi.fn())
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: mockToast,
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const consoleQuery = new Proxy(actual.consoleQuery, {
get(target, prop, receiver) {
if (prop === 'workspaces') {
diff --git a/web/app/components/custom/custom-web-app-brand/hooks/use-web-app-brand.ts b/web/app/components/custom/custom-web-app-brand/hooks/use-web-app-brand.ts
index 68121c9a969..7dd76072233 100644
--- a/web/app/components/custom/custom-web-app-brand/hooks/use-web-app-brand.ts
+++ b/web/app/components/custom/custom-web-app-brand/hooks/use-web-app-brand.ts
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import { getImageUploadErrorMessage, imageUpload } from '@/app/components/base/image-uploader/utils'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
const MAX_LOGO_FILE_SIZE = 5 * 1024 * 1024
diff --git a/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx b/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx
index c09d2909ceb..189712d68b9 100644
--- a/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/common/retrieval-method-config/__tests__/index.spec.tsx
@@ -2,7 +2,7 @@ import type { RetrievalConfig } from '@/types/app'
import { fireEvent, screen } from '@testing-library/react'
import * as React from 'react'
import { DEFAULT_WEIGHTED_SCORE, RerankingModeEnum, WeightedScoreEnum } from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { RETRIEVE_METHOD } from '@/types/app'
import RetrievalMethodConfig from '../index'
diff --git a/web/app/components/datasets/common/retrieval-method-config/index.tsx b/web/app/components/datasets/common/retrieval-method-config/index.tsx
index b5fed072075..1cbfc2b3594 100644
--- a/web/app/components/datasets/common/retrieval-method-config/index.tsx
+++ b/web/app/components/datasets/common/retrieval-method-config/index.tsx
@@ -13,7 +13,7 @@ import {
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { DEFAULT_WEIGHTED_SCORE, RerankingModeEnum, WeightedScoreEnum } from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { RETRIEVE_METHOD } from '@/types/app'
import { EffectColor } from '../../settings/chunk-structure/types'
import OptionCard from '../../settings/option-card'
diff --git a/web/app/components/datasets/create/embedding-process/index.tsx b/web/app/components/datasets/create/embedding-process/index.tsx
index b8d555ebe61..7a98c4010e7 100644
--- a/web/app/components/datasets/create/embedding-process/index.tsx
+++ b/web/app/components/datasets/create/embedding-process/index.tsx
@@ -13,7 +13,7 @@ import VectorSpaceAdmissionAlert from '@/app/components/datasets/common/vector-s
import { deploymentEditionAtom } from '@/features/system-features/state'
import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useProcessRule } from '@/service/knowledge/use-dataset'
import { useInvalidDocumentList } from '@/service/knowledge/use-document'
import IndexingProgressItem from './indexing-progress-item'
diff --git a/web/app/components/datasets/create/step-one/__tests__/index.spec.tsx b/web/app/components/datasets/create/step-one/__tests__/index.spec.tsx
index 1f4bd03b499..56aa9b22bad 100644
--- a/web/app/components/datasets/create/step-one/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/create/step-one/__tests__/index.spec.tsx
@@ -4,7 +4,7 @@ import type { NotionPage } from '@/models/common'
import type { CrawlOptions, CrawlResultItem, DataSet, FileItem } from '@/models/datasets'
import { fireEvent, screen } from '@testing-library/react'
import { DataSourceType } from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import StepOne from '../index'
diff --git a/web/app/components/datasets/create/step-one/index.tsx b/web/app/components/datasets/create/step-one/index.tsx
index 77114dd44c4..afff9959ce7 100644
--- a/web/app/components/datasets/create/step-one/index.tsx
+++ b/web/app/components/datasets/create/step-one/index.tsx
@@ -17,7 +17,7 @@ import VectorSpaceUnavailable from '@/app/components/billing/vector-space-unavai
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { DataSourceType } from '@/models/datasets'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import EmptyDatasetCreationModal from '../empty-dataset-creation-modal'
import FileUploader from '../file-uploader'
import Website from '../website'
diff --git a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx
index e7641cb3a4c..92c28d97a32 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx
@@ -1,5 +1,5 @@
import { waitFor } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import CreateFromPipeline from '../index'
diff --git a/web/app/components/datasets/documents/create-from-pipeline/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/index.tsx
index e671f0b4afb..3289ca27632 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/index.tsx
@@ -20,7 +20,7 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { DatasourceType } from '@/models/pipeline'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useFileUploadConfig } from '@/service/use-common'
import { usePublishedPipelineInfo } from '@/service/use-pipeline'
import { getDatasetACLCapabilities } from '@/utils/permission'
diff --git a/web/app/components/datasets/documents/create-from-pipeline/processing/embedding-process/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/processing/embedding-process/index.tsx
index 3b41241b2c4..b6773c9c43d 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/processing/embedding-process/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/processing/embedding-process/index.tsx
@@ -28,7 +28,7 @@ import { deploymentEditionAtom } from '@/features/system-features/state'
import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url'
import { DatasourceType } from '@/models/pipeline'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useIndexingStatusBatch, useProcessRule } from '@/service/knowledge/use-dataset'
import { useInvalidDocumentList } from '@/service/knowledge/use-document'
import RuleDetail from './rule-detail'
diff --git a/web/app/components/datasets/documents/detail/segment-add/index.tsx b/web/app/components/datasets/documents/detail/segment-add/index.tsx
index 5c273cdff1e..b69a13adc91 100644
--- a/web/app/components/datasets/documents/detail/segment-add/index.tsx
+++ b/web/app/components/datasets/documents/detail/segment-add/index.tsx
@@ -13,7 +13,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { PlanUpgradeModal } from '@/app/components/billing/plan-upgrade-modal'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { segmentImportStatus } from '@/types/dataset'
type SegmentAddProps = {
diff --git a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx
index dcced4455ca..cc09fb8be7d 100644
--- a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx
@@ -31,7 +31,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/external-api/external-api-panel/index.tsx b/web/app/components/datasets/external-api/external-api-panel/index.tsx
index f344dd08520..7783db3e458 100644
--- a/web/app/components/datasets/external-api/external-api-panel/index.tsx
+++ b/web/app/components/datasets/external-api/external-api-panel/index.tsx
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { useDocLink } from '@/context/i18n'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import ExternalKnowledgeAPICard from '../external-knowledge-api-card'
type ExternalAPIPanelProps = {
diff --git a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx
index 6826448df8d..5e989cf31ce 100644
--- a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx
@@ -38,7 +38,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx b/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx
index 10cf7ea15fb..56ed1f085f4 100644
--- a/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx
+++ b/web/app/components/datasets/external-api/external-knowledge-api-card/index.tsx
@@ -15,7 +15,7 @@ import * as React from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
checkUsageExternalAPI,
deleteExternalAPI,
diff --git a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
index 2fe6bfdb624..972214965cc 100644
--- a/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-knowledge-base/connector/__tests__/index.spec.tsx
@@ -92,7 +92,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx
index 251d5ce1ad8..9b709615317 100644
--- a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelect.tsx
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
import { useModalContext } from '@/context/modal-context'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type ApiItem = {
value: string
diff --git a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx
index bf404ac2b30..438550799b2 100644
--- a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx
@@ -9,7 +9,7 @@ import { useEffect, useId, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useModalContext } from '@/context/modal-context'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import ExternalApiSelect from './ExternalApiSelect'
type ExternalApiSelectionProps = {
diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx
index 74e27ff89bf..ef776f5d1a7 100644
--- a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelect.spec.tsx
@@ -32,7 +32,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx
index f59765cb4fb..96231733e65 100644
--- a/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/ExternalApiSelection.spec.tsx
@@ -35,7 +35,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx
index d8a210d0796..7e2cdfafaeb 100644
--- a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx
@@ -80,7 +80,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
datasets: {
externalKnowledgeApi: {
diff --git a/web/app/components/datasets/list/__tests__/index.spec.tsx b/web/app/components/datasets/list/__tests__/index.spec.tsx
index 79d2bc4f81f..1751a5aa107 100644
--- a/web/app/components/datasets/list/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/list/__tests__/index.spec.tsx
@@ -36,8 +36,8 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', async (importOriginal) => {
- const original = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const original = await importOriginal()
return {
...original,
consoleQuery: {
diff --git a/web/app/components/datasets/list/dataset-card/hooks/use-dataset-card-state.ts b/web/app/components/datasets/list/dataset-card/hooks/use-dataset-card-state.ts
index a8bb5fb22ca..a2431ef9931 100644
--- a/web/app/components/datasets/list/dataset-card/hooks/use-dataset-card-state.ts
+++ b/web/app/components/datasets/list/dataset-card/hooks/use-dataset-card-state.ts
@@ -4,7 +4,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useExportPipelineDSL } from '@/service/use-pipeline'
import { downloadBlob } from '@/utils/download'
diff --git a/web/app/components/explore/create-app-modal/index.tsx b/web/app/components/explore/create-app-modal/index.tsx
index 541cdfb6c37..d22ba097ec4 100644
--- a/web/app/components/explore/create-app-modal/index.tsx
+++ b/web/app/components/explore/create-app-modal/index.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import AppIconPicker from '../../base/app-icon-picker'
diff --git a/web/app/components/explore/installed-app/__tests__/index.spec.tsx b/web/app/components/explore/installed-app/__tests__/index.spec.tsx
index 19824e1553f..5c3de1785db 100644
--- a/web/app/components/explore/installed-app/__tests__/index.spec.tsx
+++ b/web/app/components/explore/installed-app/__tests__/index.spec.tsx
@@ -17,7 +17,7 @@ const mocks = vi.hoisted(() => ({
getInstalledAppParameters: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/explore/installed-app/index.tsx b/web/app/components/explore/installed-app/index.tsx
index 5e415f004c5..5ab42f7a681 100644
--- a/web/app/components/explore/installed-app/index.tsx
+++ b/web/app/components/explore/installed-app/index.tsx
@@ -11,7 +11,7 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AccessMode } from '@/models/access-control'
import dynamic from '@/next/dynamic'
import { useGetUserCanAccessApp } from '@/service/access-control/use-app-access-control'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import AppUnavailable from '../../base/app-unavailable'
import { toInstalledAppAccessMode, toInstalledAppMeta, toInstalledAppParameters } from './runtime'
diff --git a/web/app/components/goto-anything/actions/__tests__/agent.spec.tsx b/web/app/components/goto-anything/actions/__tests__/agent.spec.tsx
index 73a2ed6bfde..5a11cce8ae1 100644
--- a/web/app/components/goto-anything/actions/__tests__/agent.spec.tsx
+++ b/web/app/components/goto-anything/actions/__tests__/agent.spec.tsx
@@ -3,7 +3,7 @@ import { agentAction, agentSearchQueryOptions } from '../agent'
const serviceMocks = vi.hoisted(() => ({ queryOptions: vi.fn((options) => options) }))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: { agent: { get: { queryOptions: serviceMocks.queryOptions } } },
}))
diff --git a/web/app/components/goto-anything/actions/__tests__/app.spec.ts b/web/app/components/goto-anything/actions/__tests__/app.spec.ts
index 49faf5e66a5..8508cc89361 100644
--- a/web/app/components/goto-anything/actions/__tests__/app.spec.ts
+++ b/web/app/components/goto-anything/actions/__tests__/app.spec.ts
@@ -2,7 +2,7 @@ import { appAction, appSearchQueryOptions } from '../app'
const serviceMocks = vi.hoisted(() => ({ queryOptions: vi.fn((options) => options) }))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: { apps: { get: { queryOptions: serviceMocks.queryOptions } } },
}))
diff --git a/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts b/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts
index e5a115a6742..832d508265a 100644
--- a/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts
+++ b/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts
@@ -6,7 +6,7 @@ import { knowledgeAction, knowledgeSearchQueryOptions } from '../knowledge'
const serviceMocks = vi.hoisted(() => ({ queryOptions: vi.fn((options) => options) }))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: { datasets: { get: { queryOptions: serviceMocks.queryOptions } } },
}))
diff --git a/web/app/components/goto-anything/actions/__tests__/plugin.spec.ts b/web/app/components/goto-anything/actions/__tests__/plugin.spec.ts
index 06bf9e7526f..bfcc07e3beb 100644
--- a/web/app/components/goto-anything/actions/__tests__/plugin.spec.ts
+++ b/web/app/components/goto-anything/actions/__tests__/plugin.spec.ts
@@ -2,7 +2,7 @@ import { pluginAction, pluginSearchQueryOptions } from '../plugin'
const serviceMocks = vi.hoisted(() => ({ queryOptions: vi.fn((options) => options) }))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceQuery: { searchAdvanced: { queryOptions: serviceMocks.queryOptions } },
}))
diff --git a/web/app/components/goto-anything/actions/__tests__/skill.spec.tsx b/web/app/components/goto-anything/actions/__tests__/skill.spec.tsx
index b057fc5fb6b..a23dc37cab3 100644
--- a/web/app/components/goto-anything/actions/__tests__/skill.spec.tsx
+++ b/web/app/components/goto-anything/actions/__tests__/skill.spec.tsx
@@ -3,7 +3,7 @@ import { skillAction, skillSearchQueryOptions } from '../skill'
const serviceMocks = vi.hoisted(() => ({ queryOptions: vi.fn((options) => options) }))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: { current: { skills: { get: { queryOptions: serviceMocks.queryOptions } } } },
},
diff --git a/web/app/components/goto-anything/actions/agent.tsx b/web/app/components/goto-anything/actions/agent.tsx
index 9d69ebc8452..6ff69e73d37 100644
--- a/web/app/components/goto-anything/actions/agent.tsx
+++ b/web/app/components/goto-anything/actions/agent.tsx
@@ -1,7 +1,7 @@
import type { AgentAppPartial, AgentIconType } from '@dify/contracts/api/console/agent/types.gen'
import type { ActionItem, AgentSearchResult } from './types'
import { getI18n } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import AppIcon from '../../base/app-icon'
function getAgentResults(agents: AgentAppPartial[]): AgentSearchResult[] {
diff --git a/web/app/components/goto-anything/actions/app.tsx b/web/app/components/goto-anything/actions/app.tsx
index edacdf6d824..bafec065c77 100644
--- a/web/app/components/goto-anything/actions/app.tsx
+++ b/web/app/components/goto-anything/actions/app.tsx
@@ -1,7 +1,7 @@
import type { AppPartial } from '@dify/contracts/api/console/apps/types.gen'
import type { ActionItem, AppSearchResult, SearchResult } from './types'
import type { AppIconType, AppModeEnum as AppMode } from '@/types/app'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirectionPath } from '@/utils/app-redirection'
import { AppTypeIcon } from '../../app/type-selector'
diff --git a/web/app/components/goto-anything/actions/knowledge.tsx b/web/app/components/goto-anything/actions/knowledge.tsx
index fcff4872ca3..311a19b0a8b 100644
--- a/web/app/components/goto-anything/actions/knowledge.tsx
+++ b/web/app/components/goto-anything/actions/knowledge.tsx
@@ -1,7 +1,7 @@
import type { DatasetListItemResponse } from '@dify/contracts/api/console/datasets/types.gen'
import type { ActionItem, KnowledgeSearchResult } from './types'
import { cn } from '@langgenius/dify-ui/cn'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { Folder } from '../../base/icons/src/vender/solid/files'
const EXTERNAL_PROVIDER = 'external' as const
diff --git a/web/app/components/goto-anything/actions/plugin.tsx b/web/app/components/goto-anything/actions/plugin.tsx
index b25a138231c..14980fc1691 100644
--- a/web/app/components/goto-anything/actions/plugin.tsx
+++ b/web/app/components/goto-anything/actions/plugin.tsx
@@ -1,7 +1,7 @@
import type { Plugin } from '../../plugins/types'
import type { ActionItem, PluginSearchResult } from './types'
import { renderI18nObject } from '@/i18n-config'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import Icon from '../../plugins/card/base/card-icon'
import { getFormattedPlugin } from '../../plugins/marketplace/utils'
diff --git a/web/app/components/goto-anything/actions/skill.tsx b/web/app/components/goto-anything/actions/skill.tsx
index ace3b0d725c..db67431bc7f 100644
--- a/web/app/components/goto-anything/actions/skill.tsx
+++ b/web/app/components/goto-anything/actions/skill.tsx
@@ -1,7 +1,7 @@
import type { SkillResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { ActionItem, SkillSearchResult } from './types'
import { getI18n } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
function getSkillResults(skills: SkillResponse[]): SkillSearchResult[] {
return skills.map((skill) => ({
diff --git a/web/app/components/header/account-dropdown/compliance.tsx b/web/app/components/header/account-dropdown/compliance.tsx
index 63d54911416..842f18aabc8 100644
--- a/web/app/components/header/account-dropdown/compliance.tsx
+++ b/web/app/components/header/account-dropdown/compliance.tsx
@@ -19,8 +19,8 @@ import {
settingsQueryParser,
} from '@/app/components/header/account-setting/query-params'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
import { getDocDownloadUrl } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { downloadUrl } from '@/utils/download'
import Gdpr from '../../base/icons/src/public/common/Gdpr'
import Iso from '../../base/icons/src/public/common/Iso'
diff --git a/web/app/components/header/account-dropdown/main-nav-menu-content.tsx b/web/app/components/header/account-dropdown/main-nav-menu-content.tsx
index 2d4b8449a06..12491bb837b 100644
--- a/web/app/components/header/account-dropdown/main-nav-menu-content.tsx
+++ b/web/app/components/header/account-dropdown/main-nav-menu-content.tsx
@@ -28,7 +28,7 @@ import {
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ExternalLinkIndicator, MenuItemContent } from './menu-item-content'
type MainNavRadioItemContentProps = {
diff --git a/web/app/components/header/account-setting/__tests__/index.spec.tsx b/web/app/components/header/account-setting/__tests__/index.spec.tsx
index 2ae74260d2f..0c94188a555 100644
--- a/web/app/components/header/account-setting/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/__tests__/index.spec.tsx
@@ -86,8 +86,8 @@ vi.mock('@/service/use-common', async (importOriginal) => {
}
})
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleQuery: new Proxy(actual.consoleQuery, {
diff --git a/web/app/components/header/account-setting/access-rules-page/permission-set-modal/__tests__/index.spec.tsx b/web/app/components/header/account-setting/access-rules-page/permission-set-modal/__tests__/index.spec.tsx
index 7c4b00da20e..8ecc52563de 100644
--- a/web/app/components/header/account-setting/access-rules-page/permission-set-modal/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/access-rules-page/permission-set-modal/__tests__/index.spec.tsx
@@ -3,7 +3,7 @@ import type { ReactNode } from 'react'
import { QueryClientProvider } from '@tanstack/react-query'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createTestQueryClient } from '@/test/query-client'
import PermissionSetModal from '../index'
diff --git a/web/app/components/header/account-setting/access-rules-page/permission-set-modal/hooks.ts b/web/app/components/header/account-setting/access-rules-page/permission-set-modal/hooks.ts
index 37051dd35f6..70d4de11fab 100644
--- a/web/app/components/header/account-setting/access-rules-page/permission-set-modal/hooks.ts
+++ b/web/app/components/header/account-setting/access-rules-page/permission-set-modal/hooks.ts
@@ -3,7 +3,7 @@ import type { AccessPolicyResourceType } from '@/models/access-control'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const usePermissionsGroups = (resourceType: AccessPolicyResourceType) => {
const { t } = useTranslation()
diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx
index 7c95d94b908..7e9d6d163d9 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx
@@ -26,7 +26,7 @@ vi.mock('@/context/permission-state', async () => {
}))
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx
index 013c2a0ac21..b0a76663809 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx
@@ -9,7 +9,7 @@ const { mockDeleteApiBasedExtension } = vi.hoisted(() => ({
mockDeleteApiBasedExtension: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apiBasedExtension: {
byId: {
diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/modal.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/modal.spec.tsx
index 8d699dfe8ff..f5dd0d3057a 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/modal.spec.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/modal.spec.tsx
@@ -27,7 +27,7 @@ vi.mock('@/context/i18n', () => ({
useDocLink: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apiBasedExtension: {
post: {
diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx
index 9f5663708af..785a1f9ea75 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx
@@ -22,7 +22,7 @@ vi.mock('@/context/i18n', () => ({
`https://docs.dify.ai${path}`,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apiBasedExtension: {
get: {
diff --git a/web/app/components/header/account-setting/api-based-extension-page/index.tsx b/web/app/components/header/account-setting/api-based-extension-page/index.tsx
index 47660dda28d..9b44a240d94 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/index.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/index.tsx
@@ -9,7 +9,7 @@ import { SearchInput } from '@/app/components/base/search-input'
import { SkeletonContainer, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
import { STEP_BY_STEP_TOUR_TARGETS } from '@/app/components/step-by-step-tour/target-registry'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { Empty } from './empty'
import { Item } from './item'
diff --git a/web/app/components/header/account-setting/api-based-extension-page/item.tsx b/web/app/components/header/account-setting/api-based-extension-page/item.tsx
index 45aaf62129d..331f254bb63 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/item.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/item.tsx
@@ -11,7 +11,7 @@ import { Button } from '@langgenius/dify-ui/button'
import { useMutation } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type ItemProps = {
apiBasedExtension: ApiBasedExtensionResponse
diff --git a/web/app/components/header/account-setting/api-based-extension-page/modal.tsx b/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
index 2eb5ac7fd1b..2c09de22bf6 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/modal.tsx
@@ -12,7 +12,7 @@ import { toast } from '@langgenius/dify-ui/toast'
import { useMutation } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type ApiBasedExtensionModalProps = {
open: boolean
diff --git a/web/app/components/header/account-setting/api-based-extension-page/selector.tsx b/web/app/components/header/account-setting/api-based-extension-page/selector.tsx
index 8311b7f7215..0b42c0c6fea 100644
--- a/web/app/components/header/account-setting/api-based-extension-page/selector.tsx
+++ b/web/app/components/header/account-setting/api-based-extension-page/selector.tsx
@@ -14,7 +14,7 @@ import {
settingsQueryParamName,
settingsQueryParser,
} from '@/app/components/header/account-setting/query-params'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ApiBasedExtensionModal } from './modal'
type ApiBasedExtensionSelectorProps = {
diff --git a/web/app/components/header/account-setting/members-page/index.tsx b/web/app/components/header/account-setting/members-page/index.tsx
index d6215b10dff..e894c2c52f4 100644
--- a/web/app/components/header/account-setting/members-page/index.tsx
+++ b/web/app/components/header/account-setting/members-page/index.tsx
@@ -18,7 +18,7 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { getAccessControlTemplateLanguage, LanguagesSupported } from '@/i18n-config/language'
import { useUpdateRolesOfMember } from '@/service/access-control/use-member-roles'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useMembers } from '@/service/use-common'
import { hasPermission } from '@/utils/permission'
import EditWorkspaceModal from './edit-workspace-modal'
diff --git a/web/app/components/header/account-setting/members-page/invite-modal/__tests__/index.spec.tsx b/web/app/components/header/account-setting/members-page/invite-modal/__tests__/index.spec.tsx
index 1f66c34d75c..275946ac47b 100644
--- a/web/app/components/header/account-setting/members-page/invite-modal/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/members-page/invite-modal/__tests__/index.spec.tsx
@@ -16,8 +16,8 @@ const { fetchFeatures, inviteMember } = vi.hoisted(() => ({
}))
vi.mock('@/service/access-control/use-workspace-roles')
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleQuery: {
diff --git a/web/app/components/header/account-setting/members-page/invite-modal/index.tsx b/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
index 9d16137c944..df9137c48d7 100644
--- a/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
+++ b/web/app/components/header/account-setting/members-page/invite-modal/index.tsx
@@ -19,7 +19,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocale } from '@/context/i18n'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { commonQueryKeys } from '@/service/use-common'
import { mergeEmailRecipients } from './email-recipients'
import { EmailRecipientsField } from './email-recipients-field'
diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts
index f8e03853fbc..b5375efef30 100644
--- a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts
+++ b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts
@@ -9,8 +9,8 @@ import type {
} from '../declarations'
import { act, renderHook } from '@testing-library/react'
import { useLocale } from '@/context/i18n'
-import { consoleQuery } from '@/service/client'
import { fetchDefaultModal } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import {
ConfigurationMethodEnum,
CurrentSystemQuotaTypeEnum,
diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/index.non-cloud.spec.tsx b/web/app/components/header/account-setting/model-provider-page/__tests__/index.non-cloud.spec.tsx
index 52659532eb8..18d13b2bc38 100644
--- a/web/app/components/header/account-setting/model-provider-page/__tests__/index.non-cloud.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/__tests__/index.non-cloud.spec.tsx
@@ -116,8 +116,8 @@ vi.mock('@/app/components/plugins/reference-setting-modal', () => ({
default: () => ,
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const originalWorkspaces = actual.consoleQuery.workspaces
return {
...actual,
diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/__tests__/index.spec.tsx
index f87e5ed837e..25a5c944ddd 100644
--- a/web/app/components/header/account-setting/model-provider-page/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/__tests__/index.spec.tsx
@@ -329,8 +329,8 @@ vi.mock('nuqs', async (importOriginal) => {
return { ...actual, useQueryState: () => [null, mockSetSettingsDestination] }
})
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const originalWorkspaces = actual.consoleQuery.workspaces
return {
...actual,
diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/install-from-marketplace.spec.tsx b/web/app/components/header/account-setting/model-provider-page/__tests__/install-from-marketplace.spec.tsx
index c2e6a8e7fe7..aa800e85f42 100644
--- a/web/app/components/header/account-setting/model-provider-page/__tests__/install-from-marketplace.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/__tests__/install-from-marketplace.spec.tsx
@@ -5,7 +5,7 @@ import {
getStepByStepTourTargetSelector,
STEP_BY_STEP_TOUR_TARGETS,
} from '@/app/components/step-by-step-tour/target-registry'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { useMarketplaceAllPlugins } from '../hooks'
import InstallFromMarketplace from '../install-from-marketplace'
diff --git a/web/app/components/header/account-setting/model-provider-page/hooks.ts b/web/app/components/header/account-setting/model-provider-page/hooks.ts
index 737bcf1aa4d..85046ba3e61 100644
--- a/web/app/components/header/account-setting/model-provider-page/hooks.ts
+++ b/web/app/components/header/account-setting/model-provider-page/hooks.ts
@@ -20,8 +20,8 @@ import {
import { PluginCategoryEnum } from '@/app/components/plugins/types'
import { useLocale } from '@/context/i18n'
import { useModalContextSelector } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
import { fetchDefaultModal, fetchModelList } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { commonQueryKeys, modelProviderDetailsQueryOptions } from '@/service/use-common'
import { useExpandModelProviderList } from './atoms'
import { CustomConfigurationStatusEnum, ModelStatusEnum, ModelTypeEnum } from './declarations'
diff --git a/web/app/components/header/account-setting/model-provider-page/index.tsx b/web/app/components/header/account-setting/model-provider-page/index.tsx
index 097f2ab0d76..83f0df67996 100644
--- a/web/app/components/header/account-setting/model-provider-page/index.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/index.tsx
@@ -13,7 +13,7 @@ import { usePluginSettingsAccess } from '@/app/components/plugins/plugin-page/us
import { PluginCategoryEnum } from '@/app/components/plugins/types'
import { useProviderContext } from '@/context/provider-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import UpdateSettingDialog from '../update-setting-dialog'
import { ModelTypeEnum } from './declarations'
import { useDefaultModel } from './hooks'
diff --git a/web/app/components/header/account-setting/model-provider-page/install-from-marketplace.tsx b/web/app/components/header/account-setting/model-provider-page/install-from-marketplace.tsx
index 21d7b5e9fbb..9bf467f009d 100644
--- a/web/app/components/header/account-setting/model-provider-page/install-from-marketplace.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/install-from-marketplace.tsx
@@ -12,7 +12,7 @@ import { usePluginSettingsAccess } from '@/app/components/plugins/plugin-page/us
import ProviderCard from '@/app/components/plugins/provider-card'
import { PluginCategoryEnum } from '@/app/components/plugins/types'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useMarketplaceAllPlugins } from './hooks'
type InstallFromMarketplaceProps = {
diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/index.spec.tsx
index 2a3878ccfb6..9d30326a8a4 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/index.spec.tsx
@@ -4,7 +4,7 @@ import type { Model, ModelItem } from '../../declarations'
import { QueryClientProvider } from '@tanstack/react-query'
import { fireEvent, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient } from '@/test/console/query-data'
import { ConfigurationMethodEnum, ModelStatusEnum, ModelTypeEnum } from '../../declarations'
import { ModelSelector, SplitModelSelector } from '../index'
diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.tsx
index dafc380ca20..d5334b8e5a2 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-selector/model-selector-trigger.tsx
@@ -4,7 +4,7 @@ import { PopoverTrigger } from '@langgenius/dify-ui/popover'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
DERIVED_MODEL_STATUS_BADGE_I18N,
DERIVED_MODEL_STATUS_TOOLTIP_I18N,
diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx
index 486a2a03f33..87adca1df51 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx
@@ -22,7 +22,7 @@ import { PluginCategoryEnum } from '@/app/components/plugins/types'
import { useProviderContext } from '@/context/provider-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { renderI18nObject } from '@/i18n-config'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
import { useInstallPackageFromMarketPlace } from '@/service/use-plugins'
import { CustomConfigurationStatusEnum, ModelFeatureEnum, ModelTypeEnum } from '../declarations'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/credential-panel.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/credential-panel.spec.tsx
index 536959badb3..d3e9231dbd9 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/credential-panel.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/credential-panel.spec.tsx
@@ -39,8 +39,8 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
},
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const mockedModelProviders = {
byProvider: {
models: {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/index.spec.tsx
index f93798d4196..cc6f52072b5 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/index.spec.tsx
@@ -35,7 +35,7 @@ const mockQueryOptions = vi.fn(
}),
)
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/provider-card-actions.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/provider-card-actions.spec.tsx
index 7d89550f75c..7f84564a72d 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/provider-card-actions.spec.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/provider-card-actions.spec.tsx
@@ -6,7 +6,7 @@ import { zPostWorkspacesCurrentPluginListInstallationsIdsResponse } from '@dify/
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { PluginSource } from '@/app/components/plugins/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { commonQueryKeys } from '@/service/use-common'
import { renderWithConsoleQuery } from '@/test/console/query-data'
import ProviderCardActions from '../provider-card-actions'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-change-provider-priority.spec.ts b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-change-provider-priority.spec.ts
index 283b6e516fe..ce2247fd7ce 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-change-provider-priority.spec.ts
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-change-provider-priority.spec.ts
@@ -36,7 +36,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
},
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: {
current: {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-trial-credits.spec.ts b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-trial-credits.spec.ts
index 91a668fba5a..a8a7296ffce 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-trial-credits.spec.ts
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/use-trial-credits.spec.ts
@@ -9,7 +9,7 @@ vi.mock('@tanstack/react-query', () => ({
useQuery: (options: unknown) => mockUseQuery(options),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: {
current: {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx
index 2219f8d8be6..7177b1a1bb6 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx
@@ -14,7 +14,7 @@ import { useProviderContextSelector } from '@/context/provider-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useCredentialPermissions } from '@/hooks/use-credential-permissions'
import { renderI18nObject } from '@/i18n-config'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
import { hasPermission } from '@/utils/permission'
import { useModelProviderListExpanded, useSetModelProviderListExpanded } from '../atoms'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.stories.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.stories.tsx
index 0d9f7c771e8..55b7fdd60a6 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.stories.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/credits-exhausted-alert.stories.tsx
@@ -1,7 +1,7 @@
import type { ModelProviderCreditsResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import CreditsExhaustedAlert from './credits-exhausted-alert'
const baseCredits: ModelProviderCreditsResponse = {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx
index c96749fd0ab..0abb42477ab 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx
@@ -13,8 +13,8 @@ import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndE
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { useProviderContextSelector } from '@/context/provider-context'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
import { disableModel, enableModel } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { ModelStatusEnum } from '../declarations'
import { useUpdateModelList } from '../hooks'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.tsx
index f2b2d1e901a..8eb4fd8edfa 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/provider-card-actions.tsx
@@ -29,7 +29,7 @@ import { PluginSource } from '@/app/components/plugins/types'
import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker'
import { useLocale } from '@/context/i18n'
import useTheme from '@/hooks/use-theme'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { uninstallPlugin } from '@/service/plugins'
import { commonQueryKeys } from '@/service/use-common'
import { normalizeInstalledPluginDetail } from '@/service/use-plugins'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx
index 3370561085a..c2b83f8f2e9 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx
@@ -17,7 +17,7 @@ import useWorkspacePluginInstallPermission from '@/app/components/plugins/instal
import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import useTimestamp from '@/hooks/use-timestamp'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchManifestFromMarketPlace, fetchPluginInfoFromMarketPlace } from '@/service/plugins'
import { formatNumber } from '@/utils/format'
import { PreferredProviderTypeEnum } from '../declarations'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.ts b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.ts
index 46f25e02380..71339c9b5ce 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.ts
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-change-provider-priority.ts
@@ -3,7 +3,7 @@ import type { ModelProvider, PreferredProviderTypeEnum } from '../declarations'
import { toast } from '@langgenius/dify-ui/toast'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ConfigurationMethodEnum } from '../declarations'
import { useUpdateModelList, useUpdateModelProviders } from '../hooks'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.ts b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.ts
index 27da0df0a19..02f1b69173b 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.ts
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-credential-panel-state.ts
@@ -3,7 +3,7 @@ import type { ModelProvider } from '../declarations'
import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { useCredentialStatus } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { PreferredProviderTypeEnum } from '../declarations'
import { providerSupportsCredits } from '../supports-credits'
import { useTrialCredits } from './use-trial-credits'
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.ts b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.ts
index 421821c19d0..625b363e045 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.ts
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/use-trial-credits.ts
@@ -1,6 +1,6 @@
import type { ModelProviderCreditsResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import { useQuery } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const selectTrialCredits = (creditPool: ModelProviderCreditsResponse) => {
return {
diff --git a/web/app/components/header/account-setting/permissions-page/role-modal/__tests__/index.spec.tsx b/web/app/components/header/account-setting/permissions-page/role-modal/__tests__/index.spec.tsx
index b37ef35b32b..473a29cd4f4 100644
--- a/web/app/components/header/account-setting/permissions-page/role-modal/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/permissions-page/role-modal/__tests__/index.spec.tsx
@@ -4,7 +4,7 @@ import type { Role } from '@/models/access-control'
import { QueryClientProvider } from '@tanstack/react-query'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createTestQueryClient } from '@/test/query-client'
import RoleModal from '../index'
diff --git a/web/app/components/header/account-setting/permissions-page/role-modal/hooks.ts b/web/app/components/header/account-setting/permissions-page/role-modal/hooks.ts
index dc7c20b70e4..8b3ea6991b2 100644
--- a/web/app/components/header/account-setting/permissions-page/role-modal/hooks.ts
+++ b/web/app/components/header/account-setting/permissions-page/role-modal/hooks.ts
@@ -2,7 +2,7 @@ import type { SelectorKey } from 'i18next'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const useWorkspacePermissionGroups = () => {
const { t } = useTranslation()
diff --git a/web/app/components/header/account-setting/preference-page/index.tsx b/web/app/components/header/account-setting/preference-page/index.tsx
index f1690f0a773..689c6054357 100644
--- a/web/app/components/header/account-setting/preference-page/index.tsx
+++ b/web/app/components/header/account-setting/preference-page/index.tsx
@@ -18,7 +18,7 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { setLocaleOnClient } from '@/i18n-config'
import { languages } from '@/i18n-config/language'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { timezones } from '@/utils/timezone'
type SelectOption = {
diff --git a/web/app/components/header/account-setting/workflow-log-archives-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/workflow-log-archives-page/__tests__/index.spec.tsx
index 28f35568b5d..3eef4c39901 100644
--- a/web/app/components/header/account-setting/workflow-log-archives-page/__tests__/index.spec.tsx
+++ b/web/app/components/header/account-setting/workflow-log-archives-page/__tests__/index.spec.tsx
@@ -3,7 +3,7 @@ import type { GetWorkflowRunArchivesResponse } from '@dify/contracts/api/console
import { fireEvent, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import WorkflowLogArchivesPage from '../index'
diff --git a/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx b/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
index 55d3fef9adf..63b13812828 100644
--- a/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
+++ b/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
@@ -16,7 +16,7 @@ import { SkeletonRectangle } from '@/app/components/base/skeleton'
import { API_PREFIX } from '@/config'
import { useModalContext } from '@/context/modal-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const numberFormatter = new Intl.NumberFormat()
const byteFormatter = new Intl.NumberFormat(undefined, {
diff --git a/web/app/components/header/license-badge/__tests__/index.spec.tsx b/web/app/components/header/license-badge/__tests__/index.spec.tsx
index 02423811811..4c6d71b327e 100644
--- a/web/app/components/header/license-badge/__tests__/index.spec.tsx
+++ b/web/app/components/header/license-badge/__tests__/index.spec.tsx
@@ -2,7 +2,7 @@ import { zLicenseStatus } from '@dify/contracts/api/console/system-features/zod.
import { noop } from '@tanstack/react-query'
import { screen } from '@testing-library/react'
import dayjs from 'dayjs'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
renderWithConsoleQuery,
diff --git a/web/app/components/header/license-badge/index.tsx b/web/app/components/header/license-badge/index.tsx
index ac073d4cf2b..e0bad0bd089 100644
--- a/web/app/components/header/license-badge/index.tsx
+++ b/web/app/components/header/license-badge/index.tsx
@@ -4,7 +4,7 @@ import { zLicenseStatus } from '@dify/contracts/api/console/system-features/zod.
import { useQuery } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import PremiumBadge from '../../base/premium-badge'
function LicenseBadge() {
diff --git a/web/app/components/main-nav/__tests__/index.spec.tsx b/web/app/components/main-nav/__tests__/index.spec.tsx
index e210775b7d5..afba8badfe4 100644
--- a/web/app/components/main-nav/__tests__/index.spec.tsx
+++ b/web/app/components/main-nav/__tests__/index.spec.tsx
@@ -33,7 +33,7 @@ import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { usePathname, useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, renderWithConsoleQuery } from '@/test/console/query-data'
import { seedRegisteredConsoleStateFixture } from '@/test/console/state-fixture'
import { AppModeEnum } from '@/types/app'
@@ -253,8 +253,8 @@ vi.mock('react-i18next', async () => {
}
})
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const currentWorkspaceQueryKey = ['console', 'workspaces', 'current', 'summary', 'get'] as const
const currentPermissionsQueryKey = [
['console', 'workspaces', 'current', 'rbac', 'myPermissions', 'get'],
diff --git a/web/app/components/main-nav/components/__tests__/support-menu.spec.tsx b/web/app/components/main-nav/components/__tests__/support-menu.spec.tsx
index 736d479e137..00ed59f374f 100644
--- a/web/app/components/main-nav/components/__tests__/support-menu.spec.tsx
+++ b/web/app/components/main-nav/components/__tests__/support-menu.spec.tsx
@@ -9,7 +9,7 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'
import { zendeskRuntime } from '@/app/components/base/zendesk/runtime'
import { mailToSupport } from '@/app/components/header/utils/util'
import { useModalContext } from '@/context/modal-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryClient, createConsoleQueryWrapper } from '@/test/console/query-data'
import { render } from '@/test/console/render'
import SupportMenu from '../support-menu'
diff --git a/web/app/components/main-nav/components/__tests__/workspace-card.spec.tsx b/web/app/components/main-nav/components/__tests__/workspace-card.spec.tsx
index 3ab0be0ad20..aafe967efe5 100644
--- a/web/app/components/main-nav/components/__tests__/workspace-card.spec.tsx
+++ b/web/app/components/main-nav/components/__tests__/workspace-card.spec.tsx
@@ -10,7 +10,7 @@ import userEvent from '@testing-library/user-event'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createConsoleQueryClient,
renderWithConsoleQuery,
@@ -48,8 +48,8 @@ vi.mock('@/context/modal-context', () => ({
useModalContext: vi.fn(),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const consoleQuery = new Proxy(actual.consoleQuery, {
get(target, prop, receiver) {
if (prop === 'workspaces') {
diff --git a/web/app/components/main-nav/components/help-menu.tsx b/web/app/components/main-nav/components/help-menu.tsx
index f7d26d8a3a1..270ca7fdc62 100644
--- a/web/app/components/main-nav/components/help-menu.tsx
+++ b/web/app/components/main-nav/components/help-menu.tsx
@@ -50,7 +50,7 @@ import {
import { env } from '@/env'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import styles from './help-menu.module.css'
import AccountAboutDialog from './help-menu/account-about-dialog'
import SupportMenu from './support-menu'
diff --git a/web/app/components/main-nav/components/support-menu.tsx b/web/app/components/main-nav/components/support-menu.tsx
index 5cf8b5251e6..571fa4d33b2 100644
--- a/web/app/components/main-nav/components/support-menu.tsx
+++ b/web/app/components/main-nav/components/support-menu.tsx
@@ -12,7 +12,7 @@ import { SUPPORT_EMAIL_ADDRESS, ZENDESK_WIDGET_KEY } from '@/config'
import { useModalContext } from '@/context/modal-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export default function SupportMenu() {
const { t } = useTranslation()
diff --git a/web/app/components/main-nav/components/web-apps-section.tsx b/web/app/components/main-nav/components/web-apps-section.tsx
index a3c0097805f..00ef027ba49 100644
--- a/web/app/components/main-nav/components/web-apps-section.tsx
+++ b/web/app/components/main-nav/components/web-apps-section.tsx
@@ -39,7 +39,7 @@ import { InstalledAppPaginationSkeleton } from '@/app/components/explore/install
import { isInstalledAppPath } from '@/app/components/explore/installed-app/routes'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { usePathname } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
const emptyInstalledApps: InstalledAppResponse[] = []
diff --git a/web/app/components/main-nav/components/workspace-card.tsx b/web/app/components/main-nav/components/workspace-card.tsx
index 521a1a1439e..113d2c948e2 100644
--- a/web/app/components/main-nav/components/workspace-card.tsx
+++ b/web/app/components/main-nav/components/workspace-card.tsx
@@ -27,7 +27,7 @@ import { useModalContext } from '@/context/modal-context'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { basePath } from '@/utils/var'
import { formatCredits } from '../utils'
diff --git a/web/app/components/plugins/__tests__/use-plugins-with-latest-version.spec.ts b/web/app/components/plugins/__tests__/use-plugins-with-latest-version.spec.ts
index 0aca3286a70..a40b02307ea 100644
--- a/web/app/components/plugins/__tests__/use-plugins-with-latest-version.spec.ts
+++ b/web/app/components/plugins/__tests__/use-plugins-with-latest-version.spec.ts
@@ -1,7 +1,7 @@
import type { PluginDetail } from '../types'
import { useQuery } from '@tanstack/react-query'
import { renderHook } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { usePluginsWithLatestVersion } from '../hooks'
import { PluginSource } from '../types'
@@ -9,7 +9,7 @@ vi.mock('@tanstack/react-query', () => ({
useQuery: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: {
current: {
diff --git a/web/app/components/plugins/hooks.ts b/web/app/components/plugins/hooks.ts
index 6bd07c90804..102dc86172f 100644
--- a/web/app/components/plugins/hooks.ts
+++ b/web/app/components/plugins/hooks.ts
@@ -3,7 +3,7 @@ import type { PluginDetail } from './types'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { categoryKeys, tagKeys } from './constants'
import { PluginCategoryEnum, PluginSource } from './types'
diff --git a/web/app/components/plugins/marketplace/__tests__/hydration-server.spec.tsx b/web/app/components/plugins/marketplace/__tests__/hydration-server.spec.tsx
index 80c0a37463a..eb010d5e4cb 100644
--- a/web/app/components/plugins/marketplace/__tests__/hydration-server.spec.tsx
+++ b/web/app/components/plugins/marketplace/__tests__/hydration-server.spec.tsx
@@ -19,7 +19,7 @@ const mockCollections = vi.fn()
const mockCollectionPlugins = vi.fn()
const mockSearchAdvanced = vi.fn()
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
collections: (...args: unknown[]) => mockCollections(...args),
collectionPlugins: (...args: unknown[]) => mockCollectionPlugins(...args),
diff --git a/web/app/components/plugins/marketplace/__tests__/query.spec.tsx b/web/app/components/plugins/marketplace/__tests__/query.spec.tsx
index 9cf84fed0dc..bbca851c5b5 100644
--- a/web/app/components/plugins/marketplace/__tests__/query.spec.tsx
+++ b/web/app/components/plugins/marketplace/__tests__/query.spec.tsx
@@ -18,7 +18,7 @@ const mockCollections = vi.fn()
const mockCollectionPlugins = vi.fn()
const mockSearchAdvanced = vi.fn()
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
collections: (...args: unknown[]) => mockCollections(...args),
collectionPlugins: (...args: unknown[]) => mockCollectionPlugins(...args),
diff --git a/web/app/components/plugins/marketplace/__tests__/state.spec.tsx b/web/app/components/plugins/marketplace/__tests__/state.spec.tsx
index 876224f4da0..5fa44db78d1 100644
--- a/web/app/components/plugins/marketplace/__tests__/state.spec.tsx
+++ b/web/app/components/plugins/marketplace/__tests__/state.spec.tsx
@@ -21,7 +21,7 @@ const mockCollections = vi.fn()
const mockCollectionPlugins = vi.fn()
const mockSearchAdvanced = vi.fn()
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
collections: (...args: unknown[]) => mockCollections(...args),
collectionPlugins: (...args: unknown[]) => mockCollectionPlugins(...args),
diff --git a/web/app/components/plugins/marketplace/__tests__/utils.spec.ts b/web/app/components/plugins/marketplace/__tests__/utils.spec.ts
index a51a208fc96..0fcb52f7b7c 100644
--- a/web/app/components/plugins/marketplace/__tests__/utils.spec.ts
+++ b/web/app/components/plugins/marketplace/__tests__/utils.spec.ts
@@ -21,7 +21,7 @@ const mockCollectionPlugins = vi.fn()
const mockCollections = vi.fn()
const mockSearchAdvanced = vi.fn()
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
collections: (...args: unknown[]) => mockCollections(...args),
collectionPlugins: (...args: unknown[]) => mockCollectionPlugins(...args),
diff --git a/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts b/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts
index 8aac42bfb92..725a59a2557 100644
--- a/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts
+++ b/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts
@@ -11,7 +11,7 @@ const mocks = vi.hoisted(() => ({
vi.mock('server-only', () => ({}))
vi.mock('@/config', () => ({ MARKETPLACE_API_PREFIX: 'https://marketplace.example/api/v1' }))
-vi.mock('@/service/client', () => ({ marketplaceClient: mocks }))
+vi.mock('@/service/marketplace', () => ({ marketplaceClient: mocks }))
const plugin = {
type: 'plugin',
diff --git a/web/app/components/plugins/marketplace/creator-profile/data.server.ts b/web/app/components/plugins/marketplace/creator-profile/data.server.ts
index 38910290da6..24ce1c93ae4 100644
--- a/web/app/components/plugins/marketplace/creator-profile/data.server.ts
+++ b/web/app/components/plugins/marketplace/creator-profile/data.server.ts
@@ -2,7 +2,7 @@ import type { MarketplaceCreator, MarketplaceOrganization } from '@dify/contract
import type { CreatorSortField, CreatorSortOrder, LoadedCreatorProfile } from './model'
import { cache } from 'react'
import { MARKETPLACE_API_PREFIX } from '@/config'
-import { marketplaceClient } from '@/service/client'
+import { marketplaceClient } from '@/service/marketplace'
import { getPluginIconInMarketplace } from '../utils'
import {
adaptCreatorProfile,
diff --git a/web/app/components/plugins/marketplace/creator-profile/publisher.ts b/web/app/components/plugins/marketplace/creator-profile/publisher.ts
index 624a30c2234..2fab1de7266 100644
--- a/web/app/components/plugins/marketplace/creator-profile/publisher.ts
+++ b/web/app/components/plugins/marketplace/creator-profile/publisher.ts
@@ -2,7 +2,7 @@ import type { MarketplacePlugin, MarketplaceTemplate } from '@dify/contracts/mar
import type { CreatorCreation, CreatorSortField, CreatorSortOrder } from './model'
import type { Plugin } from '@/app/components/plugins/types'
import { MARKETPLACE_API_PREFIX } from '@/config'
-import { marketplaceClient } from '@/service/client'
+import { marketplaceClient } from '@/service/marketplace'
import { getFormattedPlugin, getPluginIconInMarketplace } from '../utils'
import { adaptCreations, toPublisherSortQuery } from './model'
diff --git a/web/app/components/plugins/marketplace/home/__tests__/embedded-marketplace-search.spec.tsx b/web/app/components/plugins/marketplace/home/__tests__/embedded-marketplace-search.spec.tsx
index ba7d2be04dc..018f6e30a41 100644
--- a/web/app/components/plugins/marketplace/home/__tests__/embedded-marketplace-search.spec.tsx
+++ b/web/app/components/plugins/marketplace/home/__tests__/embedded-marketplace-search.spec.tsx
@@ -42,7 +42,7 @@ vi.mock('#i18n', async () => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceQuery: {
searchAdvanced: {
queryOptions: ({ input }: { input: unknown }) => ({
diff --git a/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.browser.spec.tsx b/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.browser.spec.tsx
index d0b047063b9..eb9a78b6ec6 100644
--- a/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.browser.spec.tsx
+++ b/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.browser.spec.tsx
@@ -42,8 +42,8 @@ vi.mock('react-i18next', async (importOriginal) => {
}
})
-vi.mock('@/service/client', async (importOriginal) => {
- const original = await importOriginal()
+vi.mock('@/service/marketplace', async (importOriginal) => {
+ const original = await importOriginal()
return {
...original,
diff --git a/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.spec.tsx b/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.spec.tsx
index 6c2a020a9a5..b9ea0eb1909 100644
--- a/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.spec.tsx
+++ b/web/app/components/plugins/marketplace/home/__tests__/marketplace-search-autocomplete.spec.tsx
@@ -43,7 +43,7 @@ vi.mock('react-i18next', async () => {
})
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceQuery: {
searchAdvanced: {
queryOptions: ({ input }: { input: unknown }) => ({
diff --git a/web/app/components/plugins/marketplace/home/banners.spec.ts b/web/app/components/plugins/marketplace/home/banners.spec.ts
index 6989ec912e5..9ba6321dc3d 100644
--- a/web/app/components/plugins/marketplace/home/banners.spec.ts
+++ b/web/app/components/plugins/marketplace/home/banners.spec.ts
@@ -1,8 +1,8 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { marketplaceClient } from '@/service/client'
+import { marketplaceClient } from '@/service/marketplace'
import { fetchPluginBanners } from './banners'
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
banners: {
list: vi.fn(),
diff --git a/web/app/components/plugins/marketplace/home/banners.ts b/web/app/components/plugins/marketplace/home/banners.ts
index 1b1f24cc985..c604e7b0d41 100644
--- a/web/app/components/plugins/marketplace/home/banners.ts
+++ b/web/app/components/plugins/marketplace/home/banners.ts
@@ -1,6 +1,6 @@
import type { PluginBanner } from '@dify/contracts/marketplace'
import { z } from 'zod'
-import { marketplaceClient } from '@/service/client'
+import { marketplaceClient } from '@/service/marketplace'
// The banner types live in @dify/contracts/marketplace so the standalone
// marketplace and the embedded console share one definition; this module owns
diff --git a/web/app/components/plugins/marketplace/home/marketplace-search-autocomplete.tsx b/web/app/components/plugins/marketplace/home/marketplace-search-autocomplete.tsx
index 96aadc24f8d..3fd90d4366e 100644
--- a/web/app/components/plugins/marketplace/home/marketplace-search-autocomplete.tsx
+++ b/web/app/components/plugins/marketplace/home/marketplace-search-autocomplete.tsx
@@ -26,7 +26,7 @@ import { useEffect, useRef, useState } from 'react'
import { useTranslation } from '#i18n'
import { MARKETPLACE_API_PREFIX } from '@/config'
import { renderI18nObject } from '@/i18n-config/index'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import { markMarketplaceSiteSearch } from '@/utils/marketplace-site-track'
import {
getPluginDetailLinkInMarketplace,
diff --git a/web/app/components/plugins/marketplace/prefetch-marketplace-dehydrated-state.ts b/web/app/components/plugins/marketplace/prefetch-marketplace-dehydrated-state.ts
index 8ccfad85fe3..08d3774ba46 100644
--- a/web/app/components/plugins/marketplace/prefetch-marketplace-dehydrated-state.ts
+++ b/web/app/components/plugins/marketplace/prefetch-marketplace-dehydrated-state.ts
@@ -3,7 +3,7 @@ import type { MarketplaceSearchParams } from './search-params'
import { dehydrate, noop } from '@tanstack/react-query'
import { createLoader } from 'nuqs/server'
import { getQueryClient } from '@/app/get-query-client'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import { PLUGIN_CATEGORY_WITH_COLLECTIONS } from './constants'
import { getMarketplacePluginsInfiniteQueryOptions } from './query-options'
import {
diff --git a/web/app/components/plugins/marketplace/query-options.ts b/web/app/components/plugins/marketplace/query-options.ts
index a1351fea7e9..a8761440953 100644
--- a/web/app/components/plugins/marketplace/query-options.ts
+++ b/web/app/components/plugins/marketplace/query-options.ts
@@ -1,6 +1,6 @@
import type { PluginsSearchParams } from '@dify/contracts/marketplace'
import { infiniteQueryOptions, keepPreviousData } from '@tanstack/react-query'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import { getMarketplacePlugins } from './utils'
export const getMarketplacePluginsInfiniteQueryOptions = (
diff --git a/web/app/components/plugins/marketplace/query.ts b/web/app/components/plugins/marketplace/query.ts
index 17195d20efc..af10ed6de10 100644
--- a/web/app/components/plugins/marketplace/query.ts
+++ b/web/app/components/plugins/marketplace/query.ts
@@ -1,6 +1,6 @@
import type { MarketPlaceInputs, PluginsSearchParams } from '@dify/contracts/marketplace'
import { useInfiniteQuery, useQuery } from '@tanstack/react-query'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import { getMarketplacePluginsInfiniteQueryOptions } from './query-options'
import { getMarketplaceCollectionsAndPlugins } from './utils'
diff --git a/web/app/components/plugins/marketplace/utils.ts b/web/app/components/plugins/marketplace/utils.ts
index 5f1462e06e2..a55bbc59baf 100644
--- a/web/app/components/plugins/marketplace/utils.ts
+++ b/web/app/components/plugins/marketplace/utils.ts
@@ -8,7 +8,7 @@ import type { ActivePluginType } from './constants'
import type { Plugin } from '@/app/components/plugins/types'
import { PluginCategoryEnum } from '@/app/components/plugins/types'
import { MARKETPLACE_API_PREFIX } from '@/config'
-import { marketplaceClient } from '@/service/client'
+import { marketplaceClient } from '@/service/marketplace'
import { getMarketplaceUrl } from '@/utils/var'
import { PLUGIN_TYPE_SEARCH_MAP } from './constants'
diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx
index 1427c7c15f2..33b4a425a17 100644
--- a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx
@@ -42,7 +42,7 @@ const apps = [
const mockAppDetailQuery = vi.hoisted(() => vi.fn())
const mockUseAppWorkflow = vi.hoisted(() => vi.fn())
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
get: {
diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts b/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts
index 38535e5635f..de3fa4869a6 100644
--- a/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts
+++ b/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts
@@ -9,7 +9,7 @@ import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
import { BlockEnum, InputVarType, SupportUploadFileTypes } from '@/app/components/workflow/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useFileUploadConfig } from '@/service/use-common'
import { useAppWorkflow } from '@/service/use-workflow'
import { AppModeEnum, Resolution } from '@/types/app'
diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx
index d0cf2bc5f7a..f9271c971e2 100644
--- a/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx
@@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'
import AppInputsPanel from '@/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel'
import { AppPicker } from '@/app/components/plugins/plugin-detail-panel/app-selector/app-picker'
import { AppTrigger } from '@/app/components/plugins/plugin-detail-panel/app-selector/app-trigger'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const PAGE_SIZE = 20
diff --git a/web/app/components/plugins/plugin-page/__tests__/category-marketplace-panel.spec.tsx b/web/app/components/plugins/plugin-page/__tests__/category-marketplace-panel.spec.tsx
index 22bd2bcd60d..4819938e550 100644
--- a/web/app/components/plugins/plugin-page/__tests__/category-marketplace-panel.spec.tsx
+++ b/web/app/components/plugins/plugin-page/__tests__/category-marketplace-panel.spec.tsx
@@ -28,7 +28,7 @@ vi.mock('next-themes', () => ({
useTheme: () => ({ theme: 'light' }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: {
current: {
diff --git a/web/app/components/plugins/plugin-page/category-marketplace-panel.tsx b/web/app/components/plugins/plugin-page/category-marketplace-panel.tsx
index d848c5a8168..e28ba2cfc82 100644
--- a/web/app/components/plugins/plugin-page/category-marketplace-panel.tsx
+++ b/web/app/components/plugins/plugin-page/category-marketplace-panel.tsx
@@ -17,7 +17,7 @@ import { getMarketplaceCategoryUrl } from '@/app/components/plugins/marketplace/
import { usePluginSettingsAccess } from '@/app/components/plugins/plugin-page/use-reference-setting'
import ProviderCard from '@/app/components/plugins/provider-card'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getCategoryMarketplaceId } from './category-marketplace'
const MARKETPLACE_PAGE_SIZE = 30
diff --git a/web/app/components/snippet-list/__tests__/index.spec.tsx b/web/app/components/snippet-list/__tests__/index.spec.tsx
index b7448d00e55..23bf6333ca1 100644
--- a/web/app/components/snippet-list/__tests__/index.spec.tsx
+++ b/web/app/components/snippet-list/__tests__/index.spec.tsx
@@ -52,7 +52,7 @@ vi.mock('../hooks/use-snippets-query-state', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
systemFeatures: vi.fn(),
},
diff --git a/web/app/components/snippet-list/__tests__/reflow.browser.spec.tsx b/web/app/components/snippet-list/__tests__/reflow.browser.spec.tsx
index 629c80c43ae..ce4d1497752 100644
--- a/web/app/components/snippet-list/__tests__/reflow.browser.spec.tsx
+++ b/web/app/components/snippet-list/__tests__/reflow.browser.spec.tsx
@@ -70,7 +70,7 @@ vi.mock('@/features/account-profile/client', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
snippets: {
bySnippetId: {
diff --git a/web/app/components/snippet-list/components/__tests__/snippet-create-button.spec.tsx b/web/app/components/snippet-list/components/__tests__/snippet-create-button.spec.tsx
index f61422e78a0..e9feb419425 100644
--- a/web/app/components/snippet-list/components/__tests__/snippet-create-button.spec.tsx
+++ b/web/app/components/snippet-list/components/__tests__/snippet-create-button.spec.tsx
@@ -57,7 +57,7 @@ vi.mock('@/service/use-snippets', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
snippets: {
bySnippetId: {
diff --git a/web/app/components/snippets/components/hooks/use-snippet-publish.ts b/web/app/components/snippets/components/hooks/use-snippet-publish.ts
index c4d208d8cec..caa91089acd 100644
--- a/web/app/components/snippets/components/hooks/use-snippet-publish.ts
+++ b/web/app/components/snippets/components/hooks/use-snippet-publish.ts
@@ -5,7 +5,7 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useChecklistBeforePublish } from '@/app/components/workflow/hooks/use-checklist'
import { useWorkflowStore } from '@/app/components/workflow/store'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { usePublishSnippetWorkflowMutation } from '@/service/use-snippet-workflows'
import { useResetWorkflowVersionHistory } from '@/service/use-workflow'
diff --git a/web/app/components/snippets/hooks/__tests__/use-create-snippet.spec.tsx b/web/app/components/snippets/hooks/__tests__/use-create-snippet.spec.tsx
index 4492464aaeb..4afcc49a849 100644
--- a/web/app/components/snippets/hooks/__tests__/use-create-snippet.spec.tsx
+++ b/web/app/components/snippets/hooks/__tests__/use-create-snippet.spec.tsx
@@ -30,7 +30,7 @@ vi.mock('@/service/use-snippets', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
snippets: {
bySnippetId: {
diff --git a/web/app/components/snippets/hooks/__tests__/use-nodes-sync-draft.spec.ts b/web/app/components/snippets/hooks/__tests__/use-nodes-sync-draft.spec.ts
index 3b1d4658c32..5a328dff6fe 100644
--- a/web/app/components/snippets/hooks/__tests__/use-nodes-sync-draft.spec.ts
+++ b/web/app/components/snippets/hooks/__tests__/use-nodes-sync-draft.spec.ts
@@ -58,7 +58,7 @@ vi.mock('@/app/components/workflow/store', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
snippets: {
bySnippetId: {
diff --git a/web/app/components/snippets/hooks/use-create-snippet.ts b/web/app/components/snippets/hooks/use-create-snippet.ts
index 1e85eafbbb8..4d60e782db5 100644
--- a/web/app/components/snippets/hooks/use-create-snippet.ts
+++ b/web/app/components/snippets/hooks/use-create-snippet.ts
@@ -5,7 +5,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { useRouter } from '@/next/navigation'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { useCreateSnippetMutation } from '@/service/use-snippets'
import { canCreateAndModifySnippets } from '../utils/permission'
diff --git a/web/app/components/snippets/hooks/use-nodes-sync-draft.ts b/web/app/components/snippets/hooks/use-nodes-sync-draft.ts
index 80c7767392f..f3b69a03755 100644
--- a/web/app/components/snippets/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/snippets/hooks/use-nodes-sync-draft.ts
@@ -11,7 +11,7 @@ import { useStoreApi } from 'reactflow'
import { useNodesReadOnlyByCanEdit } from '@/app/components/workflow/hooks/use-workflow'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { API_PREFIX } from '@/config'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
// oxlint-disable-next-line no-restricted-imports
import { postWithKeepalive } from '@/service/fetch'
import { useSnippetDraftStore } from '../draft-store'
diff --git a/web/app/components/step-by-step-tour/__tests__/mount.spec.tsx b/web/app/components/step-by-step-tour/__tests__/mount.spec.tsx
index 9719aae9b0f..34bf115af72 100644
--- a/web/app/components/step-by-step-tour/__tests__/mount.spec.tsx
+++ b/web/app/components/step-by-step-tour/__tests__/mount.spec.tsx
@@ -226,7 +226,7 @@ vi.mock('@/next/navigation', () => ({
useRouter: () => ({ push: mockRouterPush }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/step-by-step-tour/__tests__/state.spec.ts b/web/app/components/step-by-step-tour/__tests__/state.spec.ts
index c0378899913..33aab751c60 100644
--- a/web/app/components/step-by-step-tour/__tests__/state.spec.ts
+++ b/web/app/components/step-by-step-tour/__tests__/state.spec.ts
@@ -84,7 +84,7 @@ vi.mock('@/features/system-features/state', async () => {
return { deploymentEditionAtom: atom('CLOUD') }
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
onboarding: {
stepByStepTour: {
diff --git a/web/app/components/step-by-step-tour/state.ts b/web/app/components/step-by-step-tour/state.ts
index c960d09b067..594b4588c15 100644
--- a/web/app/components/step-by-step-tour/state.ts
+++ b/web/app/components/step-by-step-tour/state.ts
@@ -16,7 +16,7 @@ import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack
import { selectAtom } from 'jotai/utils'
import { currentWorkspaceIdAtom } from '@/context/workspace-state'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const stepByStepTourStateQueryKey = () =>
consoleQuery.onboarding.stepByStepTour.state.get.queryKey()
diff --git a/web/app/components/tools/marketplace/__tests__/hooks.spec.ts b/web/app/components/tools/marketplace/__tests__/hooks.spec.ts
index f1d734768ee..b191ca0ac44 100644
--- a/web/app/components/tools/marketplace/__tests__/hooks.spec.ts
+++ b/web/app/components/tools/marketplace/__tests__/hooks.spec.ts
@@ -26,7 +26,7 @@ vi.mock('@/app/components/plugins/marketplace/hooks', () => ({
useMarketplacePlugins: (...args: unknown[]) => mockUseMarketplacePlugins(...args),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
workspaces: {
current: {
diff --git a/web/app/components/tools/marketplace/hooks.ts b/web/app/components/tools/marketplace/hooks.ts
index 2985e97dbc4..f79ea04057f 100644
--- a/web/app/components/tools/marketplace/hooks.ts
+++ b/web/app/components/tools/marketplace/hooks.ts
@@ -7,7 +7,7 @@ import {
} from '@/app/components/plugins/marketplace/hooks'
import { getMarketplaceListCondition } from '@/app/components/plugins/marketplace/utils'
import { PluginCategoryEnum } from '@/app/components/plugins/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const useMarketplace = (
searchPluginText: string,
diff --git a/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx b/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
index 454ecab1c47..461a220099a 100644
--- a/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
+++ b/web/app/components/workflow-app/components/workflow-header/__tests__/features-trigger.spec.tsx
@@ -7,7 +7,7 @@ import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useStore as useAppStore } from '@/app/components/app/store'
import { BlockEnum, InputVarType } from '@/app/components/workflow/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createConsoleQueryWrapper, seedFeatures } from '@/test/console/query-data'
import FeaturesTrigger from '../features-trigger'
diff --git a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
index e7d89862aea..5dab50d4e32 100644
--- a/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
+++ b/web/app/components/workflow-app/components/workflow-header/features-trigger.tsx
@@ -31,7 +31,7 @@ import { BlockEnum, InputVarType, isTriggerNode } from '@/app/components/workflo
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import useTheme from '@/hooks/use-theme'
import { fetchAppDetail } from '@/service/apps'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useInvalidateAppTriggers } from '@/service/use-tools'
import {
useInvalidateAppWorkflow,
diff --git a/web/app/components/workflow/block-selector/__tests__/agent-selector.spec.tsx b/web/app/components/workflow/block-selector/__tests__/agent-selector.spec.tsx
index 4a0ed57107c..e24112c1d9a 100644
--- a/web/app/components/workflow/block-selector/__tests__/agent-selector.spec.tsx
+++ b/web/app/components/workflow/block-selector/__tests__/agent-selector.spec.tsx
@@ -16,7 +16,7 @@ vi.mock('@/app/components/workflow/hooks-store', () => ({
useHooksStore: () => undefined,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
inviteOptions: {
diff --git a/web/app/components/workflow/block-selector/agent-selector.tsx b/web/app/components/workflow/block-selector/agent-selector.tsx
index 79ce1898f75..b140e910517 100644
--- a/web/app/components/workflow/block-selector/agent-selector.tsx
+++ b/web/app/components/workflow/block-selector/agent-selector.tsx
@@ -24,7 +24,7 @@ import Badge from '@/app/components/base/badge'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { useCanManageAgents } from '@/features/agent-v2/permissions'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import BlockIcon from '../block-icon'
const AGENT_SELECTOR_PAGE_SIZE = 8
diff --git a/web/app/components/workflow/block-selector/marketplace-plugin/__tests__/action.spec.tsx b/web/app/components/workflow/block-selector/marketplace-plugin/__tests__/action.spec.tsx
index cf0e7f97fac..c0efc32e307 100644
--- a/web/app/components/workflow/block-selector/marketplace-plugin/__tests__/action.spec.tsx
+++ b/web/app/components/workflow/block-selector/marketplace-plugin/__tests__/action.spec.tsx
@@ -14,7 +14,7 @@ vi.mock('next-themes', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceQuery: {
downloadPlugin: {
mutationOptions: (options = {}) => ({
diff --git a/web/app/components/workflow/block-selector/marketplace-plugin/action.tsx b/web/app/components/workflow/block-selector/marketplace-plugin/action.tsx
index 20d6f9aa50f..850780d2cb9 100644
--- a/web/app/components/workflow/block-selector/marketplace-plugin/action.tsx
+++ b/web/app/components/workflow/block-selector/marketplace-plugin/action.tsx
@@ -11,7 +11,7 @@ import { useMutation } from '@tanstack/react-query'
import { useTheme } from 'next-themes'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
-import { marketplaceQuery } from '@/service/client'
+import { marketplaceQuery } from '@/service/marketplace'
import { downloadBlob } from '@/utils/download'
import { getMarketplaceUrl } from '@/utils/var'
diff --git a/web/app/components/workflow/block-selector/snippets/__tests__/snippet-tags-filter.spec.tsx b/web/app/components/workflow/block-selector/snippets/__tests__/snippet-tags-filter.spec.tsx
index f8ba189691f..4bef9e4a83e 100644
--- a/web/app/components/workflow/block-selector/snippets/__tests__/snippet-tags-filter.spec.tsx
+++ b/web/app/components/workflow/block-selector/snippets/__tests__/snippet-tags-filter.spec.tsx
@@ -7,7 +7,7 @@ vi.mock('@tanstack/react-query', () => ({
useQuery: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/app/components/workflow/block-selector/snippets/__tests__/use-insert-snippet.spec.tsx b/web/app/components/workflow/block-selector/snippets/__tests__/use-insert-snippet.spec.tsx
index d6f9026399d..d1d72b69e8e 100644
--- a/web/app/components/workflow/block-selector/snippets/__tests__/use-insert-snippet.spec.tsx
+++ b/web/app/components/workflow/block-selector/snippets/__tests__/use-insert-snippet.spec.tsx
@@ -1,7 +1,7 @@
import type { SnippetWorkflowResponse } from '@dify/contracts/api/console/snippets/types.gen'
import type { QueryClient } from '@tanstack/react-query'
import { act, renderHook } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createQueryClientWrapper } from '@/test/console/query-client'
import { createTestQueryClient } from '@/test/query-client'
import { NESTED_ELEMENT_Z_INDEX } from '../../../constants'
diff --git a/web/app/components/workflow/block-selector/snippets/snippet-tags-filter.tsx b/web/app/components/workflow/block-selector/snippets/snippet-tags-filter.tsx
index 45650dd87b8..dc87e69d8f1 100644
--- a/web/app/components/workflow/block-selector/snippets/snippet-tags-filter.tsx
+++ b/web/app/components/workflow/block-selector/snippets/snippet-tags-filter.tsx
@@ -7,7 +7,7 @@ import { Popover, PopoverContent, PopoverTitle, PopoverTrigger } from '@langgeni
import { useQuery } from '@tanstack/react-query'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type SnippetTagsFilterProps = {
embedded?: boolean
diff --git a/web/app/components/workflow/block-selector/snippets/use-insert-snippet.ts b/web/app/components/workflow/block-selector/snippets/use-insert-snippet.ts
index d4dbd266b6d..9797e9a998d 100644
--- a/web/app/components/workflow/block-selector/snippets/use-insert-snippet.ts
+++ b/web/app/components/workflow/block-selector/snippets/use-insert-snippet.ts
@@ -6,7 +6,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useStoreApi } from 'reactflow'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useIncrementSnippetUseCountMutation } from '@/service/use-snippets'
import { CUSTOM_EDGE, NESTED_ELEMENT_Z_INDEX, NODE_WIDTH_X_OFFSET, X_OFFSET } from '../../constants'
import { useNodesSyncDraft } from '../../hooks/use-nodes-sync-draft'
diff --git a/web/app/components/workflow/comment/mention-input.spec.tsx b/web/app/components/workflow/comment/mention-input.spec.tsx
index 0483112c6f2..12569aa063e 100644
--- a/web/app/components/workflow/comment/mention-input.spec.tsx
+++ b/web/app/components/workflow/comment/mention-input.spec.tsx
@@ -23,7 +23,7 @@ vi.mock('@/next/navigation', () => ({
useParams: () => ({ appId: 'app-1' }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
apps: {
byAppId: {
diff --git a/web/app/components/workflow/comment/mention-input.tsx b/web/app/components/workflow/comment/mention-input.tsx
index ab0c4d9d4c5..02fc0622d6b 100644
--- a/web/app/components/workflow/comment/mention-input.tsx
+++ b/web/app/components/workflow/comment/mention-input.tsx
@@ -22,7 +22,7 @@ import { useTranslation } from 'react-i18next'
import Textarea from 'react-textarea-autosize'
import EnterKey from '@/app/components/base/icons/src/public/common/EnterKey'
import { useParams } from '@/next/navigation'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { useStore, useWorkflowStore } from '../store'
type MentionInputProps = {
diff --git a/web/app/components/workflow/header/header-in-restoring.tsx b/web/app/components/workflow/header/header-in-restoring.tsx
index fbb50231808..d7b50c68324 100644
--- a/web/app/components/workflow/header/header-in-restoring.tsx
+++ b/web/app/components/workflow/header/header-in-restoring.tsx
@@ -11,7 +11,7 @@ import { getWorkflowVersionName } from '@/app/components/workflow/utils/version'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { deploymentEditionAtom } from '@/features/system-features/state'
import useTheme from '@/hooks/use-theme'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
useInvalidAllLastRun,
useResetWorkflowVersionHistory,
diff --git a/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts b/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
index 609fced45bf..5337dfb00d7 100644
--- a/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
+++ b/web/app/components/workflow/hooks/__tests__/use-checklist.spec.ts
@@ -7,7 +7,7 @@ import { QueryClient } from '@tanstack/react-query'
import { act, screen, waitFor } from '@testing-library/react'
import { createElement, Fragment } from 'react'
import { CollectionType } from '@/app/components/tools/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
import { createEdge, createNode, resetFixtureCounters } from '../../__tests__/fixtures'
import { resetReactFlowMockState, rfState } from '../../__tests__/reactflow-mock-state'
diff --git a/web/app/components/workflow/hooks/__tests__/use-workflow-comment.spec.ts b/web/app/components/workflow/hooks/__tests__/use-workflow-comment.spec.ts
index 7f20afb3075..cc3da3f2204 100644
--- a/web/app/components/workflow/hooks/__tests__/use-workflow-comment.spec.ts
+++ b/web/app/components/workflow/hooks/__tests__/use-workflow-comment.spec.ts
@@ -55,8 +55,8 @@ vi.mock('@/next/navigation', () => ({
useParams: () => ({ appId: 'app-1' }),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
diff --git a/web/app/components/workflow/hooks/use-checklist.ts b/web/app/components/workflow/hooks/use-checklist.ts
index ff17c8ddae3..1ad73227514 100644
--- a/web/app/components/workflow/hooks/use-checklist.ts
+++ b/web/app/components/workflow/hooks/use-checklist.ts
@@ -38,7 +38,7 @@ import {
getAgentToolPublishIssues,
useAgentToolPresentation,
} from '@/features/agent-v2/agent-detail/configure/tool-provider-catalog'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchDatasets } from '@/service/datasets'
import { useStrategyProviders } from '@/service/use-strategy'
import {
diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts
index 6d38ddf853f..94df08aeca4 100644
--- a/web/app/components/workflow/hooks/use-nodes-interactions.ts
+++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts
@@ -19,7 +19,7 @@ import { produce } from 'immer'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { getConnectedEdges, getOutgoers, useReactFlow } from 'reactflow'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { collaborationManager } from '../collaboration/core/collaboration-manager'
import {
CUSTOM_EDGE,
diff --git a/web/app/components/workflow/hooks/use-panel-interactions.ts b/web/app/components/workflow/hooks/use-panel-interactions.ts
index e7af3d7be3b..a261bf8ba44 100644
--- a/web/app/components/workflow/hooks/use-panel-interactions.ts
+++ b/web/app/components/workflow/hooks/use-panel-interactions.ts
@@ -1,7 +1,7 @@
import type { MouseEvent } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useCallback } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useWorkflowStore } from '../store'
import { readWorkflowClipboard } from '../utils'
diff --git a/web/app/components/workflow/hooks/use-workflow-comment.ts b/web/app/components/workflow/hooks/use-workflow-comment.ts
index a95554108ee..26207f0e04a 100644
--- a/web/app/components/workflow/hooks/use-workflow-comment.ts
+++ b/web/app/components/workflow/hooks/use-workflow-comment.ts
@@ -10,7 +10,7 @@ import { collaborationManager } from '@/app/components/workflow/collaboration/co
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useParams } from '@/next/navigation'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { useStore } from '../store'
import { ControlMode } from '../types'
diff --git a/web/app/components/workflow/nodes/agent-v2/__tests__/hooks.spec.tsx b/web/app/components/workflow/nodes/agent-v2/__tests__/hooks.spec.tsx
index 7dfe81301bd..a7d9b39c37c 100644
--- a/web/app/components/workflow/nodes/agent-v2/__tests__/hooks.spec.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/__tests__/hooks.spec.tsx
@@ -146,7 +146,7 @@ vi.mock('@/utils/create-app-tracking', () => ({
trackCreateApp: trackCreateAppMock,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/app/components/workflow/nodes/agent-v2/agent-soul-config.ts b/web/app/components/workflow/nodes/agent-v2/agent-soul-config.ts
index 52f3e663719..b1a07b4197c 100644
--- a/web/app/components/workflow/nodes/agent-v2/agent-soul-config.ts
+++ b/web/app/components/workflow/nodes/agent-v2/agent-soul-config.ts
@@ -18,7 +18,7 @@ import {
agentComposerSavedDraftAtom,
isAgentComposerDirtyAtom,
} from '@/features/agent-v2/agent-composer/store'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
import { useSerialAsyncCallback } from '../../hooks/use-serial-async-callback'
diff --git a/web/app/components/workflow/nodes/agent-v2/components/__tests__/agent-orchestrate-panel-content.spec.tsx b/web/app/components/workflow/nodes/agent-v2/components/__tests__/agent-orchestrate-panel-content.spec.tsx
index 3dbc255198d..26192f89f55 100644
--- a/web/app/components/workflow/nodes/agent-v2/components/__tests__/agent-orchestrate-panel-content.spec.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/components/__tests__/agent-orchestrate-panel-content.spec.tsx
@@ -203,7 +203,7 @@ vi.mock('@/app/components/workflow/nodes/agent-v2/agent-soul-config', () => ({
}),
}))
-vi.mock('@/service/client', async () => {
+vi.mock('@/service/console', async () => {
const { createSystemFeaturesFixture } = await import('@/test/console/system-features')
return {
consoleClient: {
diff --git a/web/app/components/workflow/nodes/agent-v2/components/__tests__/save-inline-agent-to-roster-dialog.spec.tsx b/web/app/components/workflow/nodes/agent-v2/components/__tests__/save-inline-agent-to-roster-dialog.spec.tsx
index 2e6a40f8560..ff949ad2267 100644
--- a/web/app/components/workflow/nodes/agent-v2/components/__tests__/save-inline-agent-to-roster-dialog.spec.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/components/__tests__/save-inline-agent-to-roster-dialog.spec.tsx
@@ -48,7 +48,7 @@ vi.mock('@/app/components/base/app-icon-picker', () => ({
) : null,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
apps: {
byAppId: {
diff --git a/web/app/components/workflow/nodes/agent-v2/components/agent-orchestrate-panel-content.tsx b/web/app/components/workflow/nodes/agent-v2/components/agent-orchestrate-panel-content.tsx
index 7f4d4b006b4..6f068bc216d 100644
--- a/web/app/components/workflow/nodes/agent-v2/components/agent-orchestrate-panel-content.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/components/agent-orchestrate-panel-content.tsx
@@ -72,7 +72,7 @@ import {
} from '@/features/agent-v2/analytics'
import { useCanManageAgents } from '@/features/agent-v2/permissions'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
import { useWorkflowInlineAgentConfigureSync } from '../agent-soul-config'
diff --git a/web/app/components/workflow/nodes/agent-v2/components/save-inline-agent-to-roster-dialog.tsx b/web/app/components/workflow/nodes/agent-v2/components/save-inline-agent-to-roster-dialog.tsx
index 69f4f72b89d..2662213eda5 100644
--- a/web/app/components/workflow/nodes/agent-v2/components/save-inline-agent-to-roster-dialog.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/components/save-inline-agent-to-roster-dialog.tsx
@@ -24,7 +24,7 @@ import { useTranslation } from 'react-i18next'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import { createAgentIconSelection } from '@/features/agent-v2/roster/components/agent-form'
import { AgentFormFields } from '@/features/agent-v2/roster/components/agent-form-fields'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
type SaveInlineAgentToRosterDialogProps = {
diff --git a/web/app/components/workflow/nodes/agent-v2/hooks.ts b/web/app/components/workflow/nodes/agent-v2/hooks.ts
index 7f07425cd2b..dde2e2cece6 100644
--- a/web/app/components/workflow/nodes/agent-v2/hooks.ts
+++ b/web/app/components/workflow/nodes/agent-v2/hooks.ts
@@ -7,7 +7,7 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro
import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { useInlineAgentScope } from '@/features/agent-v2/analytics'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { getDefaultAgentSoul } from './agent-soul-config'
diff --git a/web/app/components/workflow/nodes/agent-v2/panel.tsx b/web/app/components/workflow/nodes/agent-v2/panel.tsx
index 1c12d645377..869cbfc6fe6 100644
--- a/web/app/components/workflow/nodes/agent-v2/panel.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/panel.tsx
@@ -19,7 +19,7 @@ import {
} from '@/app/components/base/prompt-editor/plugins/agent-output-block/utils'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { useStore } from '@/app/components/workflow/store'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { FlowType } from '@/types/common'
import { useNodeDataUpdate } from '../../hooks/use-node-data-update'
import useNodeCrud from '../_base/hooks/use-node-crud'
diff --git a/web/app/components/workflow/nodes/knowledge-base/__tests__/panel.spec.tsx b/web/app/components/workflow/nodes/knowledge-base/__tests__/panel.spec.tsx
index 2b84b8c9b1e..4c1e77e0e57 100644
--- a/web/app/components/workflow/nodes/knowledge-base/__tests__/panel.spec.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/__tests__/panel.spec.tsx
@@ -23,7 +23,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/app/components/workflow/nodes/knowledge-base/node.tsx b/web/app/components/workflow/nodes/knowledge-base/node.tsx
index 6c1a39da19e..280c5bda231 100644
--- a/web/app/components/workflow/nodes/knowledge-base/node.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/node.tsx
@@ -12,7 +12,7 @@ import {
useModelList,
} from '@/app/components/header/account-setting/model-provider-page/hooks'
import { normalizeModelProviderModelsResponse } from '@/app/components/header/account-setting/model-provider-page/utils'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useEmbeddingModelStatus } from './hooks/use-embedding-model-status'
import { useSettingsDisplay } from './hooks/use-settings-display'
import { IndexMethodEnum } from './types'
diff --git a/web/app/components/workflow/nodes/knowledge-base/panel.tsx b/web/app/components/workflow/nodes/knowledge-base/panel.tsx
index 312c4216d45..5785921be7d 100644
--- a/web/app/components/workflow/nodes/knowledge-base/panel.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/panel.tsx
@@ -16,7 +16,7 @@ import {
} from '@/app/components/workflow/nodes/_base/components/layout'
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useNodesReadOnly } from '../../hooks/use-workflow'
import Split from '../_base/components/split'
import ChunkStructure from './components/chunk-structure'
diff --git a/web/app/components/workflow/panel/version-history-panel/action-menu/use-action-menu.ts b/web/app/components/workflow/panel/version-history-panel/action-menu/use-action-menu.ts
index 2d73b9088d6..a6d4592408a 100644
--- a/web/app/components/workflow/panel/version-history-panel/action-menu/use-action-menu.ts
+++ b/web/app/components/workflow/panel/version-history-panel/action-menu/use-action-menu.ts
@@ -5,7 +5,7 @@ import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useStore } from '@/app/components/workflow/store'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { VersionHistoryContextMenuOptions } from '../../../types'
const useActionMenu = (props: ActionMenuProps) => {
diff --git a/web/app/components/workflow/panel/version-history-panel/index.tsx b/web/app/components/workflow/panel/version-history-panel/index.tsx
index a123bd8de7a..2f484776560 100644
--- a/web/app/components/workflow/panel/version-history-panel/index.tsx
+++ b/web/app/components/workflow/panel/version-history-panel/index.tsx
@@ -15,7 +15,7 @@ import { PlanUpgradeModal } from '@/app/components/billing/plan-upgrade-modal'
import { getWorkflowVersionName } from '@/app/components/workflow/utils/version'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { deploymentEditionAtom } from '@/features/system-features/state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
useDeleteWorkflow,
useInvalidAllLastRun,
diff --git a/web/app/device/page.tsx b/web/app/device/page.tsx
index 114f28854a7..799839d8a1c 100644
--- a/web/app/device/page.tsx
+++ b/web/app/device/page.tsx
@@ -11,7 +11,7 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import useDocumentTitle from '@/hooks/use-document-title'
import Link from '@/next/link'
import { usePathname, useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { deviceLookup } from '@/service/device-flow'
import AuthorizeAccount from './components/authorize-account'
import AuthorizeSSO from './components/authorize-sso'
diff --git a/web/app/education/apply/__tests__/institution-field.spec.tsx b/web/app/education/apply/__tests__/institution-field.spec.tsx
index 4347fdb9ba1..64164e8a4d0 100644
--- a/web/app/education/apply/__tests__/institution-field.spec.tsx
+++ b/web/app/education/apply/__tests__/institution-field.spec.tsx
@@ -35,7 +35,7 @@ vi.mock('@tanstack/react-query', () => ({
},
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
account: {
education: {
diff --git a/web/app/education/apply/__tests__/page.spec.tsx b/web/app/education/apply/__tests__/page.spec.tsx
index f231a09aa8e..123afe6c3d2 100644
--- a/web/app/education/apply/__tests__/page.spec.tsx
+++ b/web/app/education/apply/__tests__/page.spec.tsx
@@ -46,7 +46,7 @@ vi.mock('@/hooks/use-async-window-open', () => ({
useAsyncWindowOpen: () => vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
billing: {
invoices: {
diff --git a/web/app/education/apply/application-entry.tsx b/web/app/education/apply/application-entry.tsx
index 63c1b07ccfc..3b409b5654b 100644
--- a/web/app/education/apply/application-entry.tsx
+++ b/web/app/education/apply/application-entry.tsx
@@ -3,7 +3,7 @@
import type { GetFeaturesResponse } from '@dify/contracts/api/console/features/types.gen'
import { useQuery } from '@tanstack/react-query'
import { redirect } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import EducationApplyPage from './application-form'
const selectEducationPlan = ({ billing, education }: GetFeaturesResponse) => ({
diff --git a/web/app/education/apply/application-form.tsx b/web/app/education/apply/application-form.tsx
index e13b62edc7e..f6ff4e07daa 100644
--- a/web/app/education/apply/application-form.tsx
+++ b/web/app/education/apply/application-form.tsx
@@ -20,7 +20,7 @@ import { useDocLink } from '@/context/i18n'
import { currentWorkspaceAtom, isCurrentWorkspaceManagerAtom } from '@/context/workspace-state'
import { useAsyncWindowOpen } from '@/hooks/use-async-window-open'
import Link from '@/next/link'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import UserInfo from '../user-info'
import AppliedEducationContent from './applied-education-content'
import InstitutionField from './institution-field'
diff --git a/web/app/education/apply/institution-field.tsx b/web/app/education/apply/institution-field.tsx
index a0b8366bddf..4e510fceb99 100644
--- a/web/app/education/apply/institution-field.tsx
+++ b/web/app/education/apply/institution-field.tsx
@@ -20,7 +20,7 @@ import { useId, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-sentinel'
import Loading from '@/app/components/base/loading'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const EDUCATION_AUTOCOMPLETE_PAGE_SIZE = 40
diff --git a/web/app/education/expire-notice/use-expire-notice.ts b/web/app/education/expire-notice/use-expire-notice.ts
index cf2f7ea057b..aacd3ee9829 100644
--- a/web/app/education/expire-notice/use-expire-notice.ts
+++ b/web/app/education/expire-notice/use-expire-notice.ts
@@ -8,7 +8,7 @@ import timezone from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
import { useProviderContext } from '@/context/provider-context'
import { userProfileQueryOptions } from '@/features/account-profile/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useDismissedEducationExpireNotice } from './storage'
dayjs.extend(utc)
diff --git a/web/app/education/verify/verify-flow.tsx b/web/app/education/verify/verify-flow.tsx
index 02782474251..11b7d8b0ef5 100644
--- a/web/app/education/verify/verify-flow.tsx
+++ b/web/app/education/verify/verify-flow.tsx
@@ -12,7 +12,7 @@ import { useDocLink } from '@/context/i18n'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import Link from '@/next/link'
import { redirect, useRouter } from '@/next/navigation'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { EducationStatusCard } from '../status-card'
import UserInfo from '../user-info'
diff --git a/web/app/install/installForm.tsx b/web/app/install/installForm.tsx
index 738f8a68ac5..7066080c042 100644
--- a/web/app/install/installForm.tsx
+++ b/web/app/install/installForm.tsx
@@ -23,8 +23,8 @@ import { LICENSE_LINK } from '@/constants/link'
import useDocumentTitle from '@/hooks/use-document-title'
import Link from '@/next/link'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
import { fetchInitValidateStatus, fetchSetupStatus, login, setup } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { encryptPassword as encodePassword } from '@/utils/encryption'
import Loading from '../components/base/loading'
diff --git a/web/app/layout.tsx b/web/app/layout.tsx
index 4d5bf49cdaa..50f9e13370a 100644
--- a/web/app/layout.tsx
+++ b/web/app/layout.tsx
@@ -23,6 +23,7 @@ import { AgentationLoader } from './components/devtools/agentation-loader'
import { ReactScanLoader } from './components/devtools/react-scan/loader'
import { I18nServerProvider } from './components/provider/i18n-server'
import { TanStackQueryProvider } from './query-provider'
+import '@/service/console/server'
import './styles/globals.css'
import './styles/markdown.css'
diff --git a/web/app/signin/components/mail-and-password-auth.tsx b/web/app/signin/components/mail-and-password-auth.tsx
index e0065482830..70d94d8a0ab 100644
--- a/web/app/signin/components/mail-and-password-auth.tsx
+++ b/web/app/signin/components/mail-and-password-auth.tsx
@@ -13,8 +13,8 @@ import { trackEvent } from '@/app/components/base/amplitude'
import { emailRegex } from '@/config'
import Link from '@/next/link'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
import { login } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { setWebAppAccessToken } from '@/service/webapp-auth'
import { encryptPassword } from '@/utils/encryption'
import { replaceLoginRedirect } from '@/utils/login-redirect.client'
diff --git a/web/app/signin/invite-settings/page.tsx b/web/app/signin/invite-settings/page.tsx
index 03fe6109ee2..744f649422b 100644
--- a/web/app/signin/invite-settings/page.tsx
+++ b/web/app/signin/invite-settings/page.tsx
@@ -27,8 +27,8 @@ import { i18n, setLocaleOnClient } from '@/i18n-config'
import { languages } from '@/i18n-config/language'
import Link from '@/next/link'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
import { activateMember } from '@/service/common'
+import { consoleQuery } from '@/service/console'
import { useInvitationCheck } from '@/service/use-common'
import { replaceLoginRedirect } from '@/utils/login-redirect.client'
import { getBrowserTimezone, timezones } from '@/utils/timezone'
diff --git a/web/app/signin/one-more-step.tsx b/web/app/signin/one-more-step.tsx
index 1c9f081271c..2e885e486ea 100644
--- a/web/app/signin/one-more-step.tsx
+++ b/web/app/signin/one-more-step.tsx
@@ -23,7 +23,7 @@ import { LICENSE_LINK } from '@/constants/link'
import { languages } from '@/i18n-config/language'
import Link from '@/next/link'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useOneMoreStep } from '@/service/use-common'
import { replaceLoginRedirect } from '@/utils/login-redirect.client'
import { timezones } from '@/utils/timezone'
diff --git a/web/app/signup/set-password/page.tsx b/web/app/signup/set-password/page.tsx
index b22c556346c..bf6f2ac347f 100644
--- a/web/app/signup/set-password/page.tsx
+++ b/web/app/signup/set-password/page.tsx
@@ -23,7 +23,7 @@ import { validPassword } from '@/config'
import { useLocale } from '@/context/i18n'
import useDocumentTitle from '@/hooks/use-document-title'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useMailRegister } from '@/service/use-common'
import { rememberCreateAppExternalAttribution } from '@/utils/create-app-tracking'
import { sendGAEvent } from '@/utils/gtag'
diff --git a/web/context/__tests__/console-bootstrap.spec.tsx b/web/context/__tests__/console-bootstrap.spec.tsx
index ae3e29272a4..87a9c2ae10b 100644
--- a/web/context/__tests__/console-bootstrap.spec.tsx
+++ b/web/context/__tests__/console-bootstrap.spec.tsx
@@ -111,7 +111,7 @@ vi.mock('@/features/account-profile/client', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
features: {
get: {
diff --git a/web/context/hooks/use-trigger-events-limit-modal.ts b/web/context/hooks/use-trigger-events-limit-modal.ts
index 0ea3aa44c1f..c19b9adab2f 100644
--- a/web/context/hooks/use-trigger-events-limit-modal.ts
+++ b/web/context/hooks/use-trigger-events-limit-modal.ts
@@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
import { getResetInDaysFromDate } from '@/app/components/billing/utils'
import { currentWorkspaceIdAtom } from '@/context/workspace-state'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type TriggerEventsLimitModalContent = {
usage: number
diff --git a/web/context/permission-state.ts b/web/context/permission-state.ts
index bbe3e15ad4b..5fd54aabc4e 100644
--- a/web/context/permission-state.ts
+++ b/web/context/permission-state.ts
@@ -2,7 +2,7 @@
import { atom } from 'jotai'
import { atomWithQuery } from 'jotai-tanstack-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { emptyWorkspacePermissionKeys } from './app-context-normalizers'
const workspacePermissionKeysQueryAtom = atomWithQuery(() =>
diff --git a/web/context/provider-context-provider.tsx b/web/context/provider-context-provider.tsx
index 04103f98431..c1cfc953089 100644
--- a/web/context/provider-context-provider.tsx
+++ b/web/context/provider-context-provider.tsx
@@ -6,7 +6,7 @@ import {
ModelStatusEnum,
ModelTypeEnum,
} from '@/app/components/header/account-setting/model-provider-page/declarations'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { commonQueryKeys, useModelListByType } from '@/service/use-common'
import { ProviderContext } from './provider-context'
diff --git a/web/context/workspace-state.ts b/web/context/workspace-state.ts
index a138e98c33e..bc66d1897ca 100644
--- a/web/context/workspace-state.ts
+++ b/web/context/workspace-state.ts
@@ -2,7 +2,7 @@
import { atom } from 'jotai'
import { atomWithQuery } from 'jotai-tanstack-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { initialWorkspaceSummary } from './app-context-defaults'
import { getWorkspaceRoleFlags, normalizeCurrentWorkspaceSummary } from './app-context-normalizers'
diff --git a/web/features/account-profile/__tests__/server.spec.ts b/web/features/account-profile/__tests__/server.spec.ts
index a7628fc92ec..457271c7fdc 100644
--- a/web/features/account-profile/__tests__/server.spec.ts
+++ b/web/features/account-profile/__tests__/server.spec.ts
@@ -1,7 +1,7 @@
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
import { QueryClient } from '@tanstack/react-query'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
-import { resolveServerConsoleApiUrl } from '@/service/server'
+import { resolveServerConsoleApiUrl } from '@/service/console/server'
import { userProfileQueryOptions } from '../client'
const headersMock = vi.fn()
diff --git a/web/features/account-profile/client.ts b/web/features/account-profile/client.ts
index aaa11e77786..cfddc3df418 100644
--- a/web/features/account-profile/client.ts
+++ b/web/features/account-profile/client.ts
@@ -3,7 +3,7 @@ import { queryOptions } from '@tanstack/react-query'
import { IS_DEV } from '@/config'
// oxlint-disable-next-line no-restricted-imports
import { get } from '@/service/base'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export type UserProfileWithMeta = {
profile: GetAccountProfileResponse
diff --git a/web/features/account-profile/server.ts b/web/features/account-profile/server.ts
index 49f279f34a6..1c132254603 100644
--- a/web/features/account-profile/server.ts
+++ b/web/features/account-profile/server.ts
@@ -1,17 +1,17 @@
import type { GetAccountProfileResponse } from '@dify/contracts/api/console/account/types.gen'
import type { UserProfileWithMeta } from './client'
import { queryOptions } from '@tanstack/react-query'
+import { consoleQuery } from '@/service/console'
import {
getServerConsoleRequestHeaders,
resolveServerConsoleApiUrl,
- serverConsoleQuery,
-} from '@/service/server'
+} from '@/service/console/server'
const ACCOUNT_PROFILE_PATH = '/account/profile'
export const serverUserProfileQueryOptions = () =>
queryOptions({
- queryKey: serverConsoleQuery.account.profile.get.queryKey(),
+ queryKey: consoleQuery.account.profile.get.queryKey(),
queryFn: async () => {
const profileUrl = resolveServerConsoleApiUrl(ACCOUNT_PROFILE_PATH)
if (!profileUrl) throw new Error('Server account profile URL is not configured')
diff --git a/web/features/agent-v2/agent-detail/__tests__/layout.spec.tsx b/web/features/agent-v2/agent-detail/__tests__/layout.spec.tsx
index 2bfab6e2a23..63fd96c2c78 100644
--- a/web/features/agent-v2/agent-detail/__tests__/layout.spec.tsx
+++ b/web/features/agent-v2/agent-detail/__tests__/layout.spec.tsx
@@ -37,7 +37,7 @@ vi.mock('@/hooks/use-document-title', () => ({
const mockUseDocumentTitle = vi.mocked(useDocumentTitle)
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/__tests__/navigation.spec.tsx b/web/features/agent-v2/agent-detail/__tests__/navigation.spec.tsx
index dd6c315d597..8751a2ccf45 100644
--- a/web/features/agent-v2/agent-detail/__tests__/navigation.spec.tsx
+++ b/web/features/agent-v2/agent-detail/__tests__/navigation.spec.tsx
@@ -47,7 +47,7 @@ vi.mock('@/app/components/base/divider', () => ({
default: () => ,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/access/components/__tests__/access-surface-cards.spec.tsx b/web/features/agent-v2/agent-detail/access/components/__tests__/access-surface-cards.spec.tsx
index 8613c5abcf3..5a7cfe4017e 100644
--- a/web/features/agent-v2/agent-detail/access/components/__tests__/access-surface-cards.spec.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/__tests__/access-surface-cards.spec.tsx
@@ -81,7 +81,7 @@ vi.mock('@/context/permission-state', async () => {
},
}))
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
account: {
profile: {
diff --git a/web/features/agent-v2/agent-detail/access/components/__tests__/workflow-references-table.spec.tsx b/web/features/agent-v2/agent-detail/access/components/__tests__/workflow-references-table.spec.tsx
index 63cdd9a729b..c8e67390e1b 100644
--- a/web/features/agent-v2/agent-detail/access/components/__tests__/workflow-references-table.spec.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/__tests__/workflow-references-table.spec.tsx
@@ -12,7 +12,7 @@ const mocks = vi.hoisted(() => ({
})),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/access/components/agent-api-key-modal.tsx b/web/features/agent-v2/agent-detail/access/components/agent-api-key-modal.tsx
index 7505d43e366..a7095abeaf1 100644
--- a/web/features/agent-v2/agent-detail/access/components/agent-api-key-modal.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/agent-api-key-modal.tsx
@@ -24,7 +24,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { CopyFeedback } from '@/app/components/base/copy-feedback'
import useTimestamp from '@/hooks/use-timestamp'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function AgentApiKeyModal({
agentId,
diff --git a/web/features/agent-v2/agent-detail/access/components/service-api-access-card.tsx b/web/features/agent-v2/agent-detail/access/components/service-api-access-card.tsx
index 095cc0422b5..e2ff559d5f0 100644
--- a/web/features/agent-v2/agent-detail/access/components/service-api-access-card.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/service-api-access-card.tsx
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'
import { AccessPointCard } from '@/app/components/base/access-point/card'
import { AccessPointUrl } from '@/app/components/base/access-point/url'
import { useDocLink } from '@/context/i18n'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentApiKeyModal } from './agent-api-key-modal'
export function ServiceApiAccessCard({ agentId }: { agentId: string }) {
diff --git a/web/features/agent-v2/agent-detail/access/components/web-app-access-card.tsx b/web/features/agent-v2/agent-detail/access/components/web-app-access-card.tsx
index 904f8f6f859..30836795bc0 100644
--- a/web/features/agent-v2/agent-detail/access/components/web-app-access-card.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/web-app-access-card.tsx
@@ -20,7 +20,7 @@ import { AccessPointCard } from '@/app/components/base/access-point/card'
import { AccessPointUrl } from '@/app/components/base/access-point/url'
import AppIcon from '@/app/components/base/app-icon'
import dynamic from '@/next/dynamic'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { useWebAppAccessControl } from './use-web-app-access-control'
diff --git a/web/features/agent-v2/agent-detail/access/components/workflow-references-table.tsx b/web/features/agent-v2/agent-detail/access/components/workflow-references-table.tsx
index 0c639b57020..f5a6e30b588 100644
--- a/web/features/agent-v2/agent-detail/access/components/workflow-references-table.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/workflow-references-table.tsx
@@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import useTimestamp from '@/hooks/use-timestamp'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type WorkflowReferencesTableProps = {
agentId: string
diff --git a/web/features/agent-v2/agent-detail/access/page.tsx b/web/features/agent-v2/agent-detail/access/page.tsx
index 76b9fe1d10c..bb8a00ddd4f 100644
--- a/web/features/agent-v2/agent-detail/access/page.tsx
+++ b/web/features/agent-v2/agent-detail/access/page.tsx
@@ -10,7 +10,7 @@ import {
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentDetailSectionSurface } from '../section-surface'
import { ServiceApiAccessCard } from './components/service-api-access-card'
import { WebAppAccessCard } from './components/web-app-access-card'
diff --git a/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx b/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
index 7b3e49e9ad4..90fb44f58d6 100644
--- a/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/__tests__/page.spec.tsx
@@ -201,7 +201,7 @@ vi.mock('@/app/components/base/amplitude', () => ({
trackEvent: trackEventMock,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-sync.spec.tsx b/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-sync.spec.tsx
index a3c1ddee992..a5be3c16c57 100644
--- a/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-sync.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/__tests__/use-agent-configure-sync.spec.tsx
@@ -183,7 +183,7 @@ vi.mock('@/service/use-tools', () => ({
useAllWorkflowTools: () => ({ data: toolProviderState.workflowTools }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
get: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx b/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
index d821ae639d8..8d4c92a1ddd 100644
--- a/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/composer-session.tsx
@@ -23,7 +23,7 @@ import {
trackAgentBuildModeRun,
trackAgentPreviewModeRun,
} from '@/features/agent-v2/analytics'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useAgentConfigureModelOptions } from '../hooks'
import {
agentConfigureConversationIdsAtom,
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
index 54397b1a11f..40719552008 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/__tests__/publish-bar.spec.tsx
@@ -84,7 +84,7 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/config-context.ts b/web/features/agent-v2/agent-detail/configure/components/orchestrate/config-context.ts
index 8b2a3b18e14..181f6a9f4c4 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/config-context.ts
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/config-context.ts
@@ -6,7 +6,7 @@ import { createContext, use } from 'react'
import { useProviderContextSelector } from '@/context/provider-context'
import { agentComposerFilesAtom } from '@/features/agent-v2/agent-composer/store-modules/files'
import { agentComposerSkillsAtom } from '@/features/agent-v2/agent-composer/store-modules/skills'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export type AgentConfigApiContext = {
agentId: string
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/__tests__/index.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/__tests__/index.spec.tsx
index baf869e8ef6..ed1872b48c6 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/__tests__/index.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/__tests__/index.spec.tsx
@@ -73,7 +73,7 @@ vi.mock('@/service/use-common', () => ({
useFileUploadConfig: () => ({ data: mocks.fileUploadConfig }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/index.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/index.tsx
index dc6af91432e..c1e586283b1 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/index.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/index.tsx
@@ -26,7 +26,7 @@ import {
removeAgentFileAtom,
upsertAgentFileAtom,
} from '@/features/agent-v2/agent-composer/store-modules/files'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadBlob, downloadUrl } from '@/utils/download'
import { useRegisterAgentOrchestrateAddAction } from '../add-actions-context'
import { ConfigureSectionAddButton } from '../common/add-button'
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/upload-dialog.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/upload-dialog.tsx
index 5fa77e80cca..9c8d483ad69 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/upload-dialog.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/files/upload-dialog.tsx
@@ -26,7 +26,7 @@ import { useTranslation } from 'react-i18next'
import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
import { getSupportFileType } from '@/app/components/base/file-uploader/utils'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useFileUploadConfig } from '@/service/use-common'
import { formatFileSize } from '@/utils/format'
import { getFileIconType } from './file-icon'
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
index fe3d48a4db5..d6bf797d589 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/publish-bar/index.tsx
@@ -20,7 +20,7 @@ import { useTranslation } from 'react-i18next'
import { isAgentComposerDirtyAtom } from '@/features/agent-v2/agent-composer/store'
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
import useTimestamp from '@/hooks/use-timestamp'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentPublishImpactDetails } from './publish-impact-details'
const PUBLISH_AGENT_HOTKEY = 'Mod+Shift+P' satisfies Hotkey
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/__tests__/index.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/__tests__/index.spec.tsx
index 87f9866df66..7c2c62d4128 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/__tests__/index.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/__tests__/index.spec.tsx
@@ -120,7 +120,7 @@ vi.mock('@/context/provider-context', () => ({
selector(mocks.providerContext),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/index.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/index.tsx
index 2e71c062535..4d2135e2412 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/index.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/index.tsx
@@ -44,7 +44,7 @@ import {
} from '@/features/skills/error'
import { TagFilter } from '@/features/tag-management/components/tag-filter'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useRegisterAgentOrchestrateAddAction } from '../add-actions-context'
import { ConfigureSectionEmpty } from '../common/empty'
import { ConfigureSection } from '../common/section'
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/item.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/item.tsx
index 9212f6da1db..62442f8430d 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/item.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/item.tsx
@@ -15,7 +15,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { noop } from 'es-toolkit/function'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadUrl } from '@/utils/download'
import { MissingReferenceWarning } from '../common/missing-reference-warning'
import { AgentSkillDetailDialog } from './detail-dialog'
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/upload-dialog.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/upload-dialog.tsx
index ba0f86e5e90..57c2d092cf8 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/upload-dialog.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/upload-dialog.tsx
@@ -21,7 +21,7 @@ import { useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useFileSizeLimit } from '@/app/components/base/file-uploader/hooks'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useFileUploadConfig } from '@/service/use-common'
import { formatFileSize } from '@/utils/format'
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/use-skill-detail.ts b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/use-skill-detail.ts
index cffe5010470..aafcbfdce4a 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/use-skill-detail.ts
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/skills/use-skill-detail.ts
@@ -10,7 +10,7 @@ import Cookies from 'js-cookie'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { API_PREFIX, CSRF_COOKIE_NAME, CSRF_HEADER_NAME } from '@/config'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadBlob } from '@/utils/download'
import { getDriveFileIconType } from '../files/file-icon'
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx
index de31e43a447..6c66bed2c6b 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx
@@ -14,7 +14,7 @@ import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import { agentComposerDraftAtom } from '@/features/agent-v2/agent-composer/store'
import { agentComposerModelAtom } from '@/features/agent-v2/agent-composer/store-modules/model'
import { agentComposerPromptAtom } from '@/features/agent-v2/agent-composer/store-modules/prompt'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { render } from '@/test/console/render'
import { seedRegisteredConsoleStateFixture } from '@/test/console/state-fixture'
@@ -226,7 +226,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', ()
}),
}))
-vi.mock('@/service/client', async () => {
+vi.mock('@/service/console', async () => {
const { skipToken } = await import('@tanstack/react-query')
const getChatMessagesQueryKey = (input: unknown) => ['agent-chat-conversation-messages', input]
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/versions-panel.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/versions-panel.spec.tsx
index d37e7174589..39515b8debb 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/versions-panel.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/versions-panel.spec.tsx
@@ -45,7 +45,7 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
account: {
profile: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/working-directory-panel.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/working-directory-panel.spec.tsx
index de036134c5a..8317302679c 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/working-directory-panel.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/working-directory-panel.spec.tsx
@@ -86,7 +86,7 @@ const previewSourceCases = [
},
] as const
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/chat-conversation.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/chat-conversation.tsx
index 3f5808f93be..189b632d72c 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/chat-conversation.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/chat-conversation.tsx
@@ -22,7 +22,7 @@ import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/cha
import { useDocLink } from '@/context/i18n'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import dynamic from '@/next/dynamic'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { getAgentSoulInputs, getAgentSoulInputsForm } from './chat-config'
const Chat = dynamic(() => import('@/app/components/base/chat/chat'), { ssr: false })
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/chat-runtime.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/chat-runtime.tsx
index ba38040d440..8c7dec8d6e7 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/chat-runtime.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/chat-runtime.tsx
@@ -7,7 +7,7 @@ import type { AnswerActionPosition } from '@/app/components/base/chat/chat/answe
import { skipToken, useQuery } from '@tanstack/react-query'
import { useCallback, useMemo, useState } from 'react'
import Loading from '@/app/components/base/loading'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getFormattedAgentDebugChatTree } from './chat-history'
import { AgentPreviewChatSession } from './chat-session'
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/hook/use-working-directory-panel.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/hook/use-working-directory-panel.tsx
index dbdd3bf43cf..e4a0bc1b4c2 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/hook/use-working-directory-panel.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/hook/use-working-directory-panel.tsx
@@ -4,7 +4,7 @@ import type { QueryClient } from '@tanstack/react-query'
import type { ReactNode } from 'react'
import type { AgentWorkingDirectorySource } from '../working-directory-panel'
import { useState } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentWorkingDirectoryPanel } from '../working-directory-panel'
export function invalidateAgentWorkingDirectoryFiles({
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/versions-panel/index.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/versions-panel/index.tsx
index 3dc6a867964..af2b71b96a8 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/versions-panel/index.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/versions-panel/index.tsx
@@ -5,7 +5,7 @@ import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { userProfileQueryOptions } from '@/features/account-profile/client'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { CurrentDraftItem } from './current-draft-item'
import { VersionFilter } from './filter'
import { VersionFilterEmpty } from './version-filter-empty'
diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/working-directory-panel.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/working-directory-panel.tsx
index d4115e756e8..401f3f12392 100644
--- a/web/features/agent-v2/agent-detail/configure/components/preview/working-directory-panel.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/preview/working-directory-panel.tsx
@@ -18,7 +18,7 @@ import { skipToken, useMutation, useQueries, useQuery } from '@tanstack/react-qu
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Infotip } from '@/app/components/base/infotip'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { downloadUrl } from '@/utils/download'
import { getFileIconType } from '../orchestrate/files/file-icon'
import { AgentSkillDetailDialog } from '../orchestrate/skills/detail-dialog'
diff --git a/web/features/agent-v2/agent-detail/configure/hooks.ts b/web/features/agent-v2/agent-detail/configure/hooks.ts
index ea4ab408502..05ac8a53247 100644
--- a/web/features/agent-v2/agent-detail/configure/hooks.ts
+++ b/web/features/agent-v2/agent-detail/configure/hooks.ts
@@ -13,7 +13,7 @@ import {
} from '@/app/components/header/account-setting/model-provider-page/hooks'
import { agentComposerAppFeaturesAtom } from '@/features/agent-v2/agent-composer/store-modules/app-features'
import { agentComposerModelAtom } from '@/features/agent-v2/agent-composer/store-modules/model'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function useAgentConfigureData(agentId: string, selectedVersionId: string | null) {
const agentQuery = useQuery(
diff --git a/web/features/agent-v2/agent-detail/configure/use-agent-build-draft-run.ts b/web/features/agent-v2/agent-detail/configure/use-agent-build-draft-run.ts
index 0e7e738216b..3e3b8914e02 100644
--- a/web/features/agent-v2/agent-detail/configure/use-agent-build-draft-run.ts
+++ b/web/features/agent-v2/agent-detail/configure/use-agent-build-draft-run.ts
@@ -4,7 +4,7 @@ import type { AgentSoulConfig } from '@dify/contracts/api/console/agent/types.ge
import type { AgentConfigureSoulSource } from './state'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useCallback } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function usePrepareAgentBuildDraftBeforeRun({
agentId,
diff --git a/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts b/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
index cdc49b18d24..01a2d7596e9 100644
--- a/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
+++ b/web/features/agent-v2/agent-detail/configure/use-agent-configure-build-draft.ts
@@ -17,7 +17,7 @@ import isEqual from 'fast-deep-equal'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { agentSoulConfigToFormState } from '@/features/agent-v2/agent-composer/conversions'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { usePrepareAgentBuildDraftBeforeRun } from './use-agent-build-draft-run'
const isNotFoundResponse = (error: unknown) => error instanceof Response && error.status === 404
diff --git a/web/features/agent-v2/agent-detail/configure/use-agent-configure-sync.ts b/web/features/agent-v2/agent-detail/configure/use-agent-configure-sync.ts
index c3a101a1106..76f34a4fe2b 100644
--- a/web/features/agent-v2/agent-detail/configure/use-agent-configure-sync.ts
+++ b/web/features/agent-v2/agent-detail/configure/use-agent-configure-sync.ts
@@ -23,7 +23,7 @@ import {
isAgentComposerDirtyAtom,
} from '@/features/agent-v2/agent-composer/store'
import { agentComposerToolPresentationIdentitiesAtom } from '@/features/agent-v2/agent-composer/store-modules/tools'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
getAgentToolPublishIssue,
useAgentToolPresentation,
diff --git a/web/features/agent-v2/agent-detail/layout.tsx b/web/features/agent-v2/agent-detail/layout.tsx
index 2c9c54f881e..e1710fb1f0a 100644
--- a/web/features/agent-v2/agent-detail/layout.tsx
+++ b/web/features/agent-v2/agent-detail/layout.tsx
@@ -6,7 +6,7 @@ import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import useDocumentTitle from '@/hooks/use-document-title'
import { usePathname, useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type AgentDetailLayoutProps = {
agentId: string
diff --git a/web/features/agent-v2/agent-detail/logs/__tests__/log-detail-panel.spec.tsx b/web/features/agent-v2/agent-detail/logs/__tests__/log-detail-panel.spec.tsx
index f968c1277a1..d620e5026c3 100644
--- a/web/features/agent-v2/agent-detail/logs/__tests__/log-detail-panel.spec.tsx
+++ b/web/features/agent-v2/agent-detail/logs/__tests__/log-detail-panel.spec.tsx
@@ -52,7 +52,7 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/logs/__tests__/page.spec.tsx b/web/features/agent-v2/agent-detail/logs/__tests__/page.spec.tsx
index 02a0fcbc018..59df00723b7 100644
--- a/web/features/agent-v2/agent-detail/logs/__tests__/page.spec.tsx
+++ b/web/features/agent-v2/agent-detail/logs/__tests__/page.spec.tsx
@@ -47,7 +47,7 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
systemFeatures: {
get: {
diff --git a/web/features/agent-v2/agent-detail/logs/components/log-detail-panel.tsx b/web/features/agent-v2/agent-detail/logs/components/log-detail-panel.tsx
index 99425a44891..21d7f103001 100644
--- a/web/features/agent-v2/agent-detail/logs/components/log-detail-panel.tsx
+++ b/web/features/agent-v2/agent-detail/logs/components/log-detail-panel.tsx
@@ -13,7 +13,7 @@ import Chat from '@/app/components/base/chat/chat'
import CopyIcon from '@/app/components/base/copy-icon'
import Loading from '@/app/components/base/loading'
import useTimestamp from '@/hooks/use-timestamp'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export function AgentLogDetailPanel({
agentId,
diff --git a/web/features/agent-v2/agent-detail/logs/page.tsx b/web/features/agent-v2/agent-detail/logs/page.tsx
index c26f6faafd5..0a9e7c7412b 100644
--- a/web/features/agent-v2/agent-detail/logs/page.tsx
+++ b/web/features/agent-v2/agent-detail/logs/page.tsx
@@ -20,7 +20,7 @@ import { SearchInput } from '@/app/components/base/search-input'
import Sort from '@/app/components/base/sort'
import { useDocLink } from '@/context/i18n'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentDetailSectionSurface } from '../section-surface'
import { AgentLogDetailPanel } from './components/log-detail-panel'
import { AgentLogsTable } from './components/logs-table'
diff --git a/web/features/agent-v2/agent-detail/monitoring/__tests__/page.spec.tsx b/web/features/agent-v2/agent-detail/monitoring/__tests__/page.spec.tsx
index 83a5f36bc47..b526705f68d 100644
--- a/web/features/agent-v2/agent-detail/monitoring/__tests__/page.spec.tsx
+++ b/web/features/agent-v2/agent-detail/monitoring/__tests__/page.spec.tsx
@@ -43,7 +43,7 @@ vi.mock('@/context/i18n', () => ({
useLocale: () => 'en-US',
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/agent-detail/monitoring/page.tsx b/web/features/agent-v2/agent-detail/monitoring/page.tsx
index b7a6952cb5c..5ebbc0b7c2b 100644
--- a/web/features/agent-v2/agent-detail/monitoring/page.tsx
+++ b/web/features/agent-v2/agent-detail/monitoring/page.tsx
@@ -25,7 +25,7 @@ import { keepPreviousData, useQuery } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentDetailSectionSurface } from '../section-surface'
import { AgentMonitoringChart } from './chart'
import { getAgentMonitoringMetrics } from './metrics'
diff --git a/web/features/agent-v2/agent-detail/navigation.tsx b/web/features/agent-v2/agent-detail/navigation.tsx
index 7d712a68713..1c7439aa682 100644
--- a/web/features/agent-v2/agent-detail/navigation.tsx
+++ b/web/features/agent-v2/agent-detail/navigation.tsx
@@ -20,7 +20,7 @@ import { gotoAnythingDialogHandle } from '@/app/components/goto-anything/dialog-
import { GOTO_ANYTHING_HOTKEY } from '@/app/components/goto-anything/hotkeys'
import Link from '@/next/link'
import { usePathname } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getAgentDetailPath, getAgentIdFromPathname } from './routes'
import { AgentDetailSidebarActions } from './sidebar-actions'
diff --git a/web/features/agent-v2/roster/__tests__/page.spec.tsx b/web/features/agent-v2/roster/__tests__/page.spec.tsx
index e1ac7fa07eb..538f1ef6c2e 100644
--- a/web/features/agent-v2/roster/__tests__/page.spec.tsx
+++ b/web/features/agent-v2/roster/__tests__/page.spec.tsx
@@ -32,8 +32,8 @@ const rosterQueryState = vi.hoisted(() => ({
| undefined,
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
const agentQuery = actual.consoleQuery.agent
const agentQueryWithInputCapture = new Proxy(agentQuery, {
get(target, property, receiver) {
diff --git a/web/features/agent-v2/roster/components/__tests__/agent-roster-list.spec.tsx b/web/features/agent-v2/roster/components/__tests__/agent-roster-list.spec.tsx
index f7f41181de1..93d279c6928 100644
--- a/web/features/agent-v2/roster/components/__tests__/agent-roster-list.spec.tsx
+++ b/web/features/agent-v2/roster/components/__tests__/agent-roster-list.spec.tsx
@@ -25,7 +25,7 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/roster/components/__tests__/create-agent-dialog.spec.tsx b/web/features/agent-v2/roster/components/__tests__/create-agent-dialog.spec.tsx
index 4890cc5a745..379c4b5c07c 100644
--- a/web/features/agent-v2/roster/components/__tests__/create-agent-dialog.spec.tsx
+++ b/web/features/agent-v2/roster/components/__tests__/create-agent-dialog.spec.tsx
@@ -38,7 +38,7 @@ vi.mock('@/utils/create-app-tracking', () => ({
trackCreateApp: trackCreateAppMock,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
post: {
diff --git a/web/features/agent-v2/roster/components/__tests__/delete-agent-dialog.spec.tsx b/web/features/agent-v2/roster/components/__tests__/delete-agent-dialog.spec.tsx
index 283ef38f0a7..7ed8e40a8b9 100644
--- a/web/features/agent-v2/roster/components/__tests__/delete-agent-dialog.spec.tsx
+++ b/web/features/agent-v2/roster/components/__tests__/delete-agent-dialog.spec.tsx
@@ -10,7 +10,7 @@ vi.mock('@tanstack/react-query', () => ({
useMutation: () => mutationMock,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/roster/components/__tests__/duplicate-agent-dialog.spec.tsx b/web/features/agent-v2/roster/components/__tests__/duplicate-agent-dialog.spec.tsx
index 6087ddb4e97..5993db4ab83 100644
--- a/web/features/agent-v2/roster/components/__tests__/duplicate-agent-dialog.spec.tsx
+++ b/web/features/agent-v2/roster/components/__tests__/duplicate-agent-dialog.spec.tsx
@@ -27,7 +27,7 @@ vi.mock('@/app/components/base/app-icon-picker', () => ({
}) => (open ? {`${initialEmoji?.icon}:${initialEmoji?.background}`} : null),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/roster/components/__tests__/edit-agent-dialog.spec.tsx b/web/features/agent-v2/roster/components/__tests__/edit-agent-dialog.spec.tsx
index 632e1fce60a..74f8145ca44 100644
--- a/web/features/agent-v2/roster/components/__tests__/edit-agent-dialog.spec.tsx
+++ b/web/features/agent-v2/roster/components/__tests__/edit-agent-dialog.spec.tsx
@@ -48,7 +48,7 @@ vi.mock('@/app/components/base/app-icon-picker', () => ({
) : null,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
agent: {
byAgentId: {
diff --git a/web/features/agent-v2/roster/components/create-agent-dialog.tsx b/web/features/agent-v2/roster/components/create-agent-dialog.tsx
index 149dc830677..f3b06ee126a 100644
--- a/web/features/agent-v2/roster/components/create-agent-dialog.tsx
+++ b/web/features/agent-v2/roster/components/create-agent-dialog.tsx
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import { AgentScope } from '@/features/agent-v2/analytics'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { getAgentDetailPath } from '../../agent-detail/routes'
import { defaultAgentIcon } from './agent-form'
diff --git a/web/features/agent-v2/roster/components/delete-agent-dialog.tsx b/web/features/agent-v2/roster/components/delete-agent-dialog.tsx
index 7984d2c8b5a..0d48d3c2fee 100644
--- a/web/features/agent-v2/roster/components/delete-agent-dialog.tsx
+++ b/web/features/agent-v2/roster/components/delete-agent-dialog.tsx
@@ -12,7 +12,7 @@ import {
import { toast } from '@langgenius/dify-ui/toast'
import { useMutation } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type DeleteAgentDialogProps = {
agentId: string
diff --git a/web/features/agent-v2/roster/components/duplicate-agent-dialog.tsx b/web/features/agent-v2/roster/components/duplicate-agent-dialog.tsx
index 4f8ba601227..5da78c8b859 100644
--- a/web/features/agent-v2/roster/components/duplicate-agent-dialog.tsx
+++ b/web/features/agent-v2/roster/components/duplicate-agent-dialog.tsx
@@ -17,7 +17,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AppIconPicker from '@/app/components/base/app-icon-picker'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createAgentIconSelection } from './agent-form'
import { AgentFormFields } from './agent-form-fields'
diff --git a/web/features/agent-v2/roster/components/edit-agent-dialog.tsx b/web/features/agent-v2/roster/components/edit-agent-dialog.tsx
index a35cf69b820..75467f043dc 100644
--- a/web/features/agent-v2/roster/components/edit-agent-dialog.tsx
+++ b/web/features/agent-v2/roster/components/edit-agent-dialog.tsx
@@ -16,7 +16,7 @@ import { useMutation } from '@tanstack/react-query'
import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AppIconPicker from '@/app/components/base/app-icon-picker'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { createAgentIconSelection, getAgentIconKey } from './agent-form'
import { AgentFormFields } from './agent-form-fields'
diff --git a/web/features/agent-v2/roster/components/roster-create-menu.tsx b/web/features/agent-v2/roster/components/roster-create-menu.tsx
index f827ae5b44b..cbd56206792 100644
--- a/web/features/agent-v2/roster/components/roster-create-menu.tsx
+++ b/web/features/agent-v2/roster/components/roster-create-menu.tsx
@@ -4,7 +4,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { CreateAppDropdown } from '@/app/components/app/create-app-dropdown'
import CreateFromDSLModal from '@/app/components/app/create-from-dsl-modal'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { CreateAgentDialog } from './create-agent-dialog'
export function RosterCreateMenu() {
diff --git a/web/features/agent-v2/roster/page.tsx b/web/features/agent-v2/roster/page.tsx
index c7f13199c7c..2cb68dab21c 100644
--- a/web/features/agent-v2/roster/page.tsx
+++ b/web/features/agent-v2/roster/page.tsx
@@ -16,7 +16,7 @@ import { useId } from 'react'
import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'
import useDocumentTitle from '@/hooks/use-document-title'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { AgentRosterList } from './components/agent-roster-list'
import { RosterToolbar } from './components/roster-toolbar'
import {
diff --git a/web/features/home/banner/home-banner.tsx b/web/features/home/banner/home-banner.tsx
index fbdabb63b03..1e116ba9cd5 100644
--- a/web/features/home/banner/home-banner.tsx
+++ b/web/features/home/banner/home-banner.tsx
@@ -2,7 +2,7 @@
import { useSuspenseQuery } from '@tanstack/react-query'
import { useLocale } from '@/context/i18n'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { Banner } from './banner'
export function HomeBanner() {
diff --git a/web/features/home/home-content/__tests__/home-content.spec.tsx b/web/features/home/home-content/__tests__/home-content.spec.tsx
index 2d4dc622829..891f6fd9a33 100644
--- a/web/features/home/home-content/__tests__/home-content.spec.tsx
+++ b/web/features/home/home-content/__tests__/home-content.spec.tsx
@@ -219,7 +219,7 @@ vi.mock('@/app/components/base/amplitude', () => ({
trackEvent: mockTrackEvent,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
systemFeatures: () => Promise.resolve({}),
},
diff --git a/web/features/home/home-content/home-content.tsx b/web/features/home/home-content/home-content.tsx
index 38afcb506ac..3bcc110fe1a 100644
--- a/web/features/home/home-content/home-content.tsx
+++ b/web/features/home/home-content/home-content.tsx
@@ -32,7 +32,7 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useImportDSL } from '@/hooks/use-import-dsl'
import { DSLImportMode } from '@/models/app'
import dynamic from '@/next/dynamic'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { hasPermission } from '@/utils/permission'
import { HomeBanner } from '../banner/home-banner'
diff --git a/web/features/home/page.tsx b/web/features/home/page.tsx
index 121dda7e0aa..31b6fb8ac0a 100644
--- a/web/features/home/page.tsx
+++ b/web/features/home/page.tsx
@@ -3,30 +3,25 @@ import { Suspense } from 'react'
import { getQueryClient } from '@/app/get-query-client'
import { getOptionalSystemFeatures } from '@/features/system-features/server'
import { getLocaleOnServer } from '@/i18n-config/server'
-import { getServerConsoleClientContext, serverConsoleQuery } from '@/service/server'
+import { consoleQuery } from '@/service/console'
import { HomeContent } from './home-content/home-content'
import { HomeShell } from './home-shell'
import { HomeSkeleton } from './home-skeleton'
export async function HomePage() {
const homeQueryClient = getQueryClient()
- const [locale, context] = await Promise.all([
- getLocaleOnServer(),
- getServerConsoleClientContext(),
- ])
+ const locale = await getLocaleOnServer()
void homeQueryClient
.query(
- serverConsoleQuery.explore.apps.get.queryOptions({
- context,
+ consoleQuery.explore.apps.get.queryOptions({
input: { query: { language: locale } },
}),
)
.catch(noop)
void homeQueryClient
.query(
- serverConsoleQuery.apps.recent.get.queryOptions({
- context,
+ consoleQuery.apps.recent.get.queryOptions({
input: { query: { limit: 8 } },
}),
)
@@ -36,8 +31,7 @@ export async function HomePage() {
if (enableExploreBanner) {
void homeQueryClient
.query(
- serverConsoleQuery.explore.banners.get.queryOptions({
- context,
+ consoleQuery.explore.banners.get.queryOptions({
input: { query: { language: locale } },
}),
)
diff --git a/web/features/new-rag/__tests__/add-source-page.spec.tsx b/web/features/new-rag/__tests__/add-source-page.spec.tsx
index 425d217337d..447dcb201ca 100644
--- a/web/features/new-rag/__tests__/add-source-page.spec.tsx
+++ b/web/features/new-rag/__tests__/add-source-page.spec.tsx
@@ -94,7 +94,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
postKnowledgeSpacesByIdSourceConnections: clientMock.createConnection,
diff --git a/web/features/new-rag/__tests__/crawl-selection-form.spec.tsx b/web/features/new-rag/__tests__/crawl-selection-form.spec.tsx
index a878aa38f7a..b6da837d90c 100644
--- a/web/features/new-rag/__tests__/crawl-selection-form.spec.tsx
+++ b/web/features/new-rag/__tests__/crawl-selection-form.spec.tsx
@@ -37,7 +37,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
return { ...original, useQueryClient: () => queryClientMock }
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
getKnowledgeSpacesByIdSourcesBySourceIdSyncPolicy: clientMock.getPolicy,
diff --git a/web/features/new-rag/__tests__/create-knowledge-page.spec.tsx b/web/features/new-rag/__tests__/create-knowledge-page.spec.tsx
index 4473c5a9a72..c4eb58bac5c 100644
--- a/web/features/new-rag/__tests__/create-knowledge-page.spec.tsx
+++ b/web/features/new-rag/__tests__/create-knowledge-page.spec.tsx
@@ -54,7 +54,7 @@ vi.mock('jotai', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
createKnowledgeSpace: serviceMock.create,
diff --git a/web/features/new-rag/__tests__/document-detail-page.spec.tsx b/web/features/new-rag/__tests__/document-detail-page.spec.tsx
index e7ae23efa20..b76300a2a4e 100644
--- a/web/features/new-rag/__tests__/document-detail-page.spec.tsx
+++ b/web/features/new-rag/__tests__/document-detail-page.spec.tsx
@@ -229,7 +229,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
knowledgeFs: {
getKnowledgeSpacesById: {
diff --git a/web/features/new-rag/__tests__/documents-page.spec.tsx b/web/features/new-rag/__tests__/documents-page.spec.tsx
index d0571c81e8a..91b470ddfb8 100644
--- a/web/features/new-rag/__tests__/documents-page.spec.tsx
+++ b/web/features/new-rag/__tests__/documents-page.spec.tsx
@@ -181,7 +181,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
getKnowledgeSpacesByIdDocumentsByDocumentIdProcessingTasksByTaskId: getTaskSnapshot,
diff --git a/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx b/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx
index 92cc9fc5b26..f484dffd319 100644
--- a/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx
+++ b/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx
@@ -34,8 +34,8 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', async (importOriginal) => {
- const original = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const original = await importOriginal()
return {
...original,
consoleQuery: {
diff --git a/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx b/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx
index 3c46e3a6c43..fbc628bd722 100644
--- a/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx
+++ b/web/features/new-rag/__tests__/new-knowledge-list.spec.tsx
@@ -90,7 +90,7 @@ vi.mock('@/context/i18n', () => ({
useLocale: () => 'en-US',
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
knowledgeFs: {
listKnowledgeSpaces: {
diff --git a/web/features/new-rag/__tests__/processing-task-events.spec.ts b/web/features/new-rag/__tests__/processing-task-events.spec.ts
index 0149042c092..5a6ae806257 100644
--- a/web/features/new-rag/__tests__/processing-task-events.spec.ts
+++ b/web/features/new-rag/__tests__/processing-task-events.spec.ts
@@ -7,7 +7,7 @@ const { mockStreamEvents } = vi.hoisted(() => ({
mockStreamEvents: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
getKnowledgeSpacesByIdDocumentsByDocumentIdProcessingTasksByTaskIdEvents: mockStreamEvents,
diff --git a/web/features/new-rag/__tests__/sources-page.spec.tsx b/web/features/new-rag/__tests__/sources-page.spec.tsx
index de137089814..c1e9da05078 100644
--- a/web/features/new-rag/__tests__/sources-page.spec.tsx
+++ b/web/features/new-rag/__tests__/sources-page.spec.tsx
@@ -60,7 +60,7 @@ vi.mock('@tanstack/react-query', async (importOriginal) => {
}
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
deleteKnowledgeSpacesByIdSourcesBySourceId: clientMock.deleteSource,
diff --git a/web/features/new-rag/__tests__/website-crawl-preview.spec.tsx b/web/features/new-rag/__tests__/website-crawl-preview.spec.tsx
index d52d4a6847c..b817d1349f3 100644
--- a/web/features/new-rag/__tests__/website-crawl-preview.spec.tsx
+++ b/web/features/new-rag/__tests__/website-crawl-preview.spec.tsx
@@ -48,7 +48,7 @@ vi.mock('../crawl-selection-form', () => ({
),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
knowledgeFs: {
getKnowledgeSpacesByIdSources: clientMock.listSources,
diff --git a/web/features/new-rag/add-source-page.tsx b/web/features/new-rag/add-source-page.tsx
index ec9b880dba9..f5146738950 100644
--- a/web/features/new-rag/add-source-page.tsx
+++ b/web/features/new-rag/add-source-page.tsx
@@ -16,7 +16,7 @@ import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { useRouter } from '@/next/navigation'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { PendingWebsiteSetup, UnavailableConnectedSourceSetup } from './add-source-placeholder'
import { AddSourceExitDialog } from './components/add-source-exit-dialog'
import {
diff --git a/web/features/new-rag/crawl-selection-form.tsx b/web/features/new-rag/crawl-selection-form.tsx
index baaf540390c..58ac95c344d 100644
--- a/web/features/new-rag/crawl-selection-form.tsx
+++ b/web/features/new-rag/crawl-selection-form.tsx
@@ -14,7 +14,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useId, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from '@/next/navigation'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { createRequestId } from './request-id'
import { newKnowledgeDetailPath } from './routes'
diff --git a/web/features/new-rag/create-knowledge-page.tsx b/web/features/new-rag/create-knowledge-page.tsx
index 6864b917fe6..758d74253a0 100644
--- a/web/features/new-rag/create-knowledge-page.tsx
+++ b/web/features/new-rag/create-knowledge-page.tsx
@@ -35,7 +35,7 @@ import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import useDocumentTitle from '@/hooks/use-document-title'
import { useRouter, useSearchParams } from '@/next/navigation'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { DatasetACLPermission, hasPermission } from '@/utils/permission'
import { KnowledgeIllustration, StartMode } from './components/create-knowledge-dialog-parts'
import { CreateKnowledgeExitDialog } from './components/create-knowledge-exit-dialog'
diff --git a/web/features/new-rag/create-knowledge-workflow.ts b/web/features/new-rag/create-knowledge-workflow.ts
index c77f07cacd6..b6e6fe35b27 100644
--- a/web/features/new-rag/create-knowledge-workflow.ts
+++ b/web/features/new-rag/create-knowledge-workflow.ts
@@ -1,5 +1,5 @@
import type { KnowledgeSpaceCreationResponse } from '@dify/contracts/knowledge-fs/types.gen'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
export const NAME_MAX_LENGTH = 160
export const DESCRIPTION_MAX_LENGTH = 2000
diff --git a/web/features/new-rag/document-detail-page.tsx b/web/features/new-rag/document-detail-page.tsx
index e8880fb259b..a4376e8b84b 100644
--- a/web/features/new-rag/document-detail-page.tsx
+++ b/web/features/new-rag/document-detail-page.tsx
@@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { datasetDefaultPermissionKeysAtom } from '@/context/permission-state'
import useDocumentTitle from '@/hooks/use-document-title'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { DatasetACLPermission, hasPermission } from '@/utils/permission'
import { DocumentDetailHeader } from './document-detail-header'
import { initialDocumentRevision, responseStatus } from './document-detail-model'
diff --git a/web/features/new-rag/document-detail-queries.ts b/web/features/new-rag/document-detail-queries.ts
index c504e8229c3..0a2967b3107 100644
--- a/web/features/new-rag/document-detail-queries.ts
+++ b/web/features/new-rag/document-detail-queries.ts
@@ -1,4 +1,4 @@
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
const CHUNK_PAGE_SIZE = 100
diff --git a/web/features/new-rag/documents-page.tsx b/web/features/new-rag/documents-page.tsx
index 1c1f986a5b7..6cbf5ffc5e0 100644
--- a/web/features/new-rag/documents-page.tsx
+++ b/web/features/new-rag/documents-page.tsx
@@ -22,7 +22,7 @@ import {
workspacePermissionKeysFetchingAtom,
workspacePermissionKeysLoadingAtom,
} from '@/context/permission-state'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { DatasetACLPermission, hasPermission } from '@/utils/permission'
import { useAuxiliaryTaskReadGuard } from './auxiliary-task-read-guard'
import { DocumentBulkActions, DocumentsEmpty, DocumentsList } from './document-list'
diff --git a/web/features/new-rag/knowledge-space-shell.tsx b/web/features/new-rag/knowledge-space-shell.tsx
index 8649c00c05c..ae0b66df3d3 100644
--- a/web/features/new-rag/knowledge-space-shell.tsx
+++ b/web/features/new-rag/knowledge-space-shell.tsx
@@ -10,7 +10,7 @@ import Loading from '@/app/components/base/loading'
import useDocumentTitle from '@/hooks/use-document-title'
import Link from '@/next/link'
import { usePathname } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { newKnowledgeDetailPath, newKnowledgeDocumentsPath, newKnowledgeListPath } from './routes'
function responseStatus(error: unknown) {
diff --git a/web/features/new-rag/new-knowledge-list.tsx b/web/features/new-rag/new-knowledge-list.tsx
index eae1e017e68..189c920f2b5 100644
--- a/web/features/new-rag/new-knowledge-list.tsx
+++ b/web/features/new-rag/new-knowledge-list.tsx
@@ -11,7 +11,7 @@ import ExternalAPIPanel from '@/app/components/datasets/external-api/external-ap
import { ServiceApi } from '@/app/components/datasets/extra-info/service-api'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useDatasetApiBaseUrl } from '@/service/knowledge/use-dataset'
import { hasPermission } from '@/utils/permission'
import { KnowledgeSpaceCard } from './components/knowledge-space-card'
diff --git a/web/features/new-rag/processing-tasks-drawer.tsx b/web/features/new-rag/processing-tasks-drawer.tsx
index 3260cd7dd83..d60996d5c75 100644
--- a/web/features/new-rag/processing-tasks-drawer.tsx
+++ b/web/features/new-rag/processing-tasks-drawer.tsx
@@ -22,7 +22,7 @@ import { useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalS
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { taskCanRetry, taskIsActive, taskVersionIsAfter } from './document-model'
type TaskAction = 'cancel' | 'retry'
diff --git a/web/features/new-rag/services/processing-task-events.ts b/web/features/new-rag/services/processing-task-events.ts
index 01154f741d0..3a1b4b1a42a 100644
--- a/web/features/new-rag/services/processing-task-events.ts
+++ b/web/features/new-rag/services/processing-task-events.ts
@@ -1,6 +1,6 @@
import type { DocumentProcessingTaskEvent } from '@dify/contracts/knowledge-fs/types.gen'
import { getEventMeta } from '@orpc/client'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
type ProcessingTaskEventWithId = T & {
id: string
diff --git a/web/features/new-rag/sources-page.tsx b/web/features/new-rag/sources-page.tsx
index f4acb401841..b74f5de1784 100644
--- a/web/features/new-rag/sources-page.tsx
+++ b/web/features/new-rag/sources-page.tsx
@@ -31,7 +31,7 @@ import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import Link from '@/next/link'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { newKnowledgeAddSourcePath } from './routes'
diff --git a/web/features/new-rag/use-document-reindex.ts b/web/features/new-rag/use-document-reindex.ts
index 6066e6572c4..a4f7a7bd87f 100644
--- a/web/features/new-rag/use-document-reindex.ts
+++ b/web/features/new-rag/use-document-reindex.ts
@@ -6,7 +6,7 @@ import { useSetAtom } from 'jotai'
import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { refreshWorkspacePermissionKeysAfterMutationDenialAtom } from '@/context/permission-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { DatasetACLPermission, hasPermission } from '@/utils/permission'
import { responseStatus } from './document-detail-model'
import { useDocumentTaskStatus } from './use-document-task-status'
diff --git a/web/features/new-rag/use-document-task-status.ts b/web/features/new-rag/use-document-task-status.ts
index f27544abe0b..c7db943c747 100644
--- a/web/features/new-rag/use-document-task-status.ts
+++ b/web/features/new-rag/use-document-task-status.ts
@@ -7,7 +7,7 @@ import type {
import type { InfiniteData } from '@tanstack/react-query'
import { skipToken, useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query'
import { useEffect, useMemo, useRef, useState } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { responseStatus } from './document-detail-model'
import { newestTaskByDocument } from './document-model'
diff --git a/web/features/new-rag/website-crawl-preview.tsx b/web/features/new-rag/website-crawl-preview.tsx
index 171f96e725b..4a0a662b4b1 100644
--- a/web/features/new-rag/website-crawl-preview.tsx
+++ b/web/features/new-rag/website-crawl-preview.tsx
@@ -21,7 +21,7 @@ import { cn } from '@langgenius/dify-ui/cn'
import { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from '@/next/navigation'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { CrawlSelectionForm } from './crawl-selection-form'
import { createRequestId } from './request-id'
import {
diff --git a/web/features/skills/__tests__/detail-page.fixture.tsx b/web/features/skills/__tests__/detail-page.fixture.tsx
index c78dc4dba4c..9c900ab49ab 100644
--- a/web/features/skills/__tests__/detail-page.fixture.tsx
+++ b/web/features/skills/__tests__/detail-page.fixture.tsx
@@ -186,7 +186,7 @@ vi.mock('@/utils/download', () => ({
downloadBlob: mocks.downloadBlob,
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
workspaces: {
current: {
diff --git a/web/features/skills/__tests__/page.spec.tsx b/web/features/skills/__tests__/page.spec.tsx
index 07ec0652ea3..4a812e3686b 100644
--- a/web/features/skills/__tests__/page.spec.tsx
+++ b/web/features/skills/__tests__/page.spec.tsx
@@ -150,7 +150,7 @@ vi.mock('../client', () => ({
uploadSkillFile: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/features/skills/detail/__tests__/shared.spec.ts b/web/features/skills/detail/__tests__/shared.spec.ts
index da353608bde..f96b5d3f96c 100644
--- a/web/features/skills/detail/__tests__/shared.spec.ts
+++ b/web/features/skills/detail/__tests__/shared.spec.ts
@@ -1,6 +1,6 @@
import { QueryClient } from '@tanstack/react-query'
import { describe, expect, it, vi } from 'vite-plus/test'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
createUploadItemId,
deriveSkillDetailFromDraftFiles,
diff --git a/web/features/skills/detail/file-editor.tsx b/web/features/skills/detail/file-editor.tsx
index 4acf8ea755a..ccb19b09196 100644
--- a/web/features/skills/detail/file-editor.tsx
+++ b/web/features/skills/detail/file-editor.tsx
@@ -20,7 +20,7 @@ import { SkeletonRectangle } from '@/app/components/base/skeleton'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
import dynamic from '@/next/dynamic'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadBlob } from '@/utils/download'
import { fetchSkillFileBlob } from '../client'
import { FileTabs } from './file-tabs'
diff --git a/web/features/skills/detail/file-tree.tsx b/web/features/skills/detail/file-tree.tsx
index f1e7e987671..6a40d2cb225 100644
--- a/web/features/skills/detail/file-tree.tsx
+++ b/web/features/skills/detail/file-tree.tsx
@@ -63,7 +63,7 @@ import { GOTO_ANYTHING_HOTKEY } from '@/app/components/goto-anything/hotkeys'
import AccountSection from '@/app/components/main-nav/components/account-section'
import HelpMenu from '@/app/components/main-nav/components/help-menu'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { fetchSkillFileBlob, uploadSkillFile } from '../client'
import { SkillDropDestinationHint, SkillUploadStatusPanel } from './file-tree-dnd'
import { FileTreeItem, FileTreeNameInput, RootFileActionMenuItems } from './file-tree-items'
diff --git a/web/features/skills/detail/page.tsx b/web/features/skills/detail/page.tsx
index ea157340518..535f40d748d 100644
--- a/web/features/skills/detail/page.tsx
+++ b/web/features/skills/detail/page.tsx
@@ -18,7 +18,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import useDocumentTitle from '@/hooks/use-document-title'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { useSkillPermissions } from '../permissions'
import { SkillBuilderPanel } from './builder-panel'
import { FileEditor } from './file-editor'
diff --git a/web/features/skills/detail/shared.tsx b/web/features/skills/detail/shared.tsx
index 4ac6114f3c8..2afa1dd2933 100644
--- a/web/features/skills/detail/shared.tsx
+++ b/web/features/skills/detail/shared.tsx
@@ -15,7 +15,7 @@ import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import { getFileIconType } from '@/features/agent-v2/agent-detail/configure/components/orchestrate/files/file-icon'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import {
getSkillErrorCode,
getSkillErrorDetailNumber,
diff --git a/web/features/skills/detail/sidebar-actions.tsx b/web/features/skills/detail/sidebar-actions.tsx
index 2b6189d5de6..611bad6c07c 100644
--- a/web/features/skills/detail/sidebar-actions.tsx
+++ b/web/features/skills/detail/sidebar-actions.tsx
@@ -24,7 +24,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadBlob } from '@/utils/download'
import { fetchSkillArchiveBlob } from '../client'
import { SkillReferencesList, SkillReferencesListSkeleton } from './skill-metadata'
diff --git a/web/features/skills/detail/skill-display-name-editor.tsx b/web/features/skills/detail/skill-display-name-editor.tsx
index 7e2d1cb6db1..d7c519e6139 100644
--- a/web/features/skills/detail/skill-display-name-editor.tsx
+++ b/web/features/skills/detail/skill-display-name-editor.tsx
@@ -6,7 +6,7 @@ import { toast } from '@langgenius/dify-ui/toast'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useLayoutEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
getAsyncSkillErrorPayload,
getErrorCode,
diff --git a/web/features/skills/detail/skill-metadata.tsx b/web/features/skills/detail/skill-metadata.tsx
index db8db3e0d46..16a167c9d81 100644
--- a/web/features/skills/detail/skill-metadata.tsx
+++ b/web/features/skills/detail/skill-metadata.tsx
@@ -27,7 +27,7 @@ import { isCreateTagOption } from '@/features/tag-management/components/tag-comb
import { TagManagementModal } from '@/features/tag-management/components/tag-management-modal'
import { TagSearchContentView } from '@/features/tag-management/components/tag-search-content'
import Link from '@/next/link'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { SkillPublishShortcut } from './publish-bar'
import {
invalidateSkillDetail,
diff --git a/web/features/skills/detail/skill-publish-confirm-panel.stories.tsx b/web/features/skills/detail/skill-publish-confirm-panel.stories.tsx
index b288b5ac71e..9f1cc639853 100644
--- a/web/features/skills/detail/skill-publish-confirm-panel.stories.tsx
+++ b/web/features/skills/detail/skill-publish-confirm-panel.stories.tsx
@@ -1,7 +1,7 @@
import type { SkillReferenceResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { SkillPublishBottomActions } from './publish-bar'
import { SkillPublishConfirmPanel } from './skill-metadata'
diff --git a/web/features/skills/detail/version-panel.tsx b/web/features/skills/detail/version-panel.tsx
index 9be154c4b3b..1c1d8c39e6c 100644
--- a/web/features/skills/detail/version-panel.tsx
+++ b/web/features/skills/detail/version-panel.tsx
@@ -36,7 +36,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import useTimestamp from '@/hooks/use-timestamp'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getSkillVersionTitle, invalidateSkillDetail } from './shared'
type VersionFilterValue = 'all' | 'onlyNamed'
diff --git a/web/features/skills/page.tsx b/web/features/skills/page.tsx
index 0aec1f3509d..1913040a723 100644
--- a/web/features/skills/page.tsx
+++ b/web/features/skills/page.tsx
@@ -46,7 +46,7 @@ import useDocumentTitle from '@/hooks/use-document-title'
import { useFormatTimeFromNow } from '@/hooks/use-format-time-from-now'
import Link from '@/next/link'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { downloadBlob } from '@/utils/download'
import { fetchSkillArchiveBlob } from './client'
import { SkillReferencesList, SkillReferencesListSkeleton } from './detail/skill-metadata'
diff --git a/web/features/system-features/__tests__/bootstrap-boundary.spec.tsx b/web/features/system-features/__tests__/bootstrap-boundary.spec.tsx
index a817941d694..61273729ee0 100644
--- a/web/features/system-features/__tests__/bootstrap-boundary.spec.tsx
+++ b/web/features/system-features/__tests__/bootstrap-boundary.spec.tsx
@@ -7,7 +7,7 @@ import {
} from '@tanstack/react-query'
import { act, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
-import { serverConsoleQuery } from '@/service/server'
+import { consoleQuery } from '@/service/console'
import { createSystemFeaturesFixture } from '@/test/console/system-features'
import { SystemFeaturesBootstrapBoundary } from '../bootstrap-boundary'
@@ -87,7 +87,7 @@ describe('SystemFeaturesBootstrapBoundary', () => {
it('hydrates the server System Features query into the client boundary', () => {
const serverQueryClient = createQueryClient()
serverQueryClient.setQueryData(
- serverConsoleQuery.systemFeatures.get.queryKey(),
+ consoleQuery.systemFeatures.get.queryKey(),
createSystemFeaturesFixture(),
)
const queryClient = createQueryClient()
diff --git a/web/features/system-features/__tests__/server.spec.ts b/web/features/system-features/__tests__/server.spec.ts
index 10ec997f981..46f305c5fa7 100644
--- a/web/features/system-features/__tests__/server.spec.ts
+++ b/web/features/system-features/__tests__/server.spec.ts
@@ -40,8 +40,8 @@ vi.mock('@/next/server', () => ({
connection: mocks.connection,
}))
-vi.mock('@/service/server', () => ({
- serverConsoleQuery: {
+vi.mock('@/service/console', () => ({
+ consoleQuery: {
systemFeatures: {
get: {
queryOptions: (options?: { staleTime?: 'static' }) => ({
diff --git a/web/features/system-features/client.ts b/web/features/system-features/client.ts
index 976505d9bb4..b3d4ebc3c7e 100644
--- a/web/features/system-features/client.ts
+++ b/web/features/system-features/client.ts
@@ -1,4 +1,4 @@
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
export const systemFeaturesQueryOptions = () =>
consoleQuery.systemFeatures.get.queryOptions({
diff --git a/web/features/system-features/server.ts b/web/features/system-features/server.ts
index 91f3d2f2e02..6f5965ac92a 100644
--- a/web/features/system-features/server.ts
+++ b/web/features/system-features/server.ts
@@ -2,13 +2,13 @@ import { dehydrate } from '@tanstack/react-query'
import { cache } from 'react'
import { getQueryClient } from '@/app/get-query-client'
import { connection } from '@/next/server'
-import { serverConsoleQuery } from '@/service/server'
+import { consoleQuery } from '@/service/console'
import 'server-only'
const getRequestQueryClient = cache(getQueryClient)
const systemFeaturesServerQueryOptions = () =>
- serverConsoleQuery.systemFeatures.get.queryOptions({ staleTime: 'static' })
+ consoleQuery.systemFeatures.get.queryOptions({ staleTime: 'static' })
export const getOptionalSystemFeatures = async () => {
await connection()
diff --git a/web/features/tag-management/__tests__/skill-card-tags.spec.tsx b/web/features/tag-management/__tests__/skill-card-tags.spec.tsx
index 9e5528fb654..4ad2fd222ab 100644
--- a/web/features/tag-management/__tests__/skill-card-tags.spec.tsx
+++ b/web/features/tag-management/__tests__/skill-card-tags.spec.tsx
@@ -16,7 +16,7 @@ vi.mock('@tanstack/react-query', () => ({
useQuery: () => ({ data: mocks.tagList }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/features/tag-management/__tests__/tag-item-editor.spec.tsx b/web/features/tag-management/__tests__/tag-item-editor.spec.tsx
index 63a519125af..4efdf35ff99 100644
--- a/web/features/tag-management/__tests__/tag-item-editor.spec.tsx
+++ b/web/features/tag-management/__tests__/tag-item-editor.spec.tsx
@@ -44,7 +44,7 @@ vi.mock('@tanstack/react-query', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
byTagId: {
diff --git a/web/features/tag-management/__tests__/tag-management-modal.spec.tsx b/web/features/tag-management/__tests__/tag-management-modal.spec.tsx
index 6a44632f12b..5bd1f6fdb32 100644
--- a/web/features/tag-management/__tests__/tag-management-modal.spec.tsx
+++ b/web/features/tag-management/__tests__/tag-management-modal.spec.tsx
@@ -52,7 +52,7 @@ vi.mock('@/context/permission-state', async () => {
}))
})
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/features/tag-management/__tests__/tag-selector.spec.tsx b/web/features/tag-management/__tests__/tag-selector.spec.tsx
index 2cb24e804f9..e88aad06e82 100644
--- a/web/features/tag-management/__tests__/tag-selector.spec.tsx
+++ b/web/features/tag-management/__tests__/tag-selector.spec.tsx
@@ -54,7 +54,7 @@ vi.mock('@tanstack/react-query', () => ({
}),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleQuery: {
tags: {
get: {
diff --git a/web/features/tag-management/components/skill-card-tags.tsx b/web/features/tag-management/components/skill-card-tags.tsx
index 2832c6390cb..a02d6b812e3 100644
--- a/web/features/tag-management/components/skill-card-tags.tsx
+++ b/web/features/tag-management/components/skill-card-tags.tsx
@@ -1,7 +1,7 @@
import type { TagResponse as Tag } from '@dify/contracts/api/console/tags/types.gen'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { TagSelector } from './tag-selector'
type SkillCardTagsProps = {
diff --git a/web/features/tag-management/components/tag-filter.tsx b/web/features/tag-management/components/tag-filter.tsx
index 9fb65e95924..86b34404260 100644
--- a/web/features/tag-management/components/tag-filter.tsx
+++ b/web/features/tag-management/components/tag-filter.tsx
@@ -14,7 +14,7 @@ import { useQuery } from '@tanstack/react-query'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import XCircleIcon from '@/app/components/base/icons/src/vender/solid/general/XCircle'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { TagSearchContent } from './tag-search-content'
const tagFilterComboboxFilter: NonNullable['filter']> = (
diff --git a/web/features/tag-management/components/tag-item-editor.tsx b/web/features/tag-management/components/tag-item-editor.tsx
index 484ae2b2f93..434ea325e68 100644
--- a/web/features/tag-management/components/tag-item-editor.tsx
+++ b/web/features/tag-management/components/tag-item-editor.tsx
@@ -15,7 +15,7 @@ import { useMutation } from '@tanstack/react-query'
import { useDebounceFn } from 'ahooks'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
type TagItemEditorProps = {
tag: Tag
diff --git a/web/features/tag-management/components/tag-management-modal.tsx b/web/features/tag-management/components/tag-management-modal.tsx
index 804d95dc88f..8b81e18d178 100644
--- a/web/features/tag-management/components/tag-management-modal.tsx
+++ b/web/features/tag-management/components/tag-management-modal.tsx
@@ -8,7 +8,7 @@ import { useAtomValue } from 'jotai'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { getTagManagePermissionKey } from '../utils'
import { TagItemEditor } from './tag-item-editor'
diff --git a/web/features/tag-management/components/tag-selector.tsx b/web/features/tag-management/components/tag-selector.tsx
index c800c05bb3a..debcac8c8a0 100644
--- a/web/features/tag-management/components/tag-selector.tsx
+++ b/web/features/tag-management/components/tag-selector.tsx
@@ -16,7 +16,7 @@ import { useAtomValue } from 'jotai'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { hasPermission } from '@/utils/permission'
import { useApplyTagBindingsMutation } from '../hooks/use-tag-mutations'
import { getTagManagePermissionKey } from '../utils'
diff --git a/web/features/tag-management/hooks/__tests__/use-tag-mutations.spec.tsx b/web/features/tag-management/hooks/__tests__/use-tag-mutations.spec.tsx
index cf1849ba52a..8d377496c4a 100644
--- a/web/features/tag-management/hooks/__tests__/use-tag-mutations.spec.tsx
+++ b/web/features/tag-management/hooks/__tests__/use-tag-mutations.spec.tsx
@@ -21,7 +21,7 @@ const { appListKey, bindTag, listKey, recentAppListKey, starredAppListKey, unbin
}),
)
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
tagBindings: {
post: bindTag,
diff --git a/web/features/tag-management/hooks/use-tag-mutations.ts b/web/features/tag-management/hooks/use-tag-mutations.ts
index d519cad000a..7797f5bc8ee 100644
--- a/web/features/tag-management/hooks/use-tag-mutations.ts
+++ b/web/features/tag-management/hooks/use-tag-mutations.ts
@@ -1,6 +1,6 @@
import type { TagType } from '@dify/contracts/api/console/tags/types.gen'
import { useMutation, useQueryClient } from '@tanstack/react-query'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
type ApplyTagBindingsInput = {
currentTagIds: string[]
diff --git a/web/hooks/use-import-dsl.spec.tsx b/web/hooks/use-import-dsl.spec.tsx
index d8aff462318..65b0a141f15 100644
--- a/web/hooks/use-import-dsl.spec.tsx
+++ b/web/hooks/use-import-dsl.spec.tsx
@@ -38,8 +38,8 @@ vi.mock('@/next/navigation', () => ({
useRouter: () => ({ push: mockPush }),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
diff --git a/web/hooks/use-import-dsl.ts b/web/hooks/use-import-dsl.ts
index 81e32d46a91..b7b05c8edae 100644
--- a/web/hooks/use-import-dsl.ts
+++ b/web/hooks/use-import-dsl.ts
@@ -12,7 +12,7 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { DSLImportStatus } from '@/models/app'
import { useRouter } from '@/next/navigation'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { getRedirection } from '@/utils/app-redirection'
import { resolveImportedAppRedirectionTarget } from '@/utils/imported-app-redirection'
diff --git a/web/instrumentation.ts b/web/instrumentation.ts
new file mode 100644
index 00000000000..0aee7062407
--- /dev/null
+++ b/web/instrumentation.ts
@@ -0,0 +1,3 @@
+export async function register() {
+ await import('./service/console/server')
+}
diff --git a/web/service/__tests__/server.spec.ts b/web/service/__tests__/server.spec.ts
deleted file mode 100644
index 5fb935c53ec..00000000000
--- a/web/service/__tests__/server.spec.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-// @vitest-environment node
-
-import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
-
-const mocks = vi.hoisted(() => ({
- headers: vi.fn(),
- cookies: vi.fn(),
- serverConsoleApiPrefix: undefined as string | undefined,
-}))
-
-vi.mock('server-only', () => ({}))
-
-vi.mock('@/config', () => ({
- API_PREFIX: 'http://localhost:5001/console/api',
- CSRF_COOKIE_NAME: () => 'csrf_token',
- CSRF_HEADER_NAME: 'X-CSRF-Token',
-}))
-
-vi.mock('@/config/server', () => ({
- get SERVER_CONSOLE_API_PREFIX() {
- return mocks.serverConsoleApiPrefix
- },
-}))
-
-vi.mock('@/next/headers', () => ({
- headers: () => mocks.headers(),
- cookies: () => mocks.cookies(),
-}))
-
-describe('server console oRPC client', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- vi.unstubAllGlobals()
- mocks.serverConsoleApiPrefix = undefined
- mocks.headers.mockResolvedValue(
- new Headers({ cookie: 'access_token=abc; csrf_token=csrf-token' }),
- )
- mocks.cookies.mockResolvedValue({
- get: vi.fn(() => ({ value: 'csrf-token' })),
- })
- })
-
- it('should resolve server console API URLs only from configured or absolute prefixes', async () => {
- const { resolveServerConsoleApiPrefix, resolveServerConsoleApiUrl } = await import('../server')
-
- expect(resolveServerConsoleApiPrefix(undefined, '/console/api')).toBeNull()
- expect(resolveServerConsoleApiUrl('/account/profile', undefined, '/console/api')).toBeNull()
- expect(
- resolveServerConsoleApiUrl(
- '/account/profile',
- 'https://api.example.com/console/api',
- '/console/api',
- ),
- ).toBe('https://api.example.com/console/api/account/profile')
- expect(
- resolveServerConsoleApiUrl(
- '/account/profile',
- undefined,
- 'https://public.example.com/console/api',
- ),
- ).toBe('https://public.example.com/console/api/account/profile')
- })
-
- it('should build per-request context from Next headers and cookies', async () => {
- const { getServerConsoleClientContext } = await import('../server')
-
- await expect(getServerConsoleClientContext()).resolves.toEqual({
- cookie: 'access_token=abc; csrf_token=csrf-token',
- csrfToken: 'csrf-token',
- })
- })
-
- it('should call contracts with forwarded cookies, csrf header, and no-store cache', async () => {
- const { createSystemFeaturesFixture } = await import('@/test/console/system-features')
- const fetchMock = vi.fn().mockResolvedValue(
- new Response(JSON.stringify(createSystemFeaturesFixture()), {
- status: 200,
- headers: {
- 'content-type': 'application/json',
- },
- }),
- )
- vi.stubGlobal('fetch', fetchMock)
- const { getServerConsoleClientContext, serverConsoleClient } = await import('../server')
-
- await serverConsoleClient.systemFeatures.get(undefined, {
- context: await getServerConsoleClientContext(),
- })
-
- expect(fetchMock).toHaveBeenCalledWith(
- expect.any(Request),
- expect.objectContaining({
- cache: 'no-store',
- redirect: 'manual',
- }),
- )
- const request = fetchMock.mock.calls[0]?.[0] as Request
- expect(request.url).toBe('http://localhost:5001/console/api/system-features')
- expect(request.method).toBe('GET')
- expect(request.headers.get('accept')).toBe('application/json')
- expect(request.headers.get('content-type')).toBeNull()
- expect(request.headers.get('cookie')).toBe('access_token=abc; csrf_token=csrf-token')
- expect(request.headers.get('X-CSRF-Token')).toBe('csrf-token')
- })
-})
diff --git a/web/service/__tests__/use-plugins.spec.tsx b/web/service/__tests__/use-plugins.spec.tsx
index 3dcec327f51..c6b64fdef43 100644
--- a/web/service/__tests__/use-plugins.spec.tsx
+++ b/web/service/__tests__/use-plugins.spec.tsx
@@ -19,7 +19,7 @@ import {
PluginSource,
TaskStatus,
} from '@/app/components/plugins/types'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { renderHook } from '@/test/console/render'
import {
normalizeInstalledPluginDetail,
diff --git a/web/service/__tests__/use-snippets.spec.tsx b/web/service/__tests__/use-snippets.spec.tsx
index e254874af9b..5bb85e260d7 100644
--- a/web/service/__tests__/use-snippets.spec.tsx
+++ b/web/service/__tests__/use-snippets.spec.tsx
@@ -6,7 +6,7 @@ import { useExportSnippetMutation } from '../use-snippets'
const mockExportSnippet = vi.hoisted(() => vi.fn())
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
workspaces: {
current: {
diff --git a/web/service/__tests__/use-tools.spec.tsx b/web/service/__tests__/use-tools.spec.tsx
index 3171aed78e1..35213ac72f0 100644
--- a/web/service/__tests__/use-tools.spec.tsx
+++ b/web/service/__tests__/use-tools.spec.tsx
@@ -17,7 +17,7 @@ vi.mock('@/service/base', () => ({
put: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
apps: {
byAppId: {
diff --git a/web/service/__tests__/use-triggers.spec.ts b/web/service/__tests__/use-triggers.spec.ts
index c43bd091667..b6757e7b821 100644
--- a/web/service/__tests__/use-triggers.spec.ts
+++ b/web/service/__tests__/use-triggers.spec.ts
@@ -15,7 +15,7 @@ const mocks = vi.hoisted(() => ({
verifyAndUpdate: vi.fn().mockResolvedValue({ verified: false }),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
workspaces: {
current: {
diff --git a/web/service/__tests__/use-workflow.spec.tsx b/web/service/__tests__/use-workflow.spec.tsx
index 9d37b902c40..3972dad07ce 100644
--- a/web/service/__tests__/use-workflow.spec.tsx
+++ b/web/service/__tests__/use-workflow.spec.tsx
@@ -20,8 +20,8 @@ import {
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { act, renderHook } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
-import { consoleQuery } from '../client'
import { useUpdateWorkflow } from '../use-workflow'
import {
appWorkflowQueryOptions,
diff --git a/web/service/access-control/__tests__/resource-access-config.spec.tsx b/web/service/access-control/__tests__/resource-access-config.spec.tsx
index f289aae76b4..3c65d43b89e 100644
--- a/web/service/access-control/__tests__/resource-access-config.spec.tsx
+++ b/web/service/access-control/__tests__/resource-access-config.spec.tsx
@@ -32,7 +32,7 @@ const mocks = vi.hoisted(() => ({
datasetWhitelistConfigQueryOptions: vi.fn(),
}))
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
workspaces: {
current: {
diff --git a/web/service/access-control/__tests__/use-app-access-control.spec.tsx b/web/service/access-control/__tests__/use-app-access-control.spec.tsx
index 7ec890fb130..44de672d270 100644
--- a/web/service/access-control/__tests__/use-app-access-control.spec.tsx
+++ b/web/service/access-control/__tests__/use-app-access-control.spec.tsx
@@ -24,8 +24,8 @@ vi.mock('@/service/share', () => ({
getUserCanAccess: vi.fn(),
}))
-vi.mock('@/service/client', async (importOriginal) => {
- const actual = await importOriginal()
+vi.mock('@/service/console', async (importOriginal) => {
+ const actual = await importOriginal()
return {
...actual,
consoleQuery: {
diff --git a/web/service/access-control/use-app-access-config.ts b/web/service/access-control/use-app-access-config.ts
index ca9b5f1b6df..ee134da5ff6 100644
--- a/web/service/access-control/use-app-access-config.ts
+++ b/web/service/access-control/use-app-access-config.ts
@@ -4,7 +4,7 @@ import type {
UpdateAppUserAccessSettingsRequest,
} from '@/models/access-control'
import { keepPreviousData, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { normalizeAppAccessMatrix, normalizeAppUserAccessPolicies } from './normalizers'
const NAME_SPACE = 'app-access-config'
diff --git a/web/service/access-control/use-app-access-control.ts b/web/service/access-control/use-app-access-control.ts
index 97d5e37c828..fb32a53e453 100644
--- a/web/service/access-control/use-app-access-control.ts
+++ b/web/service/access-control/use-app-access-control.ts
@@ -1,8 +1,8 @@
import type { AccessControlGroup, Subject } from '@/models/access-control'
import { useInfiniteQuery, useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
+import { consoleQuery } from '@/service/console'
import { get } from '../base'
-import { consoleQuery } from '../client'
import { getUserCanAccess } from '../share'
const NAME_SPACE = 'access-control'
diff --git a/web/service/access-control/use-dataset-access-config.ts b/web/service/access-control/use-dataset-access-config.ts
index d3bb990c8ac..2361a5fb776 100644
--- a/web/service/access-control/use-dataset-access-config.ts
+++ b/web/service/access-control/use-dataset-access-config.ts
@@ -4,7 +4,7 @@ import type {
UpdateDatasetUserAccessSettingsRequest,
} from '@/models/access-control'
import { keepPreviousData, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { normalizeDatasetAccessMatrix, normalizeDatasetUserAccessPolicies } from './normalizers'
const NAME_SPACE = 'dataset-access-config'
diff --git a/web/service/common.ts b/web/service/common.ts
index ba4cec521ae..5000f03a04b 100644
--- a/web/service/common.ts
+++ b/web/service/common.ts
@@ -335,6 +335,6 @@ export const getAvatar = async ({
}: {
avatar: string
}): Promise<{ avatar_url: string }> => {
- const { consoleClient } = await import('./client')
+ const { consoleClient } = await import('@/service/console')
return consoleClient.account.avatar.get({ query: { avatar } })
}
diff --git a/web/service/console-link.ts b/web/service/console-link.ts
deleted file mode 100644
index 388b80e3e5b..00000000000
--- a/web/service/console-link.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type { ClientContext, ClientLink } from '@orpc/client'
-import type { AnyContractRouter } from '@orpc/contract'
-import { DynamicLink } from '@orpc/client'
-import { loadConsoleContractForSegment } from './console-router-loader'
-
-export function createConsoleDynamicLink(
- createLink: (contract: AnyContractRouter) => ClientLink,
-) {
- const routerLinkPromises = new Map>>()
-
- function getRouterLink(path: readonly string[]) {
- const segment = path[0]
- if (!segment) throw new Error('Console contract path is empty.')
-
- let routerLinkPromise = routerLinkPromises.get(segment)
- if (!routerLinkPromise) {
- routerLinkPromise = loadConsoleContractForSegment(segment)
- .then(createLink)
- .catch((error) => {
- routerLinkPromises.delete(segment)
- throw error
- })
- routerLinkPromises.set(segment, routerLinkPromise)
- }
-
- return routerLinkPromise
- }
-
- return new DynamicLink((_options, path) => getRouterLink(path))
-}
diff --git a/web/service/console-openapi-url.ts b/web/service/console-openapi-url.ts
deleted file mode 100644
index 3aa2a708575..00000000000
--- a/web/service/console-openapi-url.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-type QueryArrayCompatibilityRule = {
- path: RegExp
- fields: readonly string[]
-}
-
-// Keep oRPC query-array compatibility at the console OpenAPI transport boundary instead of
-// making backend handlers accept multiple serialized forms. oRPC v2 supports custom query
-// parameter serialization, so this bridge can be removed once we configure repeated keys there.
-const repeatedQueryArrayRules: readonly QueryArrayCompatibilityRule[] = [
- { path: /\/agent$/, fields: ['tag_ids', 'creator_ids'] },
- { path: /\/agent\/[^/]+\/logs$/, fields: ['sources', 'statuses'] },
- { path: /\/agent\/[^/]+\/logs\/[^/]+\/messages$/, fields: ['sources', 'statuses'] },
- { path: /\/apps$/, fields: ['tag_ids', 'creator_ids'] },
- { path: /\/apps\/starred$/, fields: ['tag_ids', 'creator_ids'] },
- { path: /\/datasets$/, fields: ['ids', 'tag_ids'] },
- { path: /\/datasets\/[^/]+\/documents\/[^/]+\/segment\/[^/]+$/, fields: ['segment_id'] },
- { path: /\/datasets\/[^/]+\/documents\/[^/]+\/segments$/, fields: ['segment_id', 'status'] },
- { path: /\/trial-apps\/[^/]+\/datasets$/, fields: ['ids'] },
- { path: /\/workspaces\/current\/customized-snippets$/, fields: ['tag_ids', 'creators'] },
- { path: /\/workspaces\/current\/skills$/, fields: ['tag'] },
- { path: /\/workspaces\/current\/plugin\/[^/]+\/list$/, fields: ['tags'] },
- {
- path: /\/workspaces\/current\/tool-provider\/builtin\/[^/]+\/credential\/info$/,
- fields: ['include_credential_ids'],
- },
- {
- path: /\/workspaces\/current\/tool-provider\/builtin\/[^/]+\/credentials$/,
- fields: ['include_credential_ids'],
- },
-]
-
-const escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
-
-const getRepeatedQueryArrayFields = (pathname: string) =>
- repeatedQueryArrayRules.find((rule) => rule.path.test(pathname))?.fields ?? []
-
-const rewriteIndexedQueryArrayParam = (url: URL, field: string) => {
- const indexedParamPattern = new RegExp(`^${escapeRegExp(field)}\\[(\\d+)\\]$`)
- const values: Array<{ index: number; value: string }> = []
- const indexedKeys = new Set()
-
- url.searchParams.forEach((value, key) => {
- const match = indexedParamPattern.exec(key)
- if (!match) return
-
- indexedKeys.add(key)
- values.push({ index: Number(match[1]), value })
- })
-
- if (!values.length) return false
-
- indexedKeys.forEach((key) => url.searchParams.delete(key))
- values
- .sort((a, b) => a.index - b.index)
- .forEach(({ value }) => url.searchParams.append(field, value))
-
- return true
-}
-
-export function normalizeConsoleOpenAPIURL(url: string | URL) {
- const normalizedUrl = new URL(url)
- const repeatedQueryArrayFields = getRepeatedQueryArrayFields(normalizedUrl.pathname)
-
- if (!repeatedQueryArrayFields.length) return normalizedUrl.href
-
- repeatedQueryArrayFields.forEach((field) => rewriteIndexedQueryArrayParam(normalizedUrl, field))
-
- return normalizedUrl.href
-}
diff --git a/web/service/console-router-loader.ts b/web/service/console-router-loader.ts
deleted file mode 100644
index 7c7ca8ad164..00000000000
--- a/web/service/console-router-loader.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import type { AnyContractRouter } from '@orpc/contract'
-import { contractLoaders } from '@dify/contracts/api/console/orpc.gen'
-
-const generatedConsoleContractLoaders: Partial Promise>> =
- contractLoaders
-
-async function loadGeneratedConsoleContract(segment: string) {
- const loader = generatedConsoleContractLoaders[segment]
- if (!loader) return null
-
- return loader()
-}
-
-async function loadEnterpriseContract(): Promise {
- const [{ contract: enterpriseContract }, { contract: appDeployContract }] = await Promise.all([
- import('@dify/contracts/enterprise/orpc.gen'),
- import('@dify/contracts/enterprise-app-deploy/orpc.gen'),
- ])
-
- return {
- enterprise: {
- ...enterpriseContract,
- appDeploy: appDeployContract,
- },
- }
-}
-
-async function loadKnowledgeFsContract(): Promise {
- const { contract } = await import('@dify/contracts/knowledge-fs/orpc.gen')
- return { knowledgeFs: contract }
-}
-
-export async function loadConsoleContractForSegment(segment: string) {
- if (segment === 'enterprise') return loadEnterpriseContract()
- if (segment === 'knowledgeFs') return loadKnowledgeFsContract()
-
- const generatedContract = await loadGeneratedConsoleContract(segment)
- if (generatedContract) return generatedContract
-
- throw new Error(`Console contract segment "${segment}" is not configured.`)
-}
diff --git a/web/service/console/README.md b/web/service/console/README.md
new file mode 100644
index 00000000000..363cb02a1ad
--- /dev/null
+++ b/web/service/console/README.md
@@ -0,0 +1,26 @@
+# Console service
+
+Use `consoleClient` and `consoleQuery` from `@/service/console`
+in Server and Client Components. Calls use the appropriate HTTP
+transport for the Python Console API.
+
+- [Browser transport] preserves the existing request
+ layer's authentication and error handling.
+- [Server transport] requires an absolute API address;
+ see [server configuration].
+ [Instrumentation] and the [root layout]
+ register this transport. Only the transport is shared globally;
+ request identity is resolved per request.
+- Shared query/mutation defaults live in
+ [query-policies.ts].
+ In oRPC v1, caller options override defaults, including callbacks.
+- Routes/layouts own prefetching and hydration. Use the existing
+ [QueryClient factory].
+
+[Browser transport]: ./browser.ts
+[Instrumentation]: ../../instrumentation.ts
+[QueryClient factory]: ../../app/get-query-client.ts
+[Server transport]: ./server.ts
+[query-policies.ts]: ./query-policies.ts
+[root layout]: ../../app/layout.tsx
+[server configuration]: ../../config/server.ts
diff --git a/web/service/console/browser.ts b/web/service/console/browser.ts
new file mode 100644
index 00000000000..dcd964339f6
--- /dev/null
+++ b/web/service/console/browser.ts
@@ -0,0 +1,30 @@
+import type { ClientLink } from '@orpc/client'
+import type { AnyContractRouter } from '@orpc/contract'
+import type { ConsoleClientContext } from './index'
+import { onError } from '@orpc/client'
+import { OpenAPILink } from '@orpc/openapi-client/fetch'
+import { API_PREFIX } from '@/config'
+// oxlint-disable-next-line no-restricted-imports -- The Console HTTP adapter must preserve existing auth refresh, CSRF, and error handling.
+import { request } from '../base'
+import { createConsoleContractLink } from './contract-loader'
+import { normalizeConsoleOpenAPIURL } from './openapi-url'
+
+function createBrowserLink(contract: AnyContractRouter): ClientLink {
+ return new OpenAPILink(contract, {
+ url: () => new URL(API_PREFIX, window.location.origin),
+ fetch: (input, init, options) => {
+ const requestInit = options.context.keepalive ? { ...init, keepalive: true } : init
+ const normalizedURL = normalizeConsoleOpenAPIURL(input.url)
+ const normalizedRequest =
+ normalizedURL === input.url ? input : new Request(normalizedURL, input)
+ return request(normalizedURL, requestInit, {
+ fetchCompat: true,
+ request: normalizedRequest,
+ silent: options.context.silent,
+ })
+ },
+ interceptors: [onError((error) => console.error(error))],
+ })
+}
+
+export const consoleBrowserLink = createConsoleContractLink(createBrowserLink)
diff --git a/web/service/client.spec.ts b/web/service/console/client.spec.ts
similarity index 78%
rename from web/service/client.spec.ts
rename to web/service/console/client.spec.ts
index a3de7a87198..8dedf8a1409 100644
--- a/web/service/client.spec.ts
+++ b/web/service/console/client.spec.ts
@@ -1,60 +1,36 @@
import type { ApiBasedExtensionResponse } from '@dify/contracts/api/console/api-based-extension/types.gen'
import type { AppDetail, AppSiteResponse } from '@dify/contracts/api/console/apps/types.gen'
import type { TagResponse as Tag } from '@dify/contracts/api/console/tags/types.gen'
-import type { EnvironmentDeployment } from '@dify/contracts/enterprise-app-deploy/types.gen'
import type { DocumentProcessingTaskEvent } from '@dify/contracts/knowledge-fs/types.gen'
import type { MutationFunctionContext, QueryFunctionContext } from '@tanstack/react-query'
-import type { consoleQuery as ConsoleQuery } from './client'
-import { QueryClient } from '@tanstack/react-query'
+import type { consoleQuery as ConsoleQuery } from '@/service/console'
+import { MutationObserver, QueryClient, QueryObserver } from '@tanstack/react-query'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test'
-import { normalizeConsoleOpenAPIURL } from './console-openapi-url'
-
-const loadGetBaseURL = async (isClientValue: boolean) => {
- vi.resetModules()
- vi.doMock('@/utils/client', () => ({ isClient: isClientValue, isServer: !isClientValue }))
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
- const module = await import('./client')
- warnSpy.mockClear()
- return { getBaseURL: module.getBaseURL, warnSpy }
-}
+import { normalizeConsoleOpenAPIURL } from './openapi-url'
const loadConsoleQuery = async () => {
vi.resetModules()
vi.doMock('@/utils/client', () => ({ isClient: true, isServer: false }))
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
- const module = await import('./client')
- warnSpy.mockRestore()
+ const module = await import('@/service/console')
return module.consoleQuery
}
const loadConsoleQueryWithRequest = async (request: ReturnType) => {
vi.resetModules()
vi.doMock('@/utils/client', () => ({ isClient: true, isServer: false }))
- vi.doMock('./base', () => ({ request }))
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
- const module = await import('./client')
- warnSpy.mockRestore()
+ vi.doMock('../base', () => ({ request }))
+ const module = await import('@/service/console')
return module.consoleQuery
}
const loadConsoleQueryWithFetch = async () => {
vi.resetModules()
- vi.doUnmock('./base')
+ vi.doUnmock('../base')
vi.doMock('@/utils/client', () => ({ isClient: true, isServer: false }))
- const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
- const module = await import('./client')
- warnSpy.mockRestore()
+ const module = await import('@/service/console')
return module.consoleQuery
}
-const loadWorkflowGenerationStream = async (sseGeneratorPost: ReturnType) => {
- vi.resetModules()
- vi.doMock('@/utils/client', () => ({ isClient: true, isServer: false }))
- vi.doMock('./base', () => ({ request: vi.fn(), sseGeneratorPost }))
- const module = await import('./client')
- return module.streamWorkflowGeneration
-}
-
const createMutationContext = (queryClient: QueryClient): MutationFunctionContext => ({
client: queryClient,
meta: undefined,
@@ -217,92 +193,6 @@ const createWorkflowComposerState = (
})
// Scenario: base URL selection and warnings.
-describe('getBaseURL', () => {
- beforeEach(() => {
- vi.clearAllMocks()
- })
-
- afterEach(() => {
- vi.restoreAllMocks()
- })
-
- // Scenario: client environment uses window origin.
- it('should use window origin when running on the client', async () => {
- // Arrange
- const { origin } = window.location
- const { getBaseURL, warnSpy } = await loadGetBaseURL(true)
-
- // Act
- const url = getBaseURL('/api')
-
- // Assert
- expect(url.href).toBe(`${origin}/api`)
- expect(warnSpy).not.toHaveBeenCalled()
- })
-
- // Scenario: server environment falls back to localhost with warning.
- it('should fall back to localhost and warn on the server', async () => {
- // Arrange
- const { getBaseURL, warnSpy } = await loadGetBaseURL(false)
-
- // Act
- const url = getBaseURL('/api')
-
- // Assert
- expect(url.href).toBe('http://localhost/api')
- expect(warnSpy).toHaveBeenCalledTimes(1)
- expect(warnSpy).toHaveBeenCalledWith(
- 'Using localhost as base URL in server environment, please configure accordingly.',
- )
- })
-
- // Scenario: non-http protocols surface warnings.
- it('should warn when protocol is not http or https', async () => {
- // Arrange
- const { getBaseURL, warnSpy } = await loadGetBaseURL(true)
-
- // Act
- const url = getBaseURL('localhost:5001/console/api')
-
- // Assert
- expect(url.protocol).toBe('localhost:')
- expect(url.href).toBe('localhost:5001/console/api')
- expect(warnSpy).toHaveBeenCalledTimes(1)
- expect(warnSpy).toHaveBeenCalledWith(
- 'Unexpected protocol for API requests, expected http or https. Current protocol: localhost:. Please configure accordingly.',
- )
- })
-
- // Scenario: absolute http URLs are preserved.
- it('should keep absolute http URLs intact', async () => {
- // Arrange
- const { getBaseURL, warnSpy } = await loadGetBaseURL(true)
-
- // Act
- const url = getBaseURL('https://api.example.com/console/api')
-
- // Assert
- expect(url.href).toBe('https://api.example.com/console/api')
- expect(warnSpy).not.toHaveBeenCalled()
- })
-})
-
-describe('streamWorkflowGeneration', () => {
- it('should preserve the generator stream transport contract', async () => {
- const expectedResult = Promise.resolve()
- const sseGeneratorPost = vi.fn().mockReturnValue(expectedResult)
- const streamWorkflowGeneration = await loadWorkflowGenerationStream(sseGeneratorPost)
- const body = { instruction: 'Build a researched answer' }
- const callbacks = { onCompleted: vi.fn() }
-
- const result = streamWorkflowGeneration('/workflow-generate/stream', body, callbacks)
-
- expect(result).toBe(expectedResult)
- expect(sseGeneratorPost).toHaveBeenCalledWith('/workflow-generate/stream', body, callbacks)
- })
-})
-
-// Scenario: oRPC operation context controls transport behavior without handwritten REST helpers.
describe('consoleQuery transport context', () => {
afterEach(() => {
vi.restoreAllMocks()
@@ -1620,346 +1510,248 @@ describe('consoleQuery Web app access mutation defaults', () => {
})
})
-describe('consoleQuery App Instance mutation defaults', () => {
- afterEach(() => {
- vi.restoreAllMocks()
- })
-
- it('should bypass a fresh list cache while waiting for a created app instance', async () => {
- const appInstance = {
- id: 'app-instance-1',
- tenantId: 'tenant-1',
- displayName: 'Production App',
- description: '',
- createdBy: { id: 'user-1', displayName: 'Ada' },
- updatedBy: { id: 'user-1', displayName: 'Ada' },
- createdAt: '2026-09-03T00:00:00Z',
- updatedAt: '2026-09-03T00:00:00Z',
- }
- const request = vi
- .fn()
- .mockResolvedValueOnce(
- new Response(JSON.stringify({ appInstances: [], pagination: {} }), {
- status: 200,
- headers: { 'content-type': 'application/json' },
- }),
- )
- .mockResolvedValueOnce(
- new Response(JSON.stringify({ appInstances: [appInstance], pagination: {} }), {
- status: 200,
- headers: { 'content-type': 'application/json' },
- }),
- )
- const consoleQuery = await loadConsoleQueryWithRequest(request)
- const queryClient = new QueryClient({
- defaultOptions: {
- queries: { retry: false, staleTime: Infinity },
- },
- })
- const listInput = {
- query: {
- pageNumber: 1,
- resultsPerPage: 100,
- },
- }
- const listOptions = consoleQuery.enterprise.appInstanceService.listAppInstances.queryOptions({
- input: listInput,
- })
- queryClient.setQueryData(listOptions.queryKey, {
- appInstances: [],
- pagination: {},
- })
-
- const onSuccess =
- consoleQuery.enterprise.appInstanceService.createAppInstance.mutationOptions().onSuccess
- const completion = onSuccess?.(
- { appInstance },
- { body: { displayName: appInstance.displayName } },
- undefined,
- createMutationContext(queryClient),
- )
- await completion
-
- expect(request).toHaveBeenCalledTimes(2)
- })
-})
-
-// Scenario: legacy App Deploy mutations share cache behavior through oRPC defaults.
-describe('consoleQuery App Deploy mutation defaults', () => {
- afterEach(() => {
- vi.restoreAllMocks()
- })
-
- it('should synchronize environment access details and deployment summaries after toggles', async () => {
- const consoleQuery = await loadConsoleQuery()
- const queryClient = new QueryClient()
- const invalidateQueries = vi.spyOn(queryClient, 'invalidateQueries')
- const params = {
- app_id: 'app-1',
- environment_id: 'staging',
- }
- const siteQuery =
- consoleQuery.enterprise.appDeploy.accessService.getEnvironmentSite.queryOptions({
- input: { params },
+describe('consoleQuery App Deploy cache behavior', () => {
+ it.each([
+ ['api', 'active'],
+ ['site', 'active'],
+ ['api', 'reopened'],
+ ['site', 'reopened'],
+ ] as const)(
+ 'keeps the saved %s switch in %s deployment reads when refreshing fails',
+ async (accessPoint, view) => {
+ const consoleQuery = await loadConsoleQuery()
+ const client = new QueryClient({
+ defaultOptions: { queries: { staleTime: Infinity, retry: false } },
})
- const apiQuery = consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions(
- {
- input: { params },
- },
- )
- const deploymentsQuery =
- consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- },
+ const params = { app_id: 'app-1', environment_id: 'staging' }
+ const staging = {
+ environment: {
+ id: 'staging',
+ display_name: 'Staging',
+ description: '',
+ status: 'ENVIRONMENT_STATUS_READY' as const,
+ },
+ access: { enable_api: true, enable_site: true },
+ }
+ const production = { ...staging, environment: { ...staging.environment, id: 'production' } }
+ const deployments = consoleQuery.enterprise.appDeploy.deploymentService
+ const list = deployments.listEnvironmentDeployments.queryOptions({
+ input: { params: { app_id: params.app_id } },
+ queryFn: async () => {
+ throw new Error('Deployment list unavailable')
},
})
- const deploymentQuery =
- consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions({
+ const detail = deployments.getEnvironmentDeployment.queryOptions({
input: { params },
+ queryFn: async () => {
+ throw new Error('Deployment detail unavailable')
+ },
})
- const stagingDeployment: EnvironmentDeployment = {
- access: {
- enable_api: false,
- enable_site: false,
- },
- environment: {
- description: 'Staging environment',
+ const otherApp = deployments.listEnvironmentDeployments.queryOptions({
+ input: { params: { app_id: 'app-2' } },
+ })
+ const otherEnvironment = deployments.getEnvironmentDeployment.queryOptions({
+ input: { params: { ...params, environment_id: 'production' } },
+ })
+ client.setQueryData(list.queryKey, { environment_deployments: [staging, production] })
+ client.setQueryData(detail.queryKey, { environment_deployment: staging })
+ client.setQueryData(otherApp.queryKey, { environment_deployments: [staging] })
+ client.setQueryData(otherEnvironment.queryKey, { environment_deployment: production })
+ const listObserver = new QueryObserver(client, list)
+ const detailObserver = new QueryObserver(client, detail)
+ const unsubscribe =
+ view === 'active'
+ ? [listObserver.subscribe(() => {}), detailObserver.subscribe(() => {})]
+ : []
+
+ try {
+ const access = consoleQuery.enterprise.appDeploy.accessService
+ if (accessPoint === 'api') {
+ const saved = { enabled: false, base_url: 'https://api.example.com/v1', api_key_count: 1 }
+ await new MutationObserver(
+ client,
+ access.updateEnvironmentApi.mutationOptions({
+ mutationFn: async () => saved,
+ }),
+ ).mutate({ params, body: { enabled: false } })
+ expect(
+ client.getQueryData(
+ access.getEnvironmentApi.queryOptions({ input: { params } }).queryKey,
+ ),
+ ).toEqual(saved)
+ } else {
+ const saved = {
+ enabled: false,
+ code: 'site-1',
+ app_base_url: 'https://app.example.com',
+ access_mode: 'public',
+ }
+ await new MutationObserver(
+ client,
+ access.updateEnvironmentSite.mutationOptions({
+ mutationFn: async () => saved,
+ }),
+ ).mutate({ params, body: { enabled: false } })
+ expect(
+ client.getQueryData(
+ access.getEnvironmentSite.queryOptions({ input: { params } }).queryKey,
+ ),
+ ).toEqual(saved)
+ }
+
+ if (view === 'reopened') {
+ unsubscribe.push(
+ listObserver.subscribe(() => {}),
+ detailObserver.subscribe(() => {}),
+ )
+ await Promise.all([
+ listObserver.refetch({ cancelRefetch: false }),
+ detailObserver.refetch({ cancelRefetch: false }),
+ ])
+ }
+
+ const savedDeployment = {
+ ...staging,
+ access: { enable_api: accessPoint !== 'api', enable_site: accessPoint !== 'site' },
+ }
+ expect(listObserver.getCurrentResult()).toMatchObject({
+ isRefetchError: true,
+ data: { environment_deployments: [savedDeployment, production] },
+ })
+ expect(detailObserver.getCurrentResult()).toMatchObject({
+ isRefetchError: true,
+ data: { environment_deployment: savedDeployment },
+ })
+ expect(client.getQueryData(otherApp.queryKey)).toEqual({
+ environment_deployments: [staging],
+ })
+ expect(client.getQueryData(otherEnvironment.queryKey)).toEqual({
+ environment_deployment: production,
+ })
+ } finally {
+ unsubscribe.forEach((stop) => stop())
+ client.clear()
+ }
+ },
+ )
+
+ it.each(['create', 'delete'] as const)(
+ 'refreshes environment keys and their count after %s',
+ async (action) => {
+ const consoleQuery = await loadConsoleQuery()
+ const client = new QueryClient({ defaultOptions: { queries: { staleTime: Infinity } } })
+ const params = { app_id: 'app-1', environment_id: 'staging' }
+ const key = { created_at: 1, id: 'key-1', token: 'secret', type: 'api' }
+ let keys = action === 'create' ? [] : [key]
+ const list = {
+ ...consoleQuery.enterprise.appDeploy.accessService.listEnvironmentApiKeys.queryOptions({
+ input: { params },
+ }),
+ queryFn: async () => ({ data: keys }),
+ }
+ const summary = {
+ ...consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions({
+ input: { params },
+ }),
+ queryFn: async () => ({
+ enabled: true,
+ base_url: 'https://api.example.com/v1',
+ api_key_count: keys.length,
+ }),
+ }
+ await Promise.all([client.query(list), client.query(summary)])
+
+ if (action === 'create') {
+ const mutation = new MutationObserver(client, {
+ ...consoleQuery.enterprise.appDeploy.accessService.createEnvironmentApiKey.mutationOptions(),
+ mutationFn: async () => {
+ keys = [key]
+ return key
+ },
+ })
+ await mutation.mutate({ params })
+ } else {
+ const mutation = new MutationObserver(client, {
+ ...consoleQuery.enterprise.appDeploy.accessService.deleteEnvironmentApiKey.mutationOptions(),
+ mutationFn: async () => {
+ keys = []
+ return {}
+ },
+ })
+ await mutation.mutate({ params: { ...params, api_key_id: key.id } })
+ }
+
+ expect((await client.query(list)).data).toEqual(keys)
+ expect((await client.query(summary)).api_key_count).toBe(keys.length)
+ },
+ )
+
+ it.each(['deploy', 'undeploy'] as const)(
+ 'refreshes deployment reads after %s',
+ async (action) => {
+ const consoleQuery = await loadConsoleQuery()
+ const client = new QueryClient({ defaultOptions: { queries: { staleTime: Infinity } } })
+ const params = { app_id: 'app-1', environment_id: 'staging', workflow_id: 'workflow-1' }
+ const environment = {
+ id: 'staging',
display_name: 'Staging',
- id: params.environment_id,
- status: 'ENVIRONMENT_STATUS_READY',
- },
- }
- const productionDeployment: EnvironmentDeployment = {
- access: {
- enable_api: false,
- enable_site: false,
- },
- environment: {
- description: 'Production environment',
- display_name: 'Production',
- id: 'production',
- status: 'ENVIRONMENT_STATUS_READY',
- },
- }
- const updatedSite = {
- access_mode: 'private',
- app_base_url: 'https://site.example.test',
- code: 'staging-code',
- enabled: true,
- }
- const updatedApi = {
- api_key_count: 2,
- base_url: 'https://api.example.test/v1',
- enabled: true,
- }
-
- queryClient.setQueryData(siteQuery.queryKey, { ...updatedSite, enabled: false })
- queryClient.setQueryData(apiQuery.queryKey, { ...updatedApi, enabled: false })
- queryClient.setQueryData(deploymentsQuery.queryKey, {
- environment_deployments: [stagingDeployment, productionDeployment],
- })
- queryClient.setQueryData(deploymentQuery.queryKey, {
- environment_deployment: stagingDeployment,
- })
-
- const siteMutation =
- consoleQuery.enterprise.appDeploy.accessService.updateEnvironmentSite.mutationOptions()
- await siteMutation.onSuccess?.(
- updatedSite,
- { body: { enabled: true }, params },
- undefined,
- createMutationContext(queryClient),
- )
-
- expect(queryClient.getQueryData(siteQuery.queryKey)).toEqual(updatedSite)
- expect(queryClient.getQueryData(deploymentsQuery.queryKey)).toEqual({
- environment_deployments: [
- {
- ...stagingDeployment,
- access: {
- enable_api: false,
- enable_site: true,
- },
- },
- productionDeployment,
- ],
- })
- expect(queryClient.getQueryData(deploymentQuery.queryKey)).toEqual({
- environment_deployment: {
- ...stagingDeployment,
- access: {
- enable_api: false,
- enable_site: true,
- },
- },
- })
-
- const apiMutation =
- consoleQuery.enterprise.appDeploy.accessService.updateEnvironmentApi.mutationOptions()
- await apiMutation.onSuccess?.(
- updatedApi,
- { body: { enabled: true }, params },
- undefined,
- createMutationContext(queryClient),
- )
-
- expect(queryClient.getQueryData(apiQuery.queryKey)).toEqual(updatedApi)
- expect(queryClient.getQueryData(deploymentsQuery.queryKey)).toEqual({
- environment_deployments: [
- {
- ...stagingDeployment,
- access: {
- enable_api: true,
- enable_site: true,
- },
- },
- productionDeployment,
- ],
- })
- expect(queryClient.getQueryData(deploymentQuery.queryKey)).toEqual({
- environment_deployment: {
- ...stagingDeployment,
- access: {
- enable_api: true,
- enable_site: true,
- },
- },
- })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentsQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledTimes(4)
- })
-
- it('should invalidate the environment key list and API summary after creating or deleting a key', async () => {
- const consoleQuery = await loadConsoleQuery()
- const queryClient = new QueryClient()
- const invalidateQueries = vi.spyOn(queryClient, 'invalidateQueries')
- const params = {
- app_id: 'app-1',
- environment_id: 'staging',
- }
- const listQuery =
- consoleQuery.enterprise.appDeploy.accessService.listEnvironmentApiKeys.queryOptions({
- input: { params },
- })
- const apiQuery = consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions(
- {
- input: { params },
- },
- )
-
- const createOptions =
- consoleQuery.enterprise.appDeploy.accessService.createEnvironmentApiKey.mutationOptions()
- await createOptions.onSuccess?.(
- {
- created_at: 1,
- id: 'key-1',
- token: 'secret',
- type: 'api',
- },
- { params },
- undefined,
- createMutationContext(queryClient),
- )
-
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: listQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: apiQuery.queryKey })
-
- invalidateQueries.mockClear()
- const deleteOptions =
- consoleQuery.enterprise.appDeploy.accessService.deleteEnvironmentApiKey.mutationOptions()
- await deleteOptions.onSuccess?.(
- {},
- {
- params: {
- ...params,
- api_key_id: 'key-1',
- },
- },
- undefined,
- createMutationContext(queryClient),
- )
-
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: listQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: apiQuery.queryKey })
- })
-
- it('should keep deploy and undeploy cache invalidation aligned', async () => {
- const consoleQuery = await loadConsoleQuery()
- const queryClient = new QueryClient()
- const invalidateQueries = vi.spyOn(queryClient, 'invalidateQueries')
- const params = {
- app_id: 'app-1',
- environment_id: 'staging',
- workflow_id: 'workflow-1',
- }
- const appEnvironmentsQuery =
- consoleQuery.enterprise.appDeploy.deploymentService.listAppEnvironments.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- },
- },
- })
- const deploymentsQuery =
- consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- },
- },
- })
- const deploymentQuery =
- consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- environment_id: params.environment_id,
- },
- },
- })
- const response = {
- operation: {
- id: 'operation-1',
- status: 'DEPLOYMENT_OPERATION_STATUS_IN_PROGRESS' as const,
- type: 'DEPLOYMENT_OPERATION_TYPE_DEPLOY' as const,
- },
- }
-
- const deployOptions =
- consoleQuery.enterprise.appDeploy.deploymentService.deployWorkflow.mutationOptions()
- await deployOptions.onSuccess?.(
- response,
- { body: { environment_variable_groups: [] }, params },
- undefined,
- createMutationContext(queryClient),
- )
-
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentsQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentQuery.queryKey })
- expect(invalidateQueries).not.toHaveBeenCalledWith({ queryKey: appEnvironmentsQuery.queryKey })
-
- invalidateQueries.mockClear()
- const undeployOptions =
- consoleQuery.enterprise.appDeploy.deploymentService.undeployWorkflow.mutationOptions()
- await undeployOptions.onSuccess?.(
- {
+ description: '',
+ status: 'ENVIRONMENT_STATUS_READY' as const,
+ }
+ const deployment = { environment, access: { enable_api: true, enable_site: true } }
+ const readList = vi.fn(async () => ({ environment_deployments: [deployment] }))
+ const readDetail = vi.fn(async () => ({ environment_deployment: deployment }))
+ const readEnvironments = vi.fn(async () => ({ data: [environment] }))
+ const list = {
+ ...consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions(
+ { input: { params: { app_id: params.app_id } } },
+ ),
+ queryFn: readList,
+ }
+ const detail = {
+ ...consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions(
+ { input: { params: { app_id: params.app_id, environment_id: params.environment_id } } },
+ ),
+ queryFn: readDetail,
+ }
+ const environments = {
+ ...consoleQuery.enterprise.appDeploy.deploymentService.listAppEnvironments.queryOptions({
+ input: { params: { app_id: params.app_id } },
+ }),
+ queryFn: readEnvironments,
+ }
+ await Promise.all([client.query(list), client.query(detail), client.query(environments)])
+ const response = {
operation: {
- ...response.operation,
- type: 'DEPLOYMENT_OPERATION_TYPE_UNDEPLOY',
+ id: 'operation-1',
+ status: 'DEPLOYMENT_OPERATION_STATUS_IN_PROGRESS' as const,
+ type: 'DEPLOYMENT_OPERATION_TYPE_DEPLOY' as const,
},
- },
- { params },
- undefined,
- createMutationContext(queryClient),
- )
+ }
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentsQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: deploymentQuery.queryKey })
- expect(invalidateQueries).toHaveBeenCalledWith({ queryKey: appEnvironmentsQuery.queryKey })
- })
+ if (action === 'deploy') {
+ await new MutationObserver(client, {
+ ...consoleQuery.enterprise.appDeploy.deploymentService.deployWorkflow.mutationOptions(),
+ mutationFn: async () => response,
+ }).mutate({ params, body: { environment_variable_groups: [] } })
+ } else {
+ await new MutationObserver(client, {
+ ...consoleQuery.enterprise.appDeploy.deploymentService.undeployWorkflow.mutationOptions(),
+ mutationFn: async () => ({
+ operation: {
+ ...response.operation,
+ type: 'DEPLOYMENT_OPERATION_TYPE_UNDEPLOY' as const,
+ },
+ }),
+ }).mutate({ params })
+ }
+
+ await Promise.all([client.query(list), client.query(detail), client.query(environments)])
+ expect(readList).toHaveBeenCalledTimes(2)
+ expect(readDetail).toHaveBeenCalledTimes(2)
+ expect(readEnvironments).toHaveBeenCalledTimes(action === 'undeploy' ? 2 : 1)
+ },
+ )
})
// Scenario: oRPC mutation defaults own shared tag cache behavior.
diff --git a/web/service/console/contract-loader.ts b/web/service/console/contract-loader.ts
new file mode 100644
index 00000000000..07ffcb26360
--- /dev/null
+++ b/web/service/console/contract-loader.ts
@@ -0,0 +1,50 @@
+import type { ClientContext, ClientLink } from '@orpc/client'
+import type { AnyContractRouter } from '@orpc/contract'
+import { contractLoaders } from '@dify/contracts/api/console/orpc.gen'
+import { DynamicLink } from '@orpc/client'
+
+const generatedConsoleContractLoaders: Partial Promise>> =
+ contractLoaders
+
+async function loadConsoleContractForSegment(segment: string): Promise {
+ if (segment === 'enterprise') {
+ const [{ contract: enterpriseContract }, { contract: appDeployContract }] = await Promise.all([
+ import('@dify/contracts/enterprise/orpc.gen'),
+ import('@dify/contracts/enterprise-app-deploy/orpc.gen'),
+ ])
+ return { enterprise: { ...enterpriseContract, appDeploy: appDeployContract } }
+ }
+ if (segment === 'knowledgeFs') {
+ const { contract } = await import('@dify/contracts/knowledge-fs/orpc.gen')
+ return { knowledgeFs: contract }
+ }
+ const loader = generatedConsoleContractLoaders[segment]
+ if (!loader) throw new Error(`Console contract segment "${segment}" is not configured.`)
+ return loader()
+}
+
+export function createConsoleContractLink(
+ createLink: (contract: AnyContractRouter) => ClientLink,
+) {
+ const routerLinkPromises = new Map>>()
+
+ function getRouterLink(path: readonly string[]) {
+ const segment = path[0]
+ if (!segment) throw new Error('Console contract path is empty.')
+
+ let routerLinkPromise = routerLinkPromises.get(segment)
+ if (!routerLinkPromise) {
+ routerLinkPromise = loadConsoleContractForSegment(segment)
+ .then(createLink)
+ .catch((error) => {
+ routerLinkPromises.delete(segment)
+ throw error
+ })
+ routerLinkPromises.set(segment, routerLinkPromise)
+ }
+
+ return routerLinkPromise
+ }
+
+ return new DynamicLink((_options, path) => getRouterLink(path))
+}
diff --git a/web/service/console/hydration.spec.tsx b/web/service/console/hydration.spec.tsx
new file mode 100644
index 00000000000..f8f2d4b4eda
--- /dev/null
+++ b/web/service/console/hydration.spec.tsx
@@ -0,0 +1,86 @@
+// @vitest-environment node
+
+import type { DehydratedState } from '@tanstack/react-query'
+import { Buffer } from 'node:buffer'
+import { PassThrough } from 'node:stream'
+import {
+ dehydrate,
+ HydrationBoundary,
+ QueryClientProvider,
+ useSuspenseQuery,
+} from '@tanstack/react-query'
+import { Suspense } from 'react'
+import { renderToPipeableStream } from 'react-dom/server'
+import { afterEach, describe, expect, it, vi } from 'vite-plus/test'
+import { getQueryClient } from '@/app/get-query-client'
+import { consoleQuery } from '@/service/console'
+import { createSystemFeaturesFixture } from '@/test/console/system-features'
+import './server'
+
+vi.mock('server-only', () => ({}))
+vi.mock('@/config', () => ({
+ API_PREFIX: '/console/api',
+ CSRF_COOKIE_NAME: () => 'csrf_token',
+ CSRF_HEADER_NAME: 'X-CSRF-Token',
+}))
+vi.mock('@/config/server', () => ({
+ SERVER_CONSOLE_API_PREFIX: 'https://internal.example/console/api',
+}))
+vi.mock('@/next/headers', () => ({
+ headers: async () => new Headers(),
+ cookies: async () => ({ get: () => undefined }),
+}))
+
+const options = () => consoleQuery.systemFeatures.get.queryOptions()
+
+function Consumer() {
+ const { data } = useSuspenseQuery(options())
+ return {data.deployment_edition}
+}
+
+function render(queryClient: ReturnType, state: DehydratedState) {
+ return new Promise((resolve, reject) => {
+ const output = new PassThrough()
+ const chunks: Buffer[] = []
+ output.on('data', (chunk) => chunks.push(chunk))
+ output.on('end', () => resolve(Buffer.concat(chunks).toString()))
+ const stream = renderToPipeableStream(
+
+
+ Loading
}>
+
+
+
+ ,
+ {
+ onAllReady() {
+ stream.pipe(output)
+ },
+ onError: reject,
+ },
+ )
+ })
+}
+
+afterEach(() => vi.unstubAllGlobals())
+
+describe('Console Suspense hydration contract', () => {
+ it('renders a prefetched Suspense result without requesting it again', async () => {
+ let resolveResponse!: (response: Response) => void
+ const response = new Promise((resolve) => {
+ resolveResponse = resolve
+ })
+ const fetch = vi.fn(() => response)
+ vi.stubGlobal('fetch', fetch)
+ const preloadClient = getQueryClient()
+ const pending = preloadClient.query(options())
+ const state = dehydrate(preloadClient)
+ const html = render(getQueryClient(), state)
+ const data = createSystemFeaturesFixture()
+ resolveResponse(Response.json(data))
+
+ await expect(html).resolves.toContain(data.deployment_edition)
+ await pending
+ expect(fetch).toHaveBeenCalledTimes(1)
+ })
+})
diff --git a/web/service/console/index.ts b/web/service/console/index.ts
new file mode 100644
index 00000000000..47f37098f93
--- /dev/null
+++ b/web/service/console/index.ts
@@ -0,0 +1,35 @@
+import type { consoleRouterContract } from '@dify/contracts/console'
+import type { ClientLink } from '@orpc/client'
+import type { ContractRouterClient } from '@orpc/contract'
+import type { JsonifiedClient } from '@orpc/openapi-client'
+import type { TanstackQueryOperationContext } from '@orpc/tanstack-query'
+import { createORPCClient, DynamicLink } from '@orpc/client'
+import { consoleBrowserLink } from './browser'
+import { createConsoleQuery } from './query-policies'
+
+export type ConsoleClientContext = TanstackQueryOperationContext & {
+ keepalive?: boolean
+ silent?: boolean
+}
+
+export type ConsoleClient = JsonifiedClient<
+ ContractRouterClient
+>
+
+declare global {
+ var $consoleServerLink: ClientLink | undefined
+}
+
+const consoleLink = new DynamicLink(() => {
+ if (typeof window === 'undefined') {
+ if (!globalThis.$consoleServerLink)
+ throw new Error(
+ 'Console server transport is not registered. Import @/service/console/server at the server entrypoint.',
+ )
+ return globalThis.$consoleServerLink
+ }
+ return consoleBrowserLink
+})
+
+export const consoleClient: ConsoleClient = createORPCClient(consoleLink)
+export const consoleQuery = createConsoleQuery(consoleClient)
diff --git a/web/service/console/openapi-url.ts b/web/service/console/openapi-url.ts
new file mode 100644
index 00000000000..6ab094868a5
--- /dev/null
+++ b/web/service/console/openapi-url.ts
@@ -0,0 +1,47 @@
+// These Python endpoints expect repeated keys; oRPC v1 serializes arrays with indexed keys.
+const repeatedQueryArrayRules = [
+ { path: /\/agent$/, fields: ['tag_ids', 'creator_ids'] },
+ { path: /\/agent\/[^/]+\/logs$/, fields: ['sources', 'statuses'] },
+ { path: /\/agent\/[^/]+\/logs\/[^/]+\/messages$/, fields: ['sources', 'statuses'] },
+ { path: /\/apps$/, fields: ['tag_ids', 'creator_ids'] },
+ { path: /\/apps\/starred$/, fields: ['tag_ids', 'creator_ids'] },
+ { path: /\/datasets$/, fields: ['ids', 'tag_ids'] },
+ { path: /\/datasets\/[^/]+\/documents\/[^/]+\/segment\/[^/]+$/, fields: ['segment_id'] },
+ { path: /\/datasets\/[^/]+\/documents\/[^/]+\/segments$/, fields: ['segment_id', 'status'] },
+ { path: /\/trial-apps\/[^/]+\/datasets$/, fields: ['ids'] },
+ { path: /\/workspaces\/current\/customized-snippets$/, fields: ['tag_ids', 'creators'] },
+ { path: /\/workspaces\/current\/skills$/, fields: ['tag'] },
+ { path: /\/workspaces\/current\/plugin\/[^/]+\/list$/, fields: ['tags'] },
+ {
+ path: /\/workspaces\/current\/tool-provider\/builtin\/[^/]+\/credential\/info$/,
+ fields: ['include_credential_ids'],
+ },
+ {
+ path: /\/workspaces\/current\/tool-provider\/builtin\/[^/]+\/credentials$/,
+ fields: ['include_credential_ids'],
+ },
+]
+
+export function normalizeConsoleOpenAPIURL(url: string | URL) {
+ const normalizedUrl = new URL(url)
+ const rule = repeatedQueryArrayRules.find(({ path }) => path.test(normalizedUrl.pathname))
+
+ for (const field of rule?.fields ?? []) {
+ const pattern = new RegExp(`^${field}\\[(\\d+)\\]$`)
+ const values: Array<{ index: number; value: string }> = []
+ const indexedKeys = new Set()
+
+ for (const [key, value] of normalizedUrl.searchParams) {
+ const match = pattern.exec(key)
+ if (!match) continue
+ indexedKeys.add(key)
+ values.push({ index: Number(match[1]), value })
+ }
+
+ for (const key of indexedKeys) normalizedUrl.searchParams.delete(key)
+ for (const { value } of values.sort((a, b) => a.index - b.index))
+ normalizedUrl.searchParams.append(field, value)
+ }
+
+ return normalizedUrl.href
+}
diff --git a/web/service/client.ts b/web/service/console/query-policies.ts
similarity index 55%
rename from web/service/client.ts
rename to web/service/console/query-policies.ts
index 98913ca7061..7b9d1677450 100644
--- a/web/service/client.ts
+++ b/web/service/console/query-policies.ts
@@ -3,549 +3,14 @@ import type {
AgentAppPagination,
} from '@dify/contracts/api/console/agent/types.gen'
import type { ApiBasedExtensionResponse } from '@dify/contracts/api/console/api-based-extension/types.gen'
-import type { TagResponse as Tag, TagType } from '@dify/contracts/api/console/tags/types.gen'
-import type { consoleRouterContract } from '@dify/contracts/console'
-import type {
- EnvironmentAccess,
- GetEnvironmentDeploymentResponse,
- ListEnvironmentDeploymentsResponse,
-} from '@dify/contracts/enterprise-app-deploy/types.gen'
-import type {
- GetReleaseResponse,
- ListReleasesResponse,
- PrecheckReleaseRequest,
-} from '@dify/contracts/enterprise/types.gen'
-import type { ClientLink } from '@orpc/client'
-import type { AnyContractRouter, ContractRouterClient } from '@orpc/contract'
-import type { JsonifiedClient } from '@orpc/openapi-client'
-import type { RouterUtils, TanstackQueryOperationContext } from '@orpc/tanstack-query'
-import type { InfiniteData, QueryClient, QueryKey } from '@tanstack/react-query'
-import { marketplaceRouterContract } from '@dify/contracts/marketplace'
-import { createORPCClient, onError } from '@orpc/client'
-import { OpenAPILink } from '@orpc/openapi-client/fetch'
+import type { TagResponse as Tag } from '@dify/contracts/api/console/tags/types.gen'
+import type { RouterUtils } from '@orpc/tanstack-query'
+import type { InfiniteData } from '@tanstack/react-query'
+import type { ConsoleClient } from './index'
import { createTanstackQueryUtils } from '@orpc/tanstack-query'
-import { API_PREFIX, APP_VERSION, IS_MARKETPLACE, MARKETPLACE_API_PREFIX } from '@/config'
-import { isClient } from '@/utils/client'
-// oxlint-disable-next-line no-restricted-imports
-import { request, sseGeneratorPost } from './base'
-import { createConsoleDynamicLink } from './console-link'
-import { normalizeConsoleOpenAPIURL } from './console-openapi-url'
-export function streamWorkflowGeneration(...args: Parameters) {
- return sseGeneratorPost(...args)
-}
-
-function getMarketplaceHeaders() {
- return new Headers({
- 'X-Dify-Version': !IS_MARKETPLACE ? APP_VERSION : '999.0.0',
- })
-}
-
-// 15s deadline so a stalled Marketplace fetch can error/retry.
-const MARKETPLACE_REQUEST_TIMEOUT_MS = 15_000
-
-// Combine the caller's abort with the deadline; AbortSignal.any is too new.
-function withRequestDeadline(callerSignal: AbortSignal | null | undefined): AbortSignal {
- const deadline = AbortSignal.timeout(MARKETPLACE_REQUEST_TIMEOUT_MS)
- if (!callerSignal) return deadline
- if (callerSignal.aborted) return callerSignal
-
- const controller = new AbortController()
- callerSignal.addEventListener('abort', () => controller.abort(callerSignal.reason), {
- once: true,
- })
- deadline.addEventListener('abort', () => controller.abort(deadline.reason), { once: true })
- return controller.signal
-}
-
-function isMarketplacePackageDownload(input: Request | URL | string): boolean {
- const href = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url
- try {
- return new URL(href).pathname.endsWith('/download')
- } catch {
- return false
- }
-}
-
-function isURL(path: string) {
- try {
- // oxlint-disable-next-line no-new
- new URL(path)
- return true
- } catch {
- return false
- }
-}
-
-export function getBaseURL(path: string) {
- const url = new URL(
- path,
- isURL(path) ? undefined : isClient ? window.location.origin : 'http://localhost',
- )
-
- if (!isClient && !isURL(path)) {
- console.warn('Using localhost as base URL in server environment, please configure accordingly.')
- }
-
- if (url.protocol !== 'http:' && url.protocol !== 'https:') {
- console.warn(
- `Unexpected protocol for API requests, expected http or https. Current protocol: ${url.protocol}. Please configure accordingly.`,
- )
- }
-
- return url
-}
-
-export type ConsoleClientContext = TanstackQueryOperationContext & {
- keepalive?: boolean
- silent?: boolean
-}
-
-type ConsoleClientLink = ClientLink
-
-function createConsoleOpenAPILink(contract: AnyContractRouter): ConsoleClientLink {
- return new OpenAPILink(contract, {
- url: getBaseURL(API_PREFIX),
- fetch: (input, init, options) => {
- const requestInit = options.context.keepalive ? { ...init, keepalive: true } : init
- const normalizedURL = normalizeConsoleOpenAPIURL(input.url)
- const normalizedRequest =
- normalizedURL === input.url ? input : new Request(normalizedURL, input)
-
- return request(normalizedURL, requestInit, {
- fetchCompat: true,
- request: normalizedRequest,
- silent: options.context.silent,
- })
- },
- interceptors: [
- onError((error) => {
- console.error(error)
- }),
- ],
- })
-}
-
-const marketplaceLink = new OpenAPILink(marketplaceRouterContract, {
- url: MARKETPLACE_API_PREFIX,
- headers: () => getMarketplaceHeaders(),
- fetch: (request, init) => {
- const requestInit = init as RequestInit | undefined
- const callerSignal = requestInit?.signal ?? request.signal
- return globalThis.fetch(request, {
- ...requestInit,
- cache: 'no-store',
- signal: isMarketplacePackageDownload(request)
- ? callerSignal
- : withRequestDeadline(callerSignal),
- })
- },
- interceptors: [
- onError((error) => {
- console.error(error)
- }),
- ],
-})
-
-export const marketplaceClient: JsonifiedClient<
- ContractRouterClient
-> = createORPCClient(marketplaceLink)
-export const marketplaceQuery = createTanstackQueryUtils(marketplaceClient, {
- path: ['marketplace'],
-})
-
-const APP_DEPLOY_SOURCE_APPS_PAGE_SIZE = 100
-const APP_DEPLOY_READINESS_RETRY_DELAYS = [0, 300, 700, 1200]
-
-type AppDeployInvalidationOptions = {
- appInstances?: boolean
- appInstanceSummaries?: boolean
- appInstance?: boolean
- appInstanceOverview?: boolean
- environmentDeployments?: boolean
- releases?: boolean
- releaseSummaries?: boolean
- releaseDeploymentView?: boolean
- accessChannels?: boolean
- accessSettings?: boolean
- developerApiSettings?: boolean
-}
-
-type ConsoleQueryUtils = RouterUtils<
- JsonifiedClient>
->
-
-function isTagType(type: string | null | undefined): type is TagType {
- return type === 'app' || type === 'knowledge' || type === 'skill' || type === 'snippet'
-}
-
-const defaultAppDeployInvalidationOptions = {
- appInstances: true,
- appInstanceSummaries: true,
- appInstance: true,
- appInstanceOverview: true,
- environmentDeployments: true,
- releases: true,
- releaseSummaries: true,
- releaseDeploymentView: true,
- accessChannels: true,
- accessSettings: true,
- developerApiSettings: true,
-} satisfies Required
-
-function invalidateQueryKeys(client: QueryClient, queryKeys: QueryKey[]) {
- return Promise.all(queryKeys.map((queryKey) => client.invalidateQueries({ queryKey })))
-}
-
-function invalidateEnvironmentApiKeyQueries(
- query: ConsoleQueryUtils,
- client: QueryClient,
- params: { app_id: string; environment_id: string },
-) {
- const environmentParams = {
- app_id: params.app_id,
- environment_id: params.environment_id,
- }
-
- return invalidateQueryKeys(client, [
- query.enterprise.appDeploy.accessService.listEnvironmentApiKeys.queryOptions({
- input: { params: environmentParams },
- }).queryKey,
- query.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions({
- input: { params: environmentParams },
- }).queryKey,
- ])
-}
-
-function environmentDeploymentQueries(
- query: ConsoleQueryUtils,
- params: { app_id: string; environment_id: string },
-) {
- const environmentParams = {
- app_id: params.app_id,
- environment_id: params.environment_id,
- }
-
- return {
- deployment: query.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions({
- input: { params: environmentParams },
- }),
- deployments:
- query.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- },
- },
- }),
- }
-}
-
-function invalidateEnvironmentDeploymentQueries(
- query: ConsoleQueryUtils,
- client: QueryClient,
- params: { app_id: string; environment_id: string },
- { appEnvironments }: { appEnvironments: boolean },
-) {
- const environmentQueries = environmentDeploymentQueries(query, params)
- const queryKeys: QueryKey[] = [
- environmentQueries.deployments.queryKey,
- environmentQueries.deployment.queryKey,
- ]
-
- if (appEnvironments) {
- queryKeys.push(
- query.enterprise.appDeploy.deploymentService.listAppEnvironments.queryOptions({
- input: {
- params: {
- app_id: params.app_id,
- },
- },
- }).queryKey,
- )
- }
-
- return invalidateQueryKeys(client, queryKeys)
-}
-
-function syncEnvironmentAccessCaches(
- query: ConsoleQueryUtils,
- client: QueryClient,
- params: { app_id: string; environment_id: string },
- accessPatch: Partial,
-) {
- const environmentQueries = environmentDeploymentQueries(query, params)
-
- client.setQueryData(
- environmentQueries.deployments.queryKey,
- (current) => {
- if (
- !current?.environment_deployments.some(
- (deployment) => deployment.environment.id === params.environment_id,
- )
- )
- return current
-
- return {
- ...current,
- environment_deployments: current.environment_deployments.map((deployment) =>
- deployment.environment.id === params.environment_id
- ? {
- ...deployment,
- access: {
- ...deployment.access,
- ...accessPatch,
- },
- }
- : deployment,
- ),
- }
- },
- )
- client.setQueryData(
- environmentQueries.deployment.queryKey,
- (current) => {
- if (!current || current.environment_deployment.environment.id !== params.environment_id)
- return current
-
- return {
- ...current,
- environment_deployment: {
- ...current.environment_deployment,
- access: {
- ...current.environment_deployment.access,
- ...accessPatch,
- },
- },
- }
- },
- )
-
- return invalidateQueryKeys(client, [
- environmentQueries.deployments.queryKey,
- environmentQueries.deployment.queryKey,
- ])
-}
-
-function appInstanceQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.appInstanceService.getAppInstance.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function appInstanceOverviewQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.appInstanceService.getAppInstanceOverview.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function environmentDeploymentsQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.deploymentService.listEnvironmentDeployments.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function releasesQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.releaseService.listReleases.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function releaseSummariesQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.releaseService.listReleaseSummaries.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function releaseDeploymentViewQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.releaseService.computeReleaseDeploymentView.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function releaseQueryKey(query: ConsoleQueryUtils, releaseId: string) {
- return query.enterprise.releaseService.getRelease.key({
- type: 'query',
- input: { params: { releaseId } },
- })
-}
-
-function cachedReleaseAppInstanceId(
- query: ConsoleQueryUtils,
- client: QueryClient,
- releaseId: string,
-) {
- const listQueries = client.getQueriesData({
- queryKey: query.enterprise.releaseService.listReleases.key({ type: 'query' }),
- })
- for (const [, data] of listQueries) {
- const appInstanceId = data?.releases?.find((release) => release.id === releaseId)?.appInstanceId
- if (appInstanceId) return appInstanceId
- }
-
- const releaseQueries = client.getQueriesData({
- queryKey: query.enterprise.releaseService.getRelease.key({ type: 'query' }),
- })
- for (const [, data] of releaseQueries) {
- const release = data?.release
- if (release?.id === releaseId && release.appInstanceId) return release.appInstanceId
- }
-}
-
-function precheckReleaseQueryKey(query: ConsoleQueryUtils, body: PrecheckReleaseRequest) {
- return query.enterprise.releaseService.precheckRelease.key({
- type: 'query',
- input: { body },
- })
-}
-
-function accessChannelsQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.accessService.getAccessChannels.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function accessSettingsQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.accessService.getAccessSettings.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function developerApiSettingsQueryKey(query: ConsoleQueryUtils, appInstanceId: string) {
- return query.enterprise.accessService.getDeveloperApiSettings.key({
- type: 'query',
- input: { params: { appInstanceId } },
- })
-}
-
-function apiKeysQueryKey(query: ConsoleQueryUtils, appInstanceId: string, environmentId: string) {
- return query.enterprise.accessService.listApiKeys.key({
- type: 'query',
- input: { params: { appInstanceId, environmentId } },
- })
-}
-
-function accessPolicyQueryKey(
- query: ConsoleQueryUtils,
- appInstanceId: string,
- environmentId: string,
-) {
- return query.enterprise.accessService.getAccessPolicy.key({
- type: 'query',
- input: { params: { appInstanceId, environmentId } },
- })
-}
-
-function invalidateAppDeployQueries(
- query: ConsoleQueryUtils,
- client: QueryClient,
- appInstanceId: string,
- options: AppDeployInvalidationOptions = {},
-) {
- const resolvedOptions = {
- ...defaultAppDeployInvalidationOptions,
- ...options,
- }
- const queryKeys: QueryKey[] = []
-
- if (resolvedOptions.appInstances)
- queryKeys.push(query.enterprise.appInstanceService.listAppInstances.key())
- if (resolvedOptions.appInstanceSummaries)
- queryKeys.push(query.enterprise.appInstanceService.listAppInstanceSummaries.key())
- if (resolvedOptions.appInstance) queryKeys.push(appInstanceQueryKey(query, appInstanceId))
- if (resolvedOptions.appInstanceOverview)
- queryKeys.push(appInstanceOverviewQueryKey(query, appInstanceId))
- if (resolvedOptions.environmentDeployments)
- queryKeys.push(environmentDeploymentsQueryKey(query, appInstanceId))
- if (resolvedOptions.releases) queryKeys.push(releasesQueryKey(query, appInstanceId))
- if (resolvedOptions.releaseSummaries)
- queryKeys.push(releaseSummariesQueryKey(query, appInstanceId))
- if (resolvedOptions.releaseDeploymentView)
- queryKeys.push(releaseDeploymentViewQueryKey(query, appInstanceId))
- if (resolvedOptions.accessChannels) queryKeys.push(accessChannelsQueryKey(query, appInstanceId))
- if (resolvedOptions.accessSettings) queryKeys.push(accessSettingsQueryKey(query, appInstanceId))
- if (resolvedOptions.developerApiSettings)
- queryKeys.push(developerApiSettingsQueryKey(query, appInstanceId))
-
- return invalidateQueryKeys(client, queryKeys)
-}
-
-function removeAppDeployQueries(
- query: ConsoleQueryUtils,
- client: QueryClient,
- appInstanceId: string,
-) {
- const queryKeys = [
- appInstanceQueryKey(query, appInstanceId),
- appInstanceOverviewQueryKey(query, appInstanceId),
- environmentDeploymentsQueryKey(query, appInstanceId),
- releasesQueryKey(query, appInstanceId),
- releaseSummariesQueryKey(query, appInstanceId),
- releaseDeploymentViewQueryKey(query, appInstanceId),
- accessChannelsQueryKey(query, appInstanceId),
- accessSettingsQueryKey(query, appInstanceId),
- developerApiSettingsQueryKey(query, appInstanceId),
- ]
-
- queryKeys.forEach((queryKey) => client.removeQueries({ queryKey }))
-}
-
-async function invalidateReleaseMutationQueries(
- query: ConsoleQueryUtils,
- client: QueryClient,
- releaseId: string,
- appInstanceId?: string,
- options: {
- removeRelease?: boolean
- } = {},
-) {
- const releaseDetailQueryKey = releaseQueryKey(query, releaseId)
- if (options.removeRelease) {
- client.removeQueries({
- queryKey: releaseDetailQueryKey,
- })
- } else {
- await client.invalidateQueries({
- queryKey: releaseDetailQueryKey,
- })
- }
-
- if (appInstanceId) {
- return invalidateAppDeployQueries(query, client, appInstanceId, {
- accessChannels: false,
- accessSettings: false,
- developerApiSettings: false,
- })
- }
-
- return invalidateQueryKeys(client, [
- query.enterprise.appInstanceService.listAppInstances.key(),
- query.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- query.enterprise.releaseService.listReleases.key({ type: 'query' }),
- query.enterprise.releaseService.listReleaseSummaries.key({ type: 'query' }),
- query.enterprise.releaseService.computeReleaseDeploymentView.key({ type: 'query' }),
- query.enterprise.appInstanceService.getAppInstance.key({ type: 'query' }),
- query.enterprise.appInstanceService.getAppInstanceOverview.key({ type: 'query' }),
- ])
-}
-
-const consoleLink = createConsoleDynamicLink(createConsoleOpenAPILink)
-
-export const consoleClient: JsonifiedClient<
- ContractRouterClient
-> = createORPCClient(consoleLink)
-
-export const consoleQuery: RouterUtils = createTanstackQueryUtils(
- consoleClient,
- {
+export function createConsoleQuery(consoleClient: ConsoleClient) {
+ const consoleQuery: RouterUtils = createTanstackQueryUtils(consoleClient, {
path: ['console'],
experimental_defaults: {
account: {
@@ -1338,14 +803,12 @@ export const consoleQuery: RouterUtils = createTanstackQue
tags: {
post: {
mutationOptions: {
- onSuccess: (tag, _variables, _onMutateResult, context) => {
- if (!isTagType(tag.type)) return
-
+ onSuccess: (tag, variables, _onMutateResult, context) => {
context.client.setQueryData(
consoleQuery.tags.get.queryKey({
input: {
query: {
- type: tag.type,
+ type: variables.body.type,
},
},
}),
@@ -1413,65 +876,169 @@ export const consoleQuery: RouterUtils = createTanstackQue
enterprise: {
appDeploy: {
accessService: {
+ updateEnvironmentApi: {
+ mutationOptions: {
+ onSuccess: (updated, variables, _result, context) => {
+ const { app_id, environment_id } = variables.params
+ context.client.setQueryData(
+ consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions({
+ input: { params: { app_id, environment_id } },
+ }).queryKey,
+ updated,
+ )
+ const list =
+ consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions(
+ {
+ input: { params: { app_id } },
+ },
+ )
+ const detail =
+ consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ )
+ context.client.setQueryData(
+ list.queryKey,
+ (current) =>
+ current && {
+ ...current,
+ environment_deployments: current.environment_deployments.map(
+ (deployment) =>
+ deployment.environment.id === environment_id
+ ? {
+ ...deployment,
+ access: { ...deployment.access, enable_api: updated.enabled },
+ }
+ : deployment,
+ ),
+ },
+ )
+ context.client.setQueryData(
+ detail.queryKey,
+ (current) =>
+ current && {
+ ...current,
+ environment_deployment: {
+ ...current.environment_deployment,
+ access: {
+ ...current.environment_deployment.access,
+ enable_api: updated.enabled,
+ },
+ },
+ },
+ )
+ return Promise.all([
+ context.client.invalidateQueries({ queryKey: list.queryKey }),
+ context.client.invalidateQueries({ queryKey: detail.queryKey }),
+ ])
+ },
+ },
+ },
+ updateEnvironmentSite: {
+ mutationOptions: {
+ onSuccess: (updated, variables, _result, context) => {
+ const { app_id, environment_id } = variables.params
+ context.client.setQueryData(
+ consoleQuery.enterprise.appDeploy.accessService.getEnvironmentSite.queryOptions(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ ).queryKey,
+ updated,
+ )
+ const list =
+ consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryOptions(
+ {
+ input: { params: { app_id } },
+ },
+ )
+ const detail =
+ consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryOptions(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ )
+ context.client.setQueryData(
+ list.queryKey,
+ (current) =>
+ current && {
+ ...current,
+ environment_deployments: current.environment_deployments.map(
+ (deployment) =>
+ deployment.environment.id === environment_id
+ ? {
+ ...deployment,
+ access: { ...deployment.access, enable_site: updated.enabled },
+ }
+ : deployment,
+ ),
+ },
+ )
+ context.client.setQueryData(
+ detail.queryKey,
+ (current) =>
+ current && {
+ ...current,
+ environment_deployment: {
+ ...current.environment_deployment,
+ access: {
+ ...current.environment_deployment.access,
+ enable_site: updated.enabled,
+ },
+ },
+ },
+ )
+ return Promise.all([
+ context.client.invalidateQueries({ queryKey: list.queryKey }),
+ context.client.invalidateQueries({ queryKey: detail.queryKey }),
+ ])
+ },
+ },
+ },
createEnvironmentApiKey: {
mutationOptions: {
onSuccess: (_data, variables, _result, context) => {
- return invalidateEnvironmentApiKeyQueries(
- consoleQuery,
- context.client,
- variables.params,
- )
+ const { app_id, environment_id } = variables.params
+ return Promise.all([
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.accessService.listEnvironmentApiKeys.queryKey(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ ),
+ }),
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryKey({
+ input: { params: { app_id, environment_id } },
+ }),
+ }),
+ ])
},
},
},
deleteEnvironmentApiKey: {
mutationOptions: {
onSuccess: (_data, variables, _result, context) => {
- return invalidateEnvironmentApiKeyQueries(
- consoleQuery,
- context.client,
- variables.params,
- )
- },
- },
- },
- updateEnvironmentApi: {
- mutationOptions: {
- onSuccess: (updatedApi, variables, _result, context) => {
- context.client.setQueryData(
- consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryOptions({
- input: { params: variables.params },
- }).queryKey,
- updatedApi,
- )
-
- return syncEnvironmentAccessCaches(
- consoleQuery,
- context.client,
- variables.params,
- { enable_api: updatedApi.enabled },
- )
- },
- },
- },
- updateEnvironmentSite: {
- mutationOptions: {
- onSuccess: (updatedSite, variables, _result, context) => {
- context.client.setQueryData(
- consoleQuery.enterprise.appDeploy.accessService.getEnvironmentSite.queryOptions(
- {
- input: { params: variables.params },
- },
- ).queryKey,
- updatedSite,
- )
-
- return syncEnvironmentAccessCaches(
- consoleQuery,
- context.client,
- variables.params,
- { enable_site: updatedSite.enabled },
- )
+ const { app_id, environment_id } = variables.params
+ return Promise.all([
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.accessService.listEnvironmentApiKeys.queryKey(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ ),
+ }),
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.accessService.getEnvironmentApi.queryKey({
+ input: { params: { app_id, environment_id } },
+ }),
+ }),
+ ])
},
},
},
@@ -1480,24 +1047,58 @@ export const consoleQuery: RouterUtils = createTanstackQue
deployWorkflow: {
mutationOptions: {
onSuccess: (_data, variables, _result, context) => {
- return invalidateEnvironmentDeploymentQueries(
- consoleQuery,
- context.client,
- variables.params,
- { appEnvironments: false },
- )
+ const { app_id, environment_id } = variables.params
+ return Promise.all([
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryKey(
+ {
+ input: { params: { app_id } },
+ },
+ ),
+ }),
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryKey(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ ),
+ }),
+ ])
},
},
},
undeployWorkflow: {
mutationOptions: {
onSuccess: (_data, variables, _result, context) => {
- return invalidateEnvironmentDeploymentQueries(
- consoleQuery,
- context.client,
- variables.params,
- { appEnvironments: true },
- )
+ const { app_id, environment_id } = variables.params
+ return Promise.all([
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.deploymentService.listEnvironmentDeployments.queryKey(
+ {
+ input: { params: { app_id } },
+ },
+ ),
+ }),
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.deploymentService.getEnvironmentDeployment.queryKey(
+ {
+ input: { params: { app_id, environment_id } },
+ },
+ ),
+ }),
+ context.client.invalidateQueries({
+ queryKey:
+ consoleQuery.enterprise.appDeploy.deploymentService.listAppEnvironments.queryKey(
+ {
+ input: { params: { app_id } },
+ },
+ ),
+ }),
+ ])
},
},
},
@@ -1530,273 +1131,9 @@ export const consoleQuery: RouterUtils = createTanstackQue
},
},
},
- appInstanceService: {
- createAppInstance: {
- mutationOptions: {
- onSuccess: async (data, _variables, _result, context) => {
- const appInstanceId = data.appInstance?.id
- if (appInstanceId) {
- for (const delay of APP_DEPLOY_READINESS_RETRY_DELAYS) {
- if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay))
-
- const listResponse = await context.client
- .query({
- ...consoleQuery.enterprise.appInstanceService.listAppInstances.queryOptions(
- {
- input: {
- query: {
- pageNumber: 1,
- resultsPerPage: APP_DEPLOY_SOURCE_APPS_PAGE_SIZE,
- },
- },
- },
- ),
- staleTime: 0,
- })
- .catch(() => undefined)
-
- if (listResponse?.appInstances?.some((app) => app.id === appInstanceId)) break
- }
- }
-
- await context.client.invalidateQueries({
- queryKey: consoleQuery.enterprise.appInstanceService.listAppInstances.key(),
- })
- await context.client.invalidateQueries({
- queryKey:
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- })
- },
- },
- },
- updateAppInstance: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId, {
- environmentDeployments: false,
- releases: false,
- accessChannels: false,
- })
- },
- },
- },
- deleteAppInstance: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- removeAppDeployQueries(consoleQuery, context.client, appInstanceId)
-
- return Promise.all([
- context.client.invalidateQueries({
- queryKey: consoleQuery.enterprise.appInstanceService.listAppInstances.key(),
- }),
- context.client.invalidateQueries({
- queryKey:
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- }),
- ])
- },
- },
- },
- },
- releaseService: {
- createRelease: {
- mutationOptions: {
- onSuccess: (data, variables, _result, context) => {
- const appInstanceId =
- data.release?.appInstanceId ??
- data.appInstance?.id ??
- variables.body.appInstanceId
- const { dsl, sourceAppId } = variables.body
- if (!appInstanceId) {
- return Promise.all([
- context.client.invalidateQueries({
- queryKey: consoleQuery.enterprise.appInstanceService.listAppInstances.key(),
- }),
- context.client.invalidateQueries({
- queryKey:
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- }),
- ])
- }
-
- const appDeployInvalidation = invalidateAppDeployQueries(
- consoleQuery,
- context.client,
- appInstanceId,
- {
- environmentDeployments: false,
- accessChannels: false,
- },
- )
- if (!dsl && !sourceAppId) return appDeployInvalidation
-
- return Promise.all([
- appDeployInvalidation,
- context.client.invalidateQueries({
- queryKey: precheckReleaseQueryKey(consoleQuery, {
- appInstanceId,
- ...(dsl ? { dsl } : { sourceAppId }),
- }),
- }),
- ])
- },
- },
- },
- deleteRelease: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const releaseId = variables.params.releaseId
- const appInstanceId = cachedReleaseAppInstanceId(
- consoleQuery,
- context.client,
- releaseId,
- )
-
- return invalidateReleaseMutationQueries(
- consoleQuery,
- context.client,
- releaseId,
- appInstanceId,
- {
- removeRelease: true,
- },
- )
- },
- },
- },
- updateRelease: {
- mutationOptions: {
- onSuccess: (data, variables, _result, context) => {
- const releaseId = variables.params.releaseId
- const appInstanceId =
- data.release?.appInstanceId ??
- cachedReleaseAppInstanceId(consoleQuery, context.client, releaseId)
-
- return invalidateReleaseMutationQueries(
- consoleQuery,
- context.client,
- releaseId,
- appInstanceId,
- )
- },
- },
- },
- },
- deploymentService: {
- deploy: {
- mutationOptions: {
- onSuccess: (data, _variables, _result, context) => {
- // Deploy always creates a new AppInstance, so the reply carries it.
- const appInstanceId = data.appInstance?.id ?? data.release?.appInstanceId
- if (!appInstanceId) {
- return Promise.all([
- context.client.invalidateQueries({
- queryKey: consoleQuery.enterprise.appInstanceService.listAppInstances.key(),
- }),
- context.client.invalidateQueries({
- queryKey:
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- }),
- ])
- }
-
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId)
- },
- },
- },
- cancelDeployment: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId)
- },
- },
- },
- promote: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId)
- },
- },
- },
- rollback: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId)
- },
- },
- },
- undeploy: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId)
- },
- },
- },
- },
- accessService: {
- createApiKey: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- const environmentId = variables.params.environmentId
- return invalidateQueryKeys(context.client, [
- appInstanceQueryKey(consoleQuery, appInstanceId),
- appInstanceOverviewQueryKey(consoleQuery, appInstanceId),
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- accessChannelsQueryKey(consoleQuery, appInstanceId),
- developerApiSettingsQueryKey(consoleQuery, appInstanceId),
- apiKeysQueryKey(consoleQuery, appInstanceId, environmentId),
- ])
- },
- },
- },
- deleteApiKey: {
- mutationOptions: {
- onSuccess: (_data, _variables, _result, context) => {
- return invalidateQueryKeys(context.client, [
- consoleQuery.enterprise.accessService.listApiKeys.key({ type: 'query' }),
- consoleQuery.enterprise.accessService.getDeveloperApiSettings.key({
- type: 'query',
- }),
- consoleQuery.enterprise.appInstanceService.getAppInstanceOverview.key({
- type: 'query',
- }),
- consoleQuery.enterprise.appInstanceService.listAppInstanceSummaries.key(),
- ])
- },
- },
- },
- updateAccessChannels: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const appInstanceId = variables.params.appInstanceId
- return invalidateAppDeployQueries(consoleQuery, context.client, appInstanceId, {
- environmentDeployments: false,
- releases: false,
- })
- },
- },
- },
- updateAccessPolicy: {
- mutationOptions: {
- onSuccess: (_data, variables, _result, context) => {
- const { appInstanceId, environmentId } = variables.params
- return invalidateQueryKeys(context.client, [
- accessPolicyQueryKey(consoleQuery, appInstanceId, environmentId),
- accessChannelsQueryKey(consoleQuery, appInstanceId),
- accessSettingsQueryKey(consoleQuery, appInstanceId),
- ])
- },
- },
- },
- },
},
},
- },
-)
+ })
+
+ return consoleQuery
+}
diff --git a/web/service/console/server.spec.ts b/web/service/console/server.spec.ts
new file mode 100644
index 00000000000..1e7bd86918e
--- /dev/null
+++ b/web/service/console/server.spec.ts
@@ -0,0 +1,167 @@
+// @vitest-environment node
+
+import { AsyncLocalStorage } from 'node:async_hooks'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test'
+
+const mocks = vi.hoisted(() => ({
+ headers: vi.fn(),
+ cookies: vi.fn(),
+ serverConsoleApiPrefix: undefined as string | undefined,
+}))
+
+vi.mock('server-only', () => ({}))
+
+vi.mock('@/config', () => ({
+ API_PREFIX: 'http://localhost:5001/console/api',
+ CSRF_COOKIE_NAME: () => 'csrf_token',
+ CSRF_HEADER_NAME: 'X-CSRF-Token',
+}))
+
+vi.mock('@/config/server', () => ({
+ get SERVER_CONSOLE_API_PREFIX() {
+ return mocks.serverConsoleApiPrefix
+ },
+}))
+
+vi.mock('@/next/headers', () => ({
+ headers: () => mocks.headers(),
+ cookies: () => mocks.cookies(),
+}))
+
+beforeEach(() => {
+ vi.clearAllMocks()
+ vi.unstubAllGlobals()
+ mocks.serverConsoleApiPrefix = undefined
+ mocks.headers.mockResolvedValue(
+ new Headers({ cookie: 'access_token=abc; csrf_token=csrf-token' }),
+ )
+ mocks.cookies.mockResolvedValue({
+ get: vi.fn(() => ({ value: 'csrf-token' })),
+ })
+})
+
+describe('server console oRPC client', () => {
+ it('should resolve server console API URLs only from configured or absolute prefixes', async () => {
+ const { resolveServerConsoleApiPrefix, resolveServerConsoleApiUrl } = await import('./server')
+
+ expect(resolveServerConsoleApiPrefix(undefined, '/console/api')).toBeNull()
+ expect(resolveServerConsoleApiUrl('/account/profile', undefined, '/console/api')).toBeNull()
+ expect(
+ resolveServerConsoleApiUrl(
+ '/account/profile',
+ 'https://api.example.com/console/api',
+ '/console/api',
+ ),
+ ).toBe('https://api.example.com/console/api/account/profile')
+ expect(
+ resolveServerConsoleApiUrl(
+ '/account/profile',
+ undefined,
+ 'https://public.example.com/console/api',
+ ),
+ ).toBe('https://public.example.com/console/api/account/profile')
+ })
+
+ it('should call contracts with forwarded cookies, csrf header, and no-store cache', async () => {
+ const { createSystemFeaturesFixture } = await import('@/test/console/system-features')
+ const fetchMock = vi.fn().mockResolvedValue(
+ new Response(JSON.stringify(createSystemFeaturesFixture()), {
+ status: 200,
+ headers: {
+ 'content-type': 'application/json',
+ },
+ }),
+ )
+ vi.stubGlobal('fetch', fetchMock)
+ await import('./server')
+ const { consoleClient } = await import('@/service/console')
+
+ await consoleClient.systemFeatures.get()
+
+ expect(fetchMock).toHaveBeenCalledWith(
+ expect.any(Request),
+ expect.objectContaining({
+ cache: 'no-store',
+ redirect: 'manual',
+ }),
+ )
+ const request = fetchMock.mock.calls[0]?.[0] as Request
+ expect(request.url).toBe('http://localhost:5001/console/api/system-features')
+ expect(request.method).toBe('GET')
+ expect(request.headers.get('accept')).toBe('application/json')
+ expect(request.headers.get('content-type')).toBeNull()
+ expect(request.headers.get('cookie')).toBe('access_token=abc; csrf_token=csrf-token')
+ expect(request.headers.get('X-CSRF-Token')).toBe('csrf-token')
+ })
+})
+
+afterEach(() => vi.unstubAllGlobals())
+
+describe('unified Console server identity', () => {
+ it('keeps concurrent request identities out of the shared transport', async () => {
+ const identities = new AsyncLocalStorage()
+ mocks.headers.mockImplementation(
+ async () => new Headers({ cookie: `session=${identities.getStore()}` }),
+ )
+ mocks.cookies.mockImplementation(async () => ({
+ get: () => ({ value: identities.getStore() }),
+ }))
+ const { createSystemFeaturesFixture } = await import('@/test/console/system-features')
+ const fetch = vi.fn(async (_request: Request) => Response.json(createSystemFeaturesFixture()))
+ vi.stubGlobal('fetch', fetch)
+ await import('./server')
+ const { consoleClient } = await import('@/service/console')
+ await Promise.all(
+ ['alice', 'bob'].map((identity) =>
+ identities.run(identity, () => consoleClient.systemFeatures.get()),
+ ),
+ )
+ expect(
+ fetch.mock.calls.map(([request]) => (request as Request).headers.get('cookie')).sort(),
+ ).toEqual(['session=alice', 'session=bob'])
+ expect(
+ fetch.mock.calls.map(([request]) => (request as Request).headers.get('X-CSRF-Token')).sort(),
+ ).toEqual(['alice', 'bob'])
+ })
+
+ it('supports anonymous requests and selects the internal host at call time', async () => {
+ mocks.headers.mockResolvedValue(new Headers())
+ mocks.cookies.mockResolvedValue({ get: () => undefined })
+ mocks.serverConsoleApiPrefix = 'https://internal.example/console/api'
+ const { createSystemFeaturesFixture } = await import('@/test/console/system-features')
+ const fetch = vi.fn(async (_request: Request) => Response.json(createSystemFeaturesFixture()))
+ vi.stubGlobal('fetch', fetch)
+ await import('./server')
+ const { consoleClient } = await import('@/service/console')
+ await consoleClient.systemFeatures.get()
+ const request = fetch.mock.calls[0]?.[0] as Request
+ expect(request.url).toBe('https://internal.example/console/api/system-features')
+ expect(request.headers.has('cookie')).toBe(false)
+ expect(request.headers.has('X-CSRF-Token')).toBe(false)
+ })
+
+ it('uses the same array encoding and forwards the abort signal on the server', async () => {
+ mocks.headers.mockResolvedValue(new Headers())
+ mocks.cookies.mockResolvedValue({ get: () => undefined })
+ const fetch = vi.fn(async (_request: Request) =>
+ Response.json({ data: [], has_more: false, limit: 20, page: 1, total: 0 }),
+ )
+ vi.stubGlobal('fetch', fetch)
+ const { consoleClient } = await import('@/service/console')
+ const controller = new AbortController()
+ await consoleClient.trialApps.byAppId.datasets.get(
+ {
+ params: { app_id: 'app-1' },
+ query: { ids: ['id-1', 'id-2'] },
+ },
+ { signal: controller.signal },
+ )
+ const request = fetch.mock.calls[0]![0]
+ const url = new URL(request.url)
+ expect(url.searchParams.getAll('ids')).toEqual(['id-1', 'id-2'])
+ expect(url.searchParams.has('ids[0]')).toBe(false)
+ expect(request.signal.aborted).toBe(false)
+ controller.abort()
+ expect(request.signal.aborted).toBe(true)
+ })
+})
diff --git a/web/service/console/server.ts b/web/service/console/server.ts
new file mode 100644
index 00000000000..c9e6425e256
--- /dev/null
+++ b/web/service/console/server.ts
@@ -0,0 +1,93 @@
+import type { ClientLink } from '@orpc/client'
+import type { AnyContractRouter } from '@orpc/contract'
+import type { ConsoleClientContext } from './index'
+import { onError } from '@orpc/client'
+import { OpenAPILink } from '@orpc/openapi-client/fetch'
+import { cache } from 'react'
+import { API_PREFIX, CSRF_COOKIE_NAME, CSRF_HEADER_NAME } from '@/config'
+import { SERVER_CONSOLE_API_PREFIX } from '@/config/server'
+import { cookies, headers } from '@/next/headers'
+import { createConsoleContractLink } from './contract-loader'
+import { normalizeConsoleOpenAPIURL } from './openapi-url'
+import 'server-only'
+
+export const resolveServerConsoleApiPrefix = (
+ serverConsoleApiPrefix = SERVER_CONSOLE_API_PREFIX,
+ publicApiPrefix = API_PREFIX,
+) => {
+ if (serverConsoleApiPrefix) return serverConsoleApiPrefix
+ try {
+ return new URL(publicApiPrefix).href
+ } catch {
+ return null
+ }
+}
+
+export const resolveServerConsoleApiUrl = (
+ pathname: string,
+ serverConsoleApiPrefix = SERVER_CONSOLE_API_PREFIX,
+ publicApiPrefix = API_PREFIX,
+) => {
+ const apiPrefix = resolveServerConsoleApiPrefix(serverConsoleApiPrefix, publicApiPrefix)
+ if (!apiPrefix) return null
+
+ return new URL(pathname.replace(/^\//, ''), `${apiPrefix.replace(/\/$/, '')}/`).href
+}
+
+const getServerConsoleApiPrefix = () => {
+ const apiPrefix = resolveServerConsoleApiPrefix()
+ if (!apiPrefix) throw new Error('Server console API URL is not configured')
+
+ return apiPrefix
+}
+
+const getConsoleRequestIdentity = cache(async () => {
+ const requestHeaders = await headers()
+ const cookieStore = await cookies()
+
+ return {
+ cookie: requestHeaders.get('cookie') || undefined,
+ csrfToken: cookieStore.get(CSRF_COOKIE_NAME())?.value,
+ }
+})
+
+export const getServerConsoleRequestHeaders = async () => {
+ const { cookie, csrfToken } = await getConsoleRequestIdentity()
+ const requestHeaders = new Headers({ Accept: 'application/json' })
+ if (cookie) requestHeaders.set('cookie', cookie)
+ if (csrfToken) requestHeaders.set(CSRF_HEADER_NAME, csrfToken)
+ return requestHeaders
+}
+
+function createServerConsoleOpenAPILink(
+ contract: AnyContractRouter,
+): ClientLink {
+ return new OpenAPILink(contract, {
+ url: getServerConsoleApiPrefix,
+ headers: getServerConsoleRequestHeaders,
+ fetch: (request, init) => {
+ if (request.body && !request.headers.has('content-type'))
+ request.headers.set('Content-Type', 'application/json')
+
+ const normalizedURL = normalizeConsoleOpenAPIURL(request.url)
+ const normalizedRequest =
+ normalizedURL === request.url ? request : new Request(normalizedURL, request)
+ return globalThis.fetch(normalizedRequest, {
+ ...init,
+ cache: 'no-store',
+ })
+ },
+ interceptors: [
+ onError((error) => {
+ console.error(error)
+ }),
+ ],
+ })
+}
+
+const consoleServerLink = createConsoleContractLink(
+ createServerConsoleOpenAPILink,
+)
+
+// Share only the transport across RSC and Client Component SSR module graphs.
+globalThis.$consoleServerLink = consoleServerLink
diff --git a/web/service/explore.spec.ts b/web/service/explore.spec.ts
index 17ace7b0000..2c2af14a39f 100644
--- a/web/service/explore.spec.ts
+++ b/web/service/explore.spec.ts
@@ -5,7 +5,7 @@ const mockExploreAppsGet = vi.hoisted(() => vi.fn())
const mockExploreAppDetailGet = vi.hoisted(() => vi.fn())
const mockInstalledAppsGet = vi.hoisted(() => vi.fn())
-vi.mock('./client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
explore: {
apps: {
diff --git a/web/service/explore.ts b/web/service/explore.ts
index 729627fc256..98d50593886 100644
--- a/web/service/explore.ts
+++ b/web/service/explore.ts
@@ -7,7 +7,7 @@ import type {
} from '@dify/contracts/api/console/explore/types.gen'
import type { App, AppCategory } from '@/models/explore'
import type { AppIconType } from '@/types/app'
-import { consoleClient } from './client'
+import { consoleClient } from '@/service/console'
type ExploreAppsResponse = {
categories: AppCategory[]
diff --git a/web/service/marketplace-template-discovery.spec.ts b/web/service/marketplace-template-discovery.spec.ts
index e2c910aab94..ef5cc2e939d 100644
--- a/web/service/marketplace-template-discovery.spec.ts
+++ b/web/service/marketplace-template-discovery.spec.ts
@@ -6,7 +6,7 @@ const mocks = vi.hoisted(() => ({
templateSearch: vi.fn(),
}))
-vi.mock('./client', () => ({
+vi.mock('@/service/marketplace', () => ({
marketplaceClient: {
templateCollections: (...args: unknown[]) => mocks.templateCollections(...args),
templateCollectionTemplates: (...args: unknown[]) => mocks.templateCollectionTemplates(...args),
diff --git a/web/service/marketplace-template-discovery.ts b/web/service/marketplace-template-discovery.ts
index 55e194f8ea4..5b20a34f55c 100644
--- a/web/service/marketplace-template-discovery.ts
+++ b/web/service/marketplace-template-discovery.ts
@@ -3,7 +3,7 @@ import type {
MarketplaceTemplateCollection,
} from '@dify/contracts/marketplace'
import { SERVER_PREFETCH_BUDGET_MS } from '@/app/components/plugins/marketplace/server-budget'
-import { marketplaceClient } from './client'
+import { marketplaceClient } from '@/service/marketplace'
export type MarketplaceTemplateCollectionsResult = {
collections: MarketplaceTemplateCollection[]
diff --git a/web/service/marketplace-templates.ts b/web/service/marketplace-templates.ts
index 2316b4dee98..c997f620a42 100644
--- a/web/service/marketplace-templates.ts
+++ b/web/service/marketplace-templates.ts
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query'
import { MARKETPLACE_API_PREFIX } from '@/config'
-import { marketplaceQuery } from './client'
+import { marketplaceQuery } from '@/service/marketplace'
export const useMarketplaceTemplateDetail = (templateId: string | null) => {
return useQuery({
diff --git a/web/service/marketplace.ts b/web/service/marketplace.ts
new file mode 100644
index 00000000000..a903986259f
--- /dev/null
+++ b/web/service/marketplace.ts
@@ -0,0 +1,51 @@
+import type { ContractRouterClient } from '@orpc/contract'
+import type { JsonifiedClient } from '@orpc/openapi-client'
+import { marketplaceRouterContract } from '@dify/contracts/marketplace'
+import { createORPCClient, onError } from '@orpc/client'
+import { OpenAPILink } from '@orpc/openapi-client/fetch'
+import { createTanstackQueryUtils } from '@orpc/tanstack-query'
+import { APP_VERSION, IS_MARKETPLACE, MARKETPLACE_API_PREFIX } from '@/config'
+
+// 15s deadline so a stalled Marketplace fetch can error/retry.
+const MARKETPLACE_REQUEST_TIMEOUT_MS = 15_000
+
+// Preserve caller cancellation alongside the Marketplace deadline.
+function withRequestDeadline(callerSignal: AbortSignal): AbortSignal {
+ const deadline = AbortSignal.timeout(MARKETPLACE_REQUEST_TIMEOUT_MS)
+ if (callerSignal.aborted) return callerSignal
+
+ const controller = new AbortController()
+ callerSignal.addEventListener('abort', () => controller.abort(callerSignal.reason), {
+ once: true,
+ })
+ deadline.addEventListener('abort', () => controller.abort(deadline.reason), { once: true })
+ return controller.signal
+}
+
+const marketplaceLink = new OpenAPILink(marketplaceRouterContract, {
+ url: MARKETPLACE_API_PREFIX,
+ headers: () => ({
+ 'X-Dify-Version': !IS_MARKETPLACE ? APP_VERSION : '999.0.0',
+ }),
+ fetch: (request, init) => {
+ return globalThis.fetch(request, {
+ ...init,
+ cache: 'no-store',
+ signal: new URL(request.url).pathname.endsWith('/download')
+ ? request.signal
+ : withRequestDeadline(request.signal),
+ })
+ },
+ interceptors: [
+ onError((error) => {
+ console.error(error)
+ }),
+ ],
+})
+
+export const marketplaceClient: JsonifiedClient<
+ ContractRouterClient
+> = createORPCClient(marketplaceLink)
+export const marketplaceQuery = createTanstackQueryUtils(marketplaceClient, {
+ path: ['marketplace'],
+})
diff --git a/web/service/plugins.spec.ts b/web/service/plugins.spec.ts
index 1d71b6db883..0397c859c3f 100644
--- a/web/service/plugins.spec.ts
+++ b/web/service/plugins.spec.ts
@@ -12,7 +12,7 @@ vi.mock('./base', () => ({
upload: vi.fn(),
}))
-vi.mock('./client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
workspaces: {
current: {
diff --git a/web/service/plugins.ts b/web/service/plugins.ts
index 452fba65c51..fdfcdb47d2c 100644
--- a/web/service/plugins.ts
+++ b/web/service/plugins.ts
@@ -7,8 +7,8 @@ import type {
updatePackageResponse,
uploadGitHubResponse,
} from '@/app/components/plugins/types'
+import { consoleClient } from '@/service/console'
import { get, getMarketplace, post, upload } from './base'
-import { consoleClient } from './client'
export const uploadFile = async (file: File, isBundle: boolean) => {
const formData = new FormData()
diff --git a/web/service/server.ts b/web/service/server.ts
deleted file mode 100644
index 7b4d90786f0..00000000000
--- a/web/service/server.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-import type { consoleRouterContract } from '@dify/contracts/api/console/router.gen'
-import type { ClientLink } from '@orpc/client'
-import type { AnyContractRouter, ContractRouterClient } from '@orpc/contract'
-import type { JsonifiedClient } from '@orpc/openapi-client'
-import { createORPCClient, onError } from '@orpc/client'
-import { OpenAPILink } from '@orpc/openapi-client/fetch'
-import { createTanstackQueryUtils } from '@orpc/tanstack-query'
-import { cache } from 'react'
-import { API_PREFIX, CSRF_COOKIE_NAME, CSRF_HEADER_NAME } from '@/config'
-import { SERVER_CONSOLE_API_PREFIX } from '@/config/server'
-import { createConsoleDynamicLink } from './console-link'
-import 'server-only'
-
-export type ServerConsoleClientContext = {
- cookie?: string
- csrfToken?: string
-}
-
-const withTrailingSlash = (value: string) => (value.endsWith('/') ? value : `${value}/`)
-const withoutLeadingSlash = (value: string) => (value.startsWith('/') ? value.slice(1) : value)
-
-const resolveAbsoluteUrlPrefix = (value: string) => {
- try {
- return new URL(value).toString()
- } catch {
- return null
- }
-}
-
-export const resolveServerConsoleApiPrefix = (
- serverConsoleApiPrefix = SERVER_CONSOLE_API_PREFIX,
- publicApiPrefix = API_PREFIX,
-) => serverConsoleApiPrefix || resolveAbsoluteUrlPrefix(publicApiPrefix)
-
-export const resolveServerConsoleApiUrl = (
- pathname: string,
- serverConsoleApiPrefix = SERVER_CONSOLE_API_PREFIX,
- publicApiPrefix = API_PREFIX,
-) => {
- const apiPrefix = resolveServerConsoleApiPrefix(serverConsoleApiPrefix, publicApiPrefix)
- if (!apiPrefix) return null
-
- return new URL(withoutLeadingSlash(pathname), withTrailingSlash(apiPrefix)).toString()
-}
-
-const getServerConsoleApiPrefix = () => {
- const apiPrefix = resolveServerConsoleApiPrefix()
- if (!apiPrefix) throw new Error('Server console API URL is not configured')
-
- return apiPrefix
-}
-
-const createServerConsoleRequestHeaders = (context: ServerConsoleClientContext | undefined) => {
- const requestHeaders = new Headers({
- Accept: 'application/json',
- })
-
- if (context?.cookie) requestHeaders.set('cookie', context.cookie)
- if (context?.csrfToken) requestHeaders.set(CSRF_HEADER_NAME, context.csrfToken)
-
- return requestHeaders
-}
-
-type ServerConsoleClientLink = ClientLink
-
-function createServerConsoleOpenAPILink(contract: AnyContractRouter): ServerConsoleClientLink {
- return new OpenAPILink(contract, {
- url: getServerConsoleApiPrefix,
- headers: ({ context }) => createServerConsoleRequestHeaders(context),
- fetch: (request, init) => {
- if (request.body && !request.headers.has('content-type'))
- request.headers.set('Content-Type', 'application/json')
-
- return globalThis.fetch(request, {
- ...init,
- cache: 'no-store',
- })
- },
- interceptors: [
- onError((error) => {
- console.error(error)
- }),
- ],
- })
-}
-
-export const getServerConsoleClientContext = cache(
- async (): Promise => {
- const { cookies, headers } = await import('@/next/headers')
- const requestHeaders = await headers()
- const cookieStore = await cookies()
-
- return {
- cookie: requestHeaders.get('cookie') || undefined,
- csrfToken: cookieStore.get(CSRF_COOKIE_NAME())?.value,
- }
- },
-)
-
-export const getServerConsoleRequestHeaders = async () =>
- createServerConsoleRequestHeaders(await getServerConsoleClientContext())
-
-const serverConsoleLink = createConsoleDynamicLink(
- createServerConsoleOpenAPILink,
-)
-
-export const serverConsoleClient: JsonifiedClient<
- ContractRouterClient
-> = createORPCClient(serverConsoleLink)
-
-export const serverConsoleQuery = createTanstackQueryUtils(serverConsoleClient, {
- path: ['console'],
-})
diff --git a/web/service/try-app.ts b/web/service/try-app.ts
index ea9a5de50d0..d0d0d2bbcdb 100644
--- a/web/service/try-app.ts
+++ b/web/service/try-app.ts
@@ -2,7 +2,7 @@ import type { ChatConfig } from '@/app/components/base/chat/types'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import { ANNOTATION_DEFAULT, DEFAULT_AGENT_SETTING } from '@/config'
import { PromptMode } from '@/models/debug'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { Resolution, RETRIEVE_TYPE, TransferMethod, TtsAutoPlay } from '@/types/app'
type TryAppParameters = import('@dify/contracts/api/console/trial-apps/types.gen').Parameters
diff --git a/web/service/use-common.ts b/web/service/use-common.ts
index a2ab3e8db9d..c6f8c089d13 100644
--- a/web/service/use-common.ts
+++ b/web/service/use-common.ts
@@ -17,9 +17,9 @@ import type {
} from '@/models/common'
import { queryOptions, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { discardRegistrationSessionState } from '@/app/components/base/amplitude/registration-session-state'
+import { consoleQuery } from '@/service/console'
// oxlint-disable-next-line no-restricted-imports
import { get, post } from './base'
-import { consoleQuery } from './client'
const NAME_SPACE = 'common'
diff --git a/web/service/use-explore.ts b/web/service/use-explore.ts
index 3319b424f4e..c7ca887fbe1 100644
--- a/web/service/use-explore.ts
+++ b/web/service/use-explore.ts
@@ -1,7 +1,7 @@
import type { App, AppCategory } from '@/models/explore'
import { useQuery } from '@tanstack/react-query'
import { useLocale } from '@/context/i18n'
-import { consoleQuery } from './client'
+import { consoleQuery } from '@/service/console'
import { fetchAppList, fetchLearnDifyAppList } from './explore'
type ExploreAppListData = {
diff --git a/web/service/use-log.ts b/web/service/use-log.ts
index d2d3d542169..65a201861a8 100644
--- a/web/service/use-log.ts
+++ b/web/service/use-log.ts
@@ -9,8 +9,8 @@ import type {
WorkflowPausedDetailsResponse,
} from '@/models/log'
import { useQuery } from '@tanstack/react-query'
+import { consoleClient } from '@/service/console'
import { get } from './base'
-import { consoleClient } from './client'
const NAME_SPACE = 'log'
diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts
index 3ccb6a5283c..365fc66a3f5 100644
--- a/web/service/use-plugins.ts
+++ b/web/service/use-plugins.ts
@@ -43,11 +43,11 @@ import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/
import { getFormattedPlugin } from '@/app/components/plugins/marketplace/utils'
import { PluginCategoryEnum, PluginSource, TaskStatus } from '@/app/components/plugins/types'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
+import { consoleQuery } from '@/service/console'
import { uninstallPlugin } from '@/service/plugins'
import { hasPermission } from '@/utils/permission'
// oxlint-disable-next-line no-restricted-imports
import { get, getMarketplace, post, postMarketplace } from './base'
-import { consoleQuery } from './client'
import { useInvalidateAllBuiltInTools } from './use-tools'
const NAME_SPACE = 'plugins'
diff --git a/web/service/use-snippet-workflows.ts b/web/service/use-snippet-workflows.ts
index c0469fa0c31..fa769a110e3 100644
--- a/web/service/use-snippet-workflows.ts
+++ b/web/service/use-snippet-workflows.ts
@@ -1,6 +1,6 @@
import type { PublishSnippetWorkflowResponse, SnippetWorkflow } from '@/types/snippet'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
const isNotFoundError = (error: unknown) => {
return !!error && typeof error === 'object' && 'status' in error && error.status === 404
diff --git a/web/service/use-snippets.ts b/web/service/use-snippets.ts
index 58a10fa22e0..d375167cd49 100644
--- a/web/service/use-snippets.ts
+++ b/web/service/use-snippets.ts
@@ -23,7 +23,7 @@ import {
useQueryClient,
} from '@tanstack/react-query'
import dayjs from 'dayjs'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
type SnippetListParams = {
page?: number
diff --git a/web/service/use-tools.ts b/web/service/use-tools.ts
index a7e84ff1d5a..002cbc9b264 100644
--- a/web/service/use-tools.ts
+++ b/web/service/use-tools.ts
@@ -10,8 +10,8 @@ import type { RAGRecommendedPlugins, ToolWithProvider } from '@/app/components/w
import type { AppIconType } from '@/types/app'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { CollectionType } from '@/app/components/tools/types'
+import { consoleClient } from '@/service/console'
import { del, get, post, put } from './base'
-import { consoleClient } from './client'
import { useInvalid } from './use-base'
const NAME_SPACE = 'tools'
diff --git a/web/service/use-triggers.ts b/web/service/use-triggers.ts
index c8bd44a4d81..0c891f2544f 100644
--- a/web/service/use-triggers.ts
+++ b/web/service/use-triggers.ts
@@ -18,7 +18,7 @@ import { FormTypeEnum } from '@/app/components/base/form/types'
import { SupportedCreationMethods } from '@/app/components/plugins/types'
import { CollectionType } from '@/app/components/tools/types'
import { TriggerCredentialType } from '@/app/components/workflow/block-selector/types'
-import { consoleClient, consoleQuery } from '@/service/client'
+import { consoleClient, consoleQuery } from '@/service/console'
import { useInvalid } from './use-base'
const NAME_SPACE = 'triggers'
diff --git a/web/service/use-try-app.ts b/web/service/use-try-app.ts
index e7a9d3426db..cdf447909a0 100644
--- a/web/service/use-try-app.ts
+++ b/web/service/use-try-app.ts
@@ -1,5 +1,5 @@
import { useQuery } from '@tanstack/react-query'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import {
fetchTryAppDatasets,
fetchTryAppFlowPreview,
diff --git a/web/service/use-workflow.ts b/web/service/use-workflow.ts
index f7cdef66528..139075aff23 100644
--- a/web/service/use-workflow.ts
+++ b/web/service/use-workflow.ts
@@ -22,9 +22,9 @@ import type {
WorkflowRunHistoryResponse,
} from '@/types/workflow'
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
+import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { del, get, patch, post, put } from './base'
-import { consoleQuery } from './client'
import { useInvalid } from './use-base'
import { getFlowPrefix } from './utils'
import { appWorkflowQueryOptions, appWorkflowVersionsInfiniteQueryKey } from './workflow-queries'
diff --git a/web/service/workflow-generator.ts b/web/service/workflow-generator.ts
index 48ae00aa775..4eff9f6eff2 100644
--- a/web/service/workflow-generator.ts
+++ b/web/service/workflow-generator.ts
@@ -6,7 +6,9 @@ import type {
} from '@dify/contracts/api/console/workflow-generate/types.gen'
// The generated client handles JSON endpoints. Streaming remains on the
// generator-specific SSE adapter until oRPC supports this event framing.
-import { consoleClient, streamWorkflowGeneration } from './client'
+import { consoleClient } from '@/service/console'
+// oxlint-disable-next-line no-restricted-imports
+import { sseGeneratorPost } from './base'
export type GenerateWorkflowBody = WorkflowGeneratePayload
export type GenerateWorkflowResponse = WorkflowGenerateResponse
@@ -35,7 +37,7 @@ export function generateWorkflowStream(
body: GenerateWorkflowBody,
callbacks: GenerateWorkflowStreamCallbacks,
) {
- return streamWorkflowGeneration('/workflow-generate/stream', body, {
+ return sseGeneratorPost('/workflow-generate/stream', body, {
onPlan: (data) => callbacks.onPlan?.(data as WorkflowGenPlan),
onResult: (data) => callbacks.onResult?.(data as GenerateWorkflowResponse),
onError: callbacks.onError,
diff --git a/web/service/workflow-queries.ts b/web/service/workflow-queries.ts
index 5221043c90c..a8e3f23ad27 100644
--- a/web/service/workflow-queries.ts
+++ b/web/service/workflow-queries.ts
@@ -1,5 +1,5 @@
import { skipToken } from '@tanstack/react-query'
-import { consoleQuery } from './client'
+import { consoleQuery } from '@/service/console'
const WORKFLOW_VERSIONS_PAGE_SIZE = 10
diff --git a/web/service/workflow.spec.ts b/web/service/workflow.spec.ts
index a72f8e967bc..4388e143171 100644
--- a/web/service/workflow.spec.ts
+++ b/web/service/workflow.spec.ts
@@ -9,7 +9,7 @@ vi.mock('./base', () => ({
post: mockPost,
}))
-vi.mock('./client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {},
}))
diff --git a/web/service/workflow.ts b/web/service/workflow.ts
index caa029f7db0..f8f42de7fd6 100644
--- a/web/service/workflow.ts
+++ b/web/service/workflow.ts
@@ -13,8 +13,8 @@ import type {
NodesDefaultConfigsResponse,
VarInInspect,
} from '@/types/workflow'
+import { consoleClient } from '@/service/console'
import { get, post } from './base'
-import { consoleClient } from './client'
import { getFlowPrefix } from './utils'
export type WorkflowDraftFeaturesPayload = WorkflowFeaturesConfigPayload
diff --git a/web/test/console/query-data.ts b/web/test/console/query-data.ts
index 2ade640de55..1c7258959dc 100644
--- a/web/test/console/query-data.ts
+++ b/web/test/console/query-data.ts
@@ -21,7 +21,7 @@ import type { DeepPartial } from '@/test/console/system-features'
import { zGetFeaturesResponse } from '@dify/contracts/api/console/features/zod.gen'
import { noop } from '@tanstack/react-query'
import { render, renderHook } from '@testing-library/react'
-import { consoleQuery } from '@/service/client'
+import { consoleQuery } from '@/service/console'
import { ensureAccountProfileQuery, seedAccountProfileQuery } from '@/test/console/account-profile'
import {
currentWorkspaceQueryKey,
diff --git a/web/utils/imported-app-redirection.spec.ts b/web/utils/imported-app-redirection.spec.ts
index 29feca53795..9f9ed5d166f 100644
--- a/web/utils/imported-app-redirection.spec.ts
+++ b/web/utils/imported-app-redirection.spec.ts
@@ -3,7 +3,7 @@ import { resolveImportedAppRedirectionTarget } from './imported-app-redirection'
const mockFetchAppDetail = vi.hoisted(() => vi.fn())
-vi.mock('@/service/client', () => ({
+vi.mock('@/service/console', () => ({
consoleClient: {
apps: {
byAppId: {
diff --git a/web/utils/imported-app-redirection.ts b/web/utils/imported-app-redirection.ts
index 7b77cd39d38..68384998602 100644
--- a/web/utils/imported-app-redirection.ts
+++ b/web/utils/imported-app-redirection.ts
@@ -1,5 +1,5 @@
import type { AppRedirectionTarget } from '@/utils/app-redirection'
-import { consoleClient } from '@/service/client'
+import { consoleClient } from '@/service/console'
import { AppModeEnum } from '@/types/app'
export const resolveImportedAppRedirectionTarget = async (