diff --git a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
index 80f9e243834..4b5f22a1c39 100644
--- a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx
@@ -3,6 +3,7 @@ import type { Credential, PluginPayload } from '../types'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { fireEvent, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { render } from '@/test/console/render'
import { AuthCategory, CredentialTypeEnum } from '../types'
@@ -44,14 +45,6 @@ const mockUserProfile = {
avatar_url: '',
}
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: mockUserProfile,
- isCurrentWorkspaceManager: mockIsCurrentWorkspaceManager(),
- workspacePermissionKeys: ['credential.use', 'credential.create', 'credential.manage'],
- }))
-})
vi.mock('@/context/workspace-state', async () => {
const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture')
return createWorkspaceStateModuleMock(() => ({
@@ -90,6 +83,7 @@ const createConsoleQueryClient = () =>
const createWrapper = () => {
const testQueryClient = createConsoleQueryClient()
+ seedAccountProfileQuery(testQueryClient, mockUserProfile)
return ({ children }: { children: ReactNode }) => (
{children}
)
diff --git a/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx b/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
index 42cbe046662..6490b85dc5a 100644
--- a/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/__tests__/api-key-modal.spec.tsx
@@ -6,7 +6,7 @@ import { fireEvent, screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import * as React from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { render } from '@/test/console/render'
+import { renderWithAccountProfile as render } from '@/test/console/account-profile'
import { AuthCategory } from '../../types'
const { mockToast } = vi.hoisted(() => {
@@ -32,10 +32,6 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
toast: mockToast,
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({ userProfile: {} }))
-})
const mockAddPluginCredential = vi.fn().mockResolvedValue({})
const mockUpdatePluginCredential = vi.fn().mockResolvedValue({})
const defaultCredentialSchemas = [
diff --git a/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx b/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
index 02e52ab0aaf..351a1d8920c 100644
--- a/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/__tests__/authorize-components.spec.tsx
@@ -1,22 +1,12 @@
import type { PluginPayload } from '../../types'
import type { FormSchema } from '@/app/components/base/form/types'
-import { QueryClient } from '@tanstack/react-query'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { createAccountProfileQueryClient } from '@/test/console/account-profile'
import { createQueryClientWrapper } from '@/test/console/query-client'
import { AuthCategory } from '../../types'
-const createWrapper = () =>
- createQueryClientWrapper(
- new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- gcTime: 0,
- },
- },
- }),
- )
+const createWrapper = () => createQueryClientWrapper(createAccountProfileQueryClient())
// Mock API hooks - these make network requests so must be mocked
const mockGetPluginOAuthUrl = vi.fn()
@@ -111,10 +101,6 @@ vi.mock('@langgenius/dify-ui/toast', () => ({
toast: mockToast,
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({ userProfile: {} }))
-})
// Factory function for creating test PluginPayload
const createPluginPayload = (overrides: Partial = {}): PluginPayload => ({
category: AuthCategory.tool,
diff --git a/web/app/components/plugins/plugin-auth/authorize/permission-selector.tsx b/web/app/components/plugins/plugin-auth/authorize/permission-selector.tsx
index 9292ebad2e0..f38c993bb06 100644
--- a/web/app/components/plugins/plugin-auth/authorize/permission-selector.tsx
+++ b/web/app/components/plugins/plugin-auth/authorize/permission-selector.tsx
@@ -8,9 +8,9 @@ import {
PopoverTrigger,
} from '@langgenius/dify-ui/popover'
import { RadioGroup, RadioItem } from '@langgenius/dify-ui/radio'
-import { useAtomValue } from 'jotai'
+import { useSuspenseQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
-import { userProfileAtom } from '@/context/account-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import { PermissionLevel } from '@/models/permission'
export type CredentialPermission =
@@ -28,7 +28,10 @@ const optionClassName =
const PermissionSelector = ({ disabled, permission, onChange }: PermissionSelectorProps) => {
const { t } = useTranslation()
- const userProfile = useAtomValue(userProfileAtom)
+ const { data: userProfile } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile,
+ })
const isOnlyMe = permission === PermissionLevel.onlyMe
const isAllTeamMembers = permission === PermissionLevel.allTeamMembers
const permissionLabel = t(($) => $['auth.whoCanUse'], { ns: 'plugin' })
diff --git a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
index 42e69745f7a..744bf4bd11c 100644
--- a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx
@@ -3,6 +3,7 @@ import type { Credential, PluginPayload } from '../../types'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { render } from '@/test/console/render'
import { AuthCategory, CredentialTypeEnum } from '../../types'
import Authorized from '../index'
@@ -87,13 +88,6 @@ const mockConsoleState = vi.hoisted(() => ({
workspacePermissionKeys: ['credential.use', 'credential.create', 'credential.manage'] as string[],
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: mockConsoleState.userProfile,
- workspacePermissionKeys: mockConsoleState.workspacePermissionKeys,
- }))
-})
vi.mock('@/context/permission-state', async () => {
const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture')
return createPermissionStateModuleMock(() => ({
@@ -137,6 +131,7 @@ const createConsoleQueryClient = () =>
const createWrapper = () => {
const testQueryClient = createConsoleQueryClient()
+ seedAccountProfileQuery(testQueryClient, mockConsoleState.userProfile)
return ({ children }: { children: ReactNode }) => (
{children}
)
diff --git a/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx b/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx
index 26cf90178a0..428004e16a2 100644
--- a/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx
+++ b/web/app/components/plugins/plugin-auth/authorized/__tests__/item.spec.tsx
@@ -1,17 +1,10 @@
import type { Credential } from '../../types'
import { cleanup, fireEvent, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import { render } from '@/test/console/render'
+import { renderWithAccountProfile as render } from '@/test/console/account-profile'
import { CredentialTypeEnum } from '../../types'
import Item from '../item'
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: { id: 'test-user' },
- workspacePermissionKeys: ['credential.use', 'credential.create', 'credential.manage'],
- }))
-})
vi.mock('@/context/permission-state', async () => {
const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture')
return createPermissionStateModuleMock(() => ({
diff --git a/web/app/components/plugins/plugin-auth/authorized/item.tsx b/web/app/components/plugins/plugin-auth/authorized/item.tsx
index f36119c14fa..a9f22472c65 100644
--- a/web/app/components/plugins/plugin-auth/authorized/item.tsx
+++ b/web/app/components/plugins/plugin-auth/authorized/item.tsx
@@ -4,13 +4,13 @@ import { cn } from '@langgenius/dify-ui/cn'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { RiInformationLine } from '@remixicon/react'
-import { useAtomValue } from 'jotai'
+import { useSuspenseQuery } from '@tanstack/react-query'
import { memo, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import Badge from '@/app/components/base/badge'
import Input from '@/app/components/base/input'
-import { userProfileIdAtom } from '@/context/account-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import { useCredentialPermissions } from '@/hooks/use-credential-permissions'
import { CredentialTypeEnum } from '../types'
@@ -50,7 +50,10 @@ const Item = ({
const { canUseCredential, canManageCredential } = useCredentialPermissions()
const isOAuth = credential.credential_type === CredentialTypeEnum.OAUTH2
const isPersonal = credential.visibility === 'only_me'
- const currentUserId = useAtomValue(userProfileIdAtom)
+ const { data: currentUserId } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile.id,
+ })
// Borrowed-from-teammate: the backend explicitly flagged this row as another member's
// only_me credential, returned only because the current node still references it.
// Fallback heuristic (created_by mismatch on a selected row) is kept for backends
diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
index 18e24b5f278..a5031c8963d 100644
--- a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
@@ -15,8 +15,8 @@ import {
} from '@langgenius/dify-ui/select'
import { Switch } from '@langgenius/dify-ui/switch'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
+import { useSuspenseQuery } from '@tanstack/react-query'
import { useBoolean } from 'ahooks'
-import { useAtomValue } from 'jotai'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Infotip } from '@/app/components/base/infotip'
@@ -33,7 +33,7 @@ import MixedVariableTextInput from '@/app/components/workflow/nodes/tool/compone
import ToolDatePicker from '@/app/components/workflow/nodes/tool/components/tool-date-picker'
import ToolDateRangePicker from '@/app/components/workflow/nodes/tool/components/tool-date-range-picker'
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
-import { userProfileAtom } from '@/context/account-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import {
createPickerProps,
getFieldFlags,
@@ -68,8 +68,10 @@ const ReasoningConfigForm: React.FC = ({
}) => {
const { t } = useTranslation()
const language = useLanguage()
- const userProfile = useAtomValue(userProfileAtom)
- const timezone = userProfile.timezone ?? 'UTC'
+ const { data: timezone } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile.timezone ?? 'UTC',
+ })
const handleAutomatic = (key: string, val: boolean, type: string) => {
onChange(updateInputAutoState(value, key, val, type))
diff --git a/web/app/components/tools/mcp/hooks/use-mcp-service-card.ts b/web/app/components/tools/mcp/hooks/use-mcp-service-card.ts
index b8acd9ff1f8..59a9c4ba132 100644
--- a/web/app/components/tools/mcp/hooks/use-mcp-service-card.ts
+++ b/web/app/components/tools/mcp/hooks/use-mcp-service-card.ts
@@ -1,12 +1,12 @@
'use client'
import type { AppDetailResponse } from '@/models/app'
import type { AppSSO } from '@/types/app'
-import { useQuery, useQueryClient } from '@tanstack/react-query'
+import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { useCallback, useMemo, useState } from 'react'
import { BlockEnum } from '@/app/components/workflow/types'
-import { userProfileIdAtom } from '@/context/account-state'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import { fetchAppDetail } from '@/service/apps'
import {
useInvalidateMCPServerDetail,
@@ -35,7 +35,10 @@ export const useMCPServiceCardState = (appInfo: AppInfo, triggerModeDisabled: bo
const { mutateAsync: updateMCPServer } = useUpdateMCPServer()
const { mutateAsync: refreshMCPServerCode, isPending: genLoading } = useRefreshMCPServerCode()
const invalidateMCPServerDetail = useInvalidateMCPServerDetail()
- const currentUserId = useAtomValue(userProfileIdAtom)
+ const { data: currentUserId } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile.id,
+ })
const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom)
const canManageMCP = useMemo(
diff --git a/web/context/account-state.ts b/web/context/account-state.ts
index 06879199ace..7d883ca5fb5 100644
--- a/web/context/account-state.ts
+++ b/web/context/account-state.ts
@@ -10,10 +10,6 @@ export const userProfileAtom = atom((get) => {
return get(accountProfileQueryAtom).data.profile
})
-export const userProfileIdAtom = atom((get) => {
- return get(userProfileAtom).id
-})
-
export const accountProfileMetaAtom = atom((get) => {
return get(accountProfileQueryAtom).data.meta
})
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 6d30a91dbcb..2aaff578db4 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
@@ -3,6 +3,7 @@ import type React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
+import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { seedSystemFeatures } from '@/test/console/query-data'
import { render } from '@/test/console/render'
import { ServiceApiAccessCard } from '../service-api-access-card'
@@ -44,21 +45,6 @@ vi.mock('@/hooks/use-timestamp', () => ({
}),
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: { id: 'user-1' },
- currentWorkspace: { id: 'workspace-1' },
- workspacePermissionKeys: ['app.acl.edit'],
- langGeniusVersionInfo: {
- current_env: 'PRODUCTION',
- current_version: '',
- latest_version: '',
- version: '',
- release_notes: '',
- },
- }))
-})
vi.mock('@/context/workspace-state', async () => {
const { createWorkspaceStateModuleMock } = await import('@/test/console/state-fixture')
return createWorkspaceStateModuleMock(() => ({
@@ -107,6 +93,13 @@ vi.mock('@/context/version-state', async () => {
vi.mock('@/service/client', () => ({
consoleQuery: {
+ account: {
+ profile: {
+ get: {
+ queryKey: () => [['console', 'account', 'profile', 'get'], { type: 'query' }],
+ },
+ },
+ },
systemFeatures: {
get: {
queryKey: () => ['system-features'],
@@ -256,6 +249,7 @@ function createConsoleQueryClient(webAppAuthEnabled = true) {
enabled: webAppAuthEnabled,
},
})
+ seedAccountProfileQuery(queryClient, { id: 'user-1' })
return queryClient
}
diff --git a/web/features/agent-v2/agent-detail/access/components/web-app-access-control-button.tsx b/web/features/agent-v2/agent-detail/access/components/web-app-access-control-button.tsx
index 0c954bd0386..4e53fddc851 100644
--- a/web/features/agent-v2/agent-detail/access/components/web-app-access-control-button.tsx
+++ b/web/features/agent-v2/agent-detail/access/components/web-app-access-control-button.tsx
@@ -6,8 +6,8 @@ import { useSuspenseQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { userProfileIdAtom } from '@/context/account-state'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { isAccessMode } from '@/models/access-control'
import dynamic from '@/next/dynamic'
@@ -27,7 +27,10 @@ export function WebAppAccessControlButton({ agent }: { agent?: AgentAppDetailWit
...systemFeaturesQueryOptions(),
select: (systemFeatures) => systemFeatures.webapp_auth.enabled,
})
- const currentUserId = useAtomValue(userProfileIdAtom)
+ const { data: currentUserId } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile.id,
+ })
const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom)
const { canReleaseAndVersion: canManageWebAppAccessControl } = getAppACLCapabilities(
agent?.permission_keys,
diff --git a/web/features/agent-v2/agent-detail/configure/components/orchestrate/tools/__tests__/index.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/orchestrate/tools/__tests__/index.spec.tsx
index 8b21b70d29a..d0ff3f728a9 100644
--- a/web/features/agent-v2/agent-detail/configure/components/orchestrate/tools/__tests__/index.spec.tsx
+++ b/web/features/agent-v2/agent-detail/configure/components/orchestrate/tools/__tests__/index.spec.tsx
@@ -15,6 +15,7 @@ import {
agentComposerSavedDraftAtom,
isAgentComposerDirtyAtom,
} from '@/features/agent-v2/agent-composer/store'
+import { seedAccountProfileQuery } from '@/test/console/account-profile'
import { AgentOrchestrateReadOnlyContext } from '../../read-only-context'
import { AgentTools } from '../index'
@@ -48,13 +49,6 @@ vi.mock('@/app/components/workflow/block-selector/tool-picker', () => ({
ToolPickerContent: () => Mock tool picker
,
}))
-vi.mock('@/context/account-state', async () => {
- const { atom } = await vi.importActual('jotai')
- return {
- userProfileIdAtom: atom('user-1'),
- }
-})
-
vi.mock('@/app/components/workflow/block-icon', () => ({
default: ({ toolIcon }: { toolIcon?: string | { content: string; background: string } }) => (
@@ -392,6 +386,7 @@ function renderAgentTools(initialDraft: AgentSoulConfigFormState = agentToolsDra
},
},
})
+ seedAccountProfileQuery(queryClient, { id: 'user-1' })
return render(
@@ -410,6 +405,7 @@ function renderAgentToolsWithStore(initialDraft: AgentSoulConfigFormState = agen
},
},
})
+ seedAccountProfileQuery(queryClient, { id: 'user-1' })
const store = createStore()
store.set(agentComposerDraftAtom, initialDraft)
store.set(agentComposerSavedDraftAtom, initialDraft)
@@ -436,6 +432,7 @@ function renderReadonlyAgentTools(initialDraft: AgentSoulConfigFormState = agent
},
},
})
+ seedAccountProfileQuery(queryClient, { id: 'user-1' })
return render(
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 98ddc319f76..308bd5a2761 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,6 +14,7 @@ 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 { seedAccountProfileQuery } from '@/test/console/account-profile'
import { render } from '@/test/console/render'
import { seedRegisteredConsoleStateFixture } from '@/test/console/state-fixture'
import { TransferMethod } from '@/types/app'
@@ -188,16 +189,6 @@ vi.mock('@/app/components/base/chat/chat/hooks', () => ({
),
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: {
- avatar_url: '',
- name: 'User',
- },
- }))
-})
-
vi.mock('@/app/components/header/account-setting/model-provider-page/hooks', () => ({
useTextGenerationCurrentProviderAndModelAndModelList: () => ({
textGenerationModelList: [
@@ -239,6 +230,13 @@ vi.mock('@/service/client', async () => {
},
},
consoleQuery: {
+ account: {
+ profile: {
+ get: {
+ queryKey: () => [['console', 'account', 'profile', 'get'], { type: 'query' }],
+ },
+ },
+ },
agent: {
byAgentId: {
chatMessages: {
@@ -275,6 +273,7 @@ function renderPreviewChat(
},
},
})
+ seedAccountProfileQuery(queryClient, { avatar_url: '', name: 'User' })
store.set(agentComposerModelAtom, {
provider: 'openai',
model: 'gpt-4',
@@ -349,6 +348,7 @@ function renderPreviewChatWithConversationHarness() {
},
},
})
+ seedAccountProfileQuery(queryClient, { avatar_url: '', name: 'User' })
store.set(agentComposerModelAtom, {
provider: 'openai',
model: 'gpt-4',
@@ -374,6 +374,7 @@ function renderPreviewChatWithClearCommandHarness() {
},
},
})
+ seedAccountProfileQuery(queryClient, { avatar_url: '', name: 'User' })
store.set(agentComposerModelAtom, {
provider: 'openai',
model: 'gpt-4',
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 90173d2bb80..d37e7174589 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
@@ -1,6 +1,6 @@
import type { AgentConfigSnapshotSummaryResponse } from '@dify/contracts/api/console/agent/types.gen'
import { fireEvent, screen } from '@testing-library/react'
-import { render } from '@/test/console/render'
+import { renderWithAccountProfile as render } from '@/test/console/account-profile'
import { AgentPreviewVersionsPanel } from '../versions-panel'
const versions: AgentConfigSnapshotSummaryResponse[] = [
@@ -47,6 +47,13 @@ vi.mock('@/hooks/use-timestamp', () => ({
vi.mock('@/service/client', () => ({
consoleQuery: {
+ account: {
+ profile: {
+ get: {
+ queryKey: () => [['console', 'account', 'profile', 'get'], { type: 'query' }],
+ },
+ },
+ },
agent: {
byAgentId: {
versions: {
@@ -59,17 +66,6 @@ vi.mock('@/service/client', () => ({
},
}))
-vi.mock('@/context/account-state', async () => {
- const { createAccountStateModuleMock } = await import('@/test/console/state-fixture')
- return createAccountStateModuleMock(() => ({
- userProfile: {
- id: 'user-1',
- name: 'Alice',
- email: 'alice@example.com',
- },
- }))
-})
-
describe('AgentPreviewVersionsPanel', () => {
beforeEach(() => {
vi.clearAllMocks()
@@ -86,6 +82,7 @@ describe('AgentPreviewVersionsPanel', () => {
onSelectVersion={handleSelectVersion}
onClose={vi.fn()}
/>,
+ { accountProfile: { id: 'user-1', name: 'Alice', email: 'alice@example.com' } },
)
fireEvent.click(screen.getByRole('button', { name: /Initial release/i }))
@@ -103,6 +100,7 @@ describe('AgentPreviewVersionsPanel', () => {
onSelectVersion={handleSelectVersion}
onClose={vi.fn()}
/>,
+ { accountProfile: { id: 'user-1', name: 'Alice', email: 'alice@example.com' } },
)
fireEvent.click(screen.getByRole('button', { name: /currentDraft/i }))
@@ -120,6 +118,7 @@ describe('AgentPreviewVersionsPanel', () => {
onSelectVersion={vi.fn()}
onClose={vi.fn()}
/>,
+ { accountProfile: { id: 'user-1', name: 'Alice', email: 'alice@example.com' } },
)
fireEvent.click(screen.getByRole('button', { name: /filter/i }))
@@ -137,6 +136,7 @@ describe('AgentPreviewVersionsPanel', () => {
onSelectVersion={vi.fn()}
onClose={vi.fn()}
/>,
+ { accountProfile: { id: 'user-1', name: 'Alice', email: 'alice@example.com' } },
)
fireEvent.click(screen.getByRole('button', { name: /filter/i }))
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 a8d60958fbb..9f6ea73931f 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
@@ -13,8 +13,7 @@ import type { Inputs } from '@/models/debug'
import { Avatar } from '@langgenius/dify-ui/avatar'
import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
-import { useQueryClient } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
+import { useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
import { useCallback, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { AgentRosterResponseContent } from '@/app/components/base/chat/chat/answer/agent-roster-response-content'
@@ -22,8 +21,8 @@ import { useChat } from '@/app/components/base/chat/chat/hooks'
import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/chat/utils'
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useTextGenerationCurrentProviderAndModelAndModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
-import { userProfileAtom } from '@/context/account-state'
import { useDocLink } from '@/context/i18n'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import dynamic from '@/next/dynamic'
import { consoleClient, consoleQuery } from '@/service/client'
import { buildChatConfig, getAgentSoulInputs, getAgentSoulInputsForm } from './chat-config'
@@ -124,7 +123,10 @@ export function AgentPreviewChatConversation({
const { t } = useTranslation('agentV2')
const docLink = useDocLink()
const queryClient = useQueryClient()
- const userProfile = useAtomValue(userProfileAtom)
+ const { data: userProfile } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile,
+ })
const sendInterruptedRef = useRef(false)
const [isSendPending, setIsSendPending] = useState(false)
const notifySendInterrupted = useCallback(() => {
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 718a61e93f6..3dc6a867964 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
@@ -1,11 +1,10 @@
'use client'
import type { AgentVersionFilter } from './filter'
-import { useQuery } from '@tanstack/react-query'
-import { useAtomValue } from 'jotai'
+import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { userProfileAtom } from '@/context/account-state'
+import { userProfileQueryOptions } from '@/features/account-profile/client'
import { consoleQuery } from '@/service/client'
import { CurrentDraftItem } from './current-draft-item'
import { VersionFilter } from './filter'
@@ -28,7 +27,10 @@ export function AgentPreviewVersionsPanel({
const { t } = useTranslation('agentV2')
const { t: tCommon } = useTranslation('common')
const { t: tWorkflow } = useTranslation('workflow')
- const userProfile = useAtomValue(userProfileAtom)
+ const { data: userProfile } = useSuspenseQuery({
+ ...userProfileQueryOptions(),
+ select: (data) => data.profile,
+ })
const [filterValue, setFilterValue] = useState('all')
const versionsQuery = useQuery(
consoleQuery.agent.byAgentId.versions.get.queryOptions({