mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 09:58:04 +08:00
Merge commit '92bde350' into sandboxed-agent-rebase
Made-with: Cursor # Conflicts: # api/controllers/console/app/workflow_draft_variable.py # api/core/agent/cot_agent_runner.py # api/core/agent/cot_chat_agent_runner.py # api/core/agent/cot_completion_agent_runner.py # api/core/agent/fc_agent_runner.py # api/core/app/apps/advanced_chat/app_generator.py # api/core/app/apps/advanced_chat/app_runner.py # api/core/app/apps/agent_chat/app_runner.py # api/core/app/apps/workflow/app_generator.py # api/core/app/apps/workflow/app_runner.py # api/core/app/entities/app_invoke_entities.py # api/core/app/entities/queue_entities.py # api/core/llm_generator/output_parser/structured_output.py # api/core/workflow/workflow_entry.py # api/dify_graph/context/__init__.py # api/dify_graph/entities/tool_entities.py # api/dify_graph/file/file_manager.py # api/dify_graph/graph_engine/response_coordinator/coordinator.py # api/dify_graph/graph_events/node.py # api/dify_graph/node_events/node.py # api/dify_graph/nodes/agent/agent_node.py # api/dify_graph/nodes/llm/entities.py # api/dify_graph/nodes/llm/llm_utils.py # api/dify_graph/nodes/llm/node.py # api/dify_graph/nodes/question_classifier/question_classifier_node.py # api/dify_graph/runtime/graph_runtime_state.py # api/dify_graph/variables/segments.py # api/factories/variable_factory.py # api/services/variable_truncator.py # api/tests/unit_tests/utils/structured_output_parser/test_structured_output_parser.py # api/uv.lock # web/app/components/app-sidebar/app-info.tsx # web/app/components/app-sidebar/app-sidebar-dropdown.tsx # web/app/components/app/create-app-modal/index.spec.tsx # web/app/components/apps/__tests__/list.spec.tsx # web/app/components/apps/app-card.tsx # web/app/components/apps/list.tsx # web/app/components/header/account-dropdown/compliance.tsx # web/app/components/header/account-dropdown/index.tsx # web/app/components/header/account-dropdown/support.tsx # web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx # web/app/components/workflow/panel/debug-and-preview/hooks.ts # web/contract/console/apps.ts # web/contract/router.ts # web/eslint-suppressions.json # web/next.config.ts # web/pnpm-lock.yaml
This commit is contained in:
@ -3,13 +3,18 @@
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
import { setUserId, setUserProperties } from '@/app/components/base/amplitude'
|
||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||
import { ZENDESK_FIELD_IDS } from '@/config'
|
||||
import {
|
||||
AppContext,
|
||||
initialLangGeniusVersionInfo,
|
||||
initialWorkspaceInfo,
|
||||
userProfilePlaceholder,
|
||||
useSelector,
|
||||
} from '@/context/app-context'
|
||||
import { env } from '@/env'
|
||||
import {
|
||||
useCurrentWorkspace,
|
||||
@ -18,72 +23,6 @@ import {
|
||||
} from '@/service/use-common'
|
||||
import { useGlobalPublicStore } from './global-public-context'
|
||||
|
||||
export type AppContextValue = {
|
||||
userProfile: UserProfileResponse
|
||||
mutateUserProfile: VoidFunction
|
||||
currentWorkspace: ICurrentWorkspace
|
||||
isCurrentWorkspaceManager: boolean
|
||||
isCurrentWorkspaceOwner: boolean
|
||||
isCurrentWorkspaceEditor: boolean
|
||||
isCurrentWorkspaceDatasetOperator: boolean
|
||||
mutateCurrentWorkspace: VoidFunction
|
||||
langGeniusVersionInfo: LangGeniusVersionResponse
|
||||
useSelector: typeof useSelector
|
||||
isLoadingCurrentWorkspace: boolean
|
||||
isValidatingCurrentWorkspace: boolean
|
||||
}
|
||||
|
||||
const userProfilePlaceholder = {
|
||||
id: '',
|
||||
name: '',
|
||||
email: '',
|
||||
avatar: '',
|
||||
avatar_url: '',
|
||||
is_password_set: false,
|
||||
}
|
||||
|
||||
const initialLangGeniusVersionInfo = {
|
||||
current_env: '',
|
||||
current_version: '',
|
||||
latest_version: '',
|
||||
release_date: '',
|
||||
release_notes: '',
|
||||
version: '',
|
||||
can_auto_update: false,
|
||||
}
|
||||
|
||||
const initialWorkspaceInfo: ICurrentWorkspace = {
|
||||
id: '',
|
||||
name: '',
|
||||
plan: '',
|
||||
status: '',
|
||||
created_at: 0,
|
||||
role: 'normal',
|
||||
providers: [],
|
||||
trial_credits: 200,
|
||||
trial_credits_used: 0,
|
||||
next_credit_reset_date: 0,
|
||||
}
|
||||
|
||||
const AppContext = createContext<AppContextValue>({
|
||||
userProfile: userProfilePlaceholder,
|
||||
currentWorkspace: initialWorkspaceInfo,
|
||||
isCurrentWorkspaceManager: false,
|
||||
isCurrentWorkspaceOwner: false,
|
||||
isCurrentWorkspaceEditor: false,
|
||||
isCurrentWorkspaceDatasetOperator: false,
|
||||
mutateUserProfile: noop,
|
||||
mutateCurrentWorkspace: noop,
|
||||
langGeniusVersionInfo: initialLangGeniusVersionInfo,
|
||||
useSelector,
|
||||
isLoadingCurrentWorkspace: false,
|
||||
isValidatingCurrentWorkspace: false,
|
||||
})
|
||||
|
||||
export function useSelector<T>(selector: (value: AppContextValue) => T): T {
|
||||
return useContextSelector(AppContext, selector)
|
||||
}
|
||||
|
||||
export type AppContextProviderProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
@ -170,7 +109,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
||||
// Report user and workspace info to Amplitude when loaded
|
||||
if (userProfile?.id) {
|
||||
setUserId(userProfile.email)
|
||||
const properties: Record<string, any> = {
|
||||
const properties: Record<string, string | number | boolean> = {
|
||||
email: userProfile.email,
|
||||
name: userProfile.name,
|
||||
has_password: userProfile.is_password_set,
|
||||
@ -213,7 +152,3 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
||||
</AppContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAppContext = () => useContext(AppContext)
|
||||
|
||||
export default AppContext
|
||||
73
web/context/app-context.ts
Normal file
73
web/context/app-context.ts
Normal file
@ -0,0 +1,73 @@
|
||||
'use client'
|
||||
|
||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
|
||||
export type AppContextValue = {
|
||||
userProfile: UserProfileResponse
|
||||
mutateUserProfile: VoidFunction
|
||||
currentWorkspace: ICurrentWorkspace
|
||||
isCurrentWorkspaceManager: boolean
|
||||
isCurrentWorkspaceOwner: boolean
|
||||
isCurrentWorkspaceEditor: boolean
|
||||
isCurrentWorkspaceDatasetOperator: boolean
|
||||
mutateCurrentWorkspace: VoidFunction
|
||||
langGeniusVersionInfo: LangGeniusVersionResponse
|
||||
useSelector: typeof useSelector
|
||||
isLoadingCurrentWorkspace: boolean
|
||||
isValidatingCurrentWorkspace: boolean
|
||||
}
|
||||
|
||||
export const userProfilePlaceholder = {
|
||||
id: '',
|
||||
name: '',
|
||||
email: '',
|
||||
avatar: '',
|
||||
avatar_url: '',
|
||||
is_password_set: false,
|
||||
}
|
||||
|
||||
export const initialLangGeniusVersionInfo = {
|
||||
current_env: '',
|
||||
current_version: '',
|
||||
latest_version: '',
|
||||
release_date: '',
|
||||
release_notes: '',
|
||||
version: '',
|
||||
can_auto_update: false,
|
||||
}
|
||||
|
||||
export const initialWorkspaceInfo: ICurrentWorkspace = {
|
||||
id: '',
|
||||
name: '',
|
||||
plan: '',
|
||||
status: '',
|
||||
created_at: 0,
|
||||
role: 'normal',
|
||||
providers: [],
|
||||
trial_credits: 200,
|
||||
trial_credits_used: 0,
|
||||
next_credit_reset_date: 0,
|
||||
}
|
||||
|
||||
export const AppContext = createContext<AppContextValue>({
|
||||
userProfile: userProfilePlaceholder,
|
||||
currentWorkspace: initialWorkspaceInfo,
|
||||
isCurrentWorkspaceManager: false,
|
||||
isCurrentWorkspaceOwner: false,
|
||||
isCurrentWorkspaceEditor: false,
|
||||
isCurrentWorkspaceDatasetOperator: false,
|
||||
mutateUserProfile: noop,
|
||||
mutateCurrentWorkspace: noop,
|
||||
langGeniusVersionInfo: initialLangGeniusVersionInfo,
|
||||
useSelector,
|
||||
isLoadingCurrentWorkspace: false,
|
||||
isValidatingCurrentWorkspace: false,
|
||||
})
|
||||
|
||||
export function useSelector<T>(selector: (value: AppContextValue) => T): T {
|
||||
return useContextSelector(AppContext, selector)
|
||||
}
|
||||
|
||||
export const useAppContext = () => useContext(AppContext)
|
||||
22
web/context/event-emitter-provider.tsx
Normal file
22
web/context/event-emitter-provider.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
'use client'
|
||||
|
||||
import type { ReactNode } from 'react'
|
||||
import type { EventEmitterValue } from './event-emitter'
|
||||
import { useEventEmitter } from 'ahooks'
|
||||
import { EventEmitterContext } from './event-emitter'
|
||||
|
||||
type EventEmitterContextProviderProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const EventEmitterContextProvider = ({
|
||||
children,
|
||||
}: EventEmitterContextProviderProps) => {
|
||||
const eventEmitter = useEventEmitter<EventEmitterValue>()
|
||||
|
||||
return (
|
||||
<EventEmitterContext.Provider value={{ eventEmitter }}>
|
||||
{children}
|
||||
</EventEmitterContext.Provider>
|
||||
)
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { EventEmitter } from 'ahooks/lib/useEventEmitter'
|
||||
import { useEventEmitter } from 'ahooks'
|
||||
import { createContext, useContext } from 'use-context-selector'
|
||||
|
||||
/**
|
||||
@ -17,25 +16,10 @@ export type EventEmitterMessage = {
|
||||
export type EventEmitterValue = string | EventEmitterMessage
|
||||
export type EventPayload = EventEmitterValue
|
||||
|
||||
const EventEmitterContext = createContext<{ eventEmitter: EventEmitter<EventEmitterValue> | null }>({
|
||||
export const EventEmitterContext = createContext<{ eventEmitter: EventEmitter<EventEmitterValue> | null }>({
|
||||
eventEmitter: null,
|
||||
})
|
||||
|
||||
export const useEventEmitterContextContext = () => useContext(EventEmitterContext)
|
||||
|
||||
type EventEmitterContextProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
export const EventEmitterContextProvider = ({
|
||||
children,
|
||||
}: EventEmitterContextProviderProps) => {
|
||||
const eventEmitter = useEventEmitter<EventEmitterValue>()
|
||||
|
||||
return (
|
||||
<EventEmitterContext.Provider value={{ eventEmitter }}>
|
||||
{children}
|
||||
</EventEmitterContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default EventEmitterContext
|
||||
19
web/context/mitt-context-provider.tsx
Normal file
19
web/context/mitt-context-provider.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
'use client'
|
||||
|
||||
import type { ReactNode } from 'react'
|
||||
import { useMitt } from '@/hooks/use-mitt'
|
||||
import { MittContext } from './mitt-context'
|
||||
|
||||
type MittProviderProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const MittProvider = ({ children }: MittProviderProps) => {
|
||||
const mitt = useMitt()
|
||||
|
||||
return (
|
||||
<MittContext.Provider value={mitt}>
|
||||
{children}
|
||||
</MittContext.Provider>
|
||||
)
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
'use client'
|
||||
|
||||
import type { useMitt } from '@/hooks/use-mitt'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
import { useMitt } from '@/hooks/use-mitt'
|
||||
|
||||
type ContextValueType = ReturnType<typeof useMitt>
|
||||
export const MittContext = createContext<ContextValueType>({
|
||||
@ -8,16 +10,6 @@ export const MittContext = createContext<ContextValueType>({
|
||||
useSubscribe: noop,
|
||||
})
|
||||
|
||||
export const MittProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const mitt = useMitt()
|
||||
|
||||
return (
|
||||
<MittContext.Provider value={mitt}>
|
||||
{children}
|
||||
</MittContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useMittContext = () => {
|
||||
return useContext(MittContext)
|
||||
}
|
||||
@ -1,32 +1,20 @@
|
||||
'use client'
|
||||
|
||||
import type { Dispatch, SetStateAction } from 'react'
|
||||
import type { TriggerEventsLimitModalPayload } from './hooks/use-trigger-events-limit-modal'
|
||||
import type { ReactNode, SetStateAction } from 'react'
|
||||
import type { ModalState, ModelModalType } from './modal-context'
|
||||
import type { OpeningStatement } from '@/app/components/base/features/types'
|
||||
import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
|
||||
import type { AccountSettingTab } from '@/app/components/header/account-setting/constants'
|
||||
import type {
|
||||
ConfigurationMethodEnum,
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
ModelModalModeEnum,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
|
||||
import type { UpdatePluginPayload } from '@/app/components/plugins/types'
|
||||
import type { InputVar } from '@/app/components/workflow/types'
|
||||
import type { ExpireNoticeModalPayloadProps } from '@/app/education-apply/expire-notice-modal'
|
||||
import type {
|
||||
ApiBasedExtension,
|
||||
ExternalDataTool,
|
||||
} from '@/models/common'
|
||||
import type { ApiBasedExtension, ExternalDataTool } from '@/models/common'
|
||||
import type { ModerationConfig, PromptVariable } from '@/models/debug'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
import {
|
||||
|
||||
DEFAULT_ACCOUNT_SETTING_TAB,
|
||||
isValidAccountSettingTab,
|
||||
} from '@/app/components/header/account-setting/constants'
|
||||
@ -39,11 +27,10 @@ import {
|
||||
useAccountSettingModal,
|
||||
usePricingModal,
|
||||
} from '@/hooks/use-query-params'
|
||||
|
||||
import { useTriggerEventsLimitModal } from './hooks/use-trigger-events-limit-modal'
|
||||
import {
|
||||
|
||||
useTriggerEventsLimitModal,
|
||||
} from './hooks/use-trigger-events-limit-modal'
|
||||
ModalContext,
|
||||
} from './modal-context'
|
||||
|
||||
const AccountSetting = dynamic(() => import('@/app/components/header/account-setting'), {
|
||||
ssr: false,
|
||||
@ -86,79 +73,15 @@ const TriggerEventsLimitModal = dynamic(() => import('@/app/components/billing/t
|
||||
ssr: false,
|
||||
})
|
||||
|
||||
export type ModalState<T> = {
|
||||
payload: T
|
||||
onCancelCallback?: () => void
|
||||
onSaveCallback?: (newPayload?: T, formValues?: Record<string, any>) => void
|
||||
onRemoveCallback?: (newPayload?: T, formValues?: Record<string, any>) => void
|
||||
onEditCallback?: (newPayload: T) => void
|
||||
onValidateBeforeSaveCallback?: (newPayload: T) => boolean
|
||||
isEditMode?: boolean
|
||||
datasetBindings?: { id: string, name: string }[]
|
||||
}
|
||||
|
||||
export type ModelModalType = {
|
||||
currentProvider: ModelProvider
|
||||
currentConfigurationMethod: ConfigurationMethodEnum
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
|
||||
isModelCredential?: boolean
|
||||
credential?: Credential
|
||||
model?: CustomModel
|
||||
mode?: ModelModalModeEnum
|
||||
}
|
||||
|
||||
export type ModalContextState = {
|
||||
setShowAccountSettingModal: Dispatch<SetStateAction<ModalState<AccountSettingTab> | null>>
|
||||
setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>>
|
||||
setShowModerationSettingModal: Dispatch<SetStateAction<ModalState<ModerationConfig> | null>>
|
||||
setShowExternalDataToolModal: Dispatch<SetStateAction<ModalState<ExternalDataTool> | null>>
|
||||
setShowPricingModal: () => void
|
||||
setShowAnnotationFullModal: () => void
|
||||
setShowModelModal: Dispatch<SetStateAction<ModalState<ModelModalType> | null>>
|
||||
setShowExternalKnowledgeAPIModal: Dispatch<SetStateAction<ModalState<CreateExternalAPIReq> | null>>
|
||||
setShowModelLoadBalancingModal: Dispatch<SetStateAction<ModelLoadBalancingModalProps | null>>
|
||||
setShowOpeningModal: Dispatch<SetStateAction<ModalState<OpeningStatement & {
|
||||
promptVariables?: PromptVariable[]
|
||||
workflowVariables?: InputVar[]
|
||||
onAutoAddPromptVariable?: (variable: PromptVariable[]) => void
|
||||
}> | null>>
|
||||
setShowUpdatePluginModal: Dispatch<SetStateAction<ModalState<UpdatePluginPayload> | null>>
|
||||
setShowEducationExpireNoticeModal: Dispatch<SetStateAction<ModalState<ExpireNoticeModalPayloadProps> | null>>
|
||||
setShowTriggerEventsLimitModal: Dispatch<SetStateAction<ModalState<TriggerEventsLimitModalPayload> | null>>
|
||||
}
|
||||
|
||||
const ModalContext = createContext<ModalContextState>({
|
||||
setShowAccountSettingModal: noop,
|
||||
setShowApiBasedExtensionModal: noop,
|
||||
setShowModerationSettingModal: noop,
|
||||
setShowExternalDataToolModal: noop,
|
||||
setShowPricingModal: noop,
|
||||
setShowAnnotationFullModal: noop,
|
||||
setShowModelModal: noop,
|
||||
setShowExternalKnowledgeAPIModal: noop,
|
||||
setShowModelLoadBalancingModal: noop,
|
||||
setShowOpeningModal: noop,
|
||||
setShowUpdatePluginModal: noop,
|
||||
setShowEducationExpireNoticeModal: noop,
|
||||
setShowTriggerEventsLimitModal: noop,
|
||||
})
|
||||
|
||||
export const useModalContext = () => useContext(ModalContext)
|
||||
|
||||
// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
|
||||
// https://github.com/microsoft/TypeScript/issues/15713
|
||||
export const useModalContextSelector = <T,>(selector: (state: ModalContextState) => T): T =>
|
||||
useContextSelector(ModalContext, selector)
|
||||
|
||||
type ModalContextProviderProps = {
|
||||
children: React.ReactNode
|
||||
children: ReactNode
|
||||
}
|
||||
export const ModalContextProvider = ({
|
||||
children,
|
||||
}: ModalContextProviderProps) => {
|
||||
// Use nuqs hooks for URL-based modal state management
|
||||
const [showPricingModal, setPricingModalOpen] = usePricingModal()
|
||||
const [urlAccountModalState, setUrlAccountModalState] = useAccountSettingModal<AccountSettingTab>()
|
||||
const [urlAccountModalState, setUrlAccountModalState] = useAccountSettingModal()
|
||||
|
||||
const accountSettingCallbacksRef = useRef<Omit<ModalState<AccountSettingTab>, 'payload'> | null>(null)
|
||||
const accountSettingTab = urlAccountModalState.isOpen
|
||||
@ -1,9 +1,9 @@
|
||||
import { act, render, screen, waitFor } from '@testing-library/react'
|
||||
import { NuqsTestingAdapter } from 'nuqs/adapters/testing'
|
||||
import { act, screen, waitFor } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
import { defaultPlan } from '@/app/components/billing/config'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import { ModalContextProvider } from '@/context/modal-context'
|
||||
import { ModalContextProvider } from '@/context/modal-context-provider'
|
||||
import { renderWithNuqs } from '@/test/nuqs-testing'
|
||||
|
||||
vi.mock('@/config', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/config')>()
|
||||
@ -71,12 +71,10 @@ const createPlan = (overrides: PlanOverrides = {}): PlanShape => ({
|
||||
},
|
||||
})
|
||||
|
||||
const renderProvider = () => render(
|
||||
<NuqsTestingAdapter>
|
||||
<ModalContextProvider>
|
||||
<div data-testid="modal-context-test-child" />
|
||||
</ModalContextProvider>
|
||||
</NuqsTestingAdapter>,
|
||||
const renderProvider = () => renderWithNuqs(
|
||||
<ModalContextProvider>
|
||||
<div data-testid="modal-context-test-child" />
|
||||
</ModalContextProvider>,
|
||||
)
|
||||
|
||||
describe('ModalContextProvider trigger events limit modal', () => {
|
||||
|
||||
92
web/context/modal-context.ts
Normal file
92
web/context/modal-context.ts
Normal file
@ -0,0 +1,92 @@
|
||||
'use client'
|
||||
|
||||
import type { Dispatch, SetStateAction } from 'react'
|
||||
import type { TriggerEventsLimitModalPayload } from './hooks/use-trigger-events-limit-modal'
|
||||
import type { OpeningStatement } from '@/app/components/base/features/types'
|
||||
import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
|
||||
import type { AccountSettingTab } from '@/app/components/header/account-setting/constants'
|
||||
import type {
|
||||
ConfigurationMethodEnum,
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
ModelModalModeEnum,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
|
||||
import type { UpdatePluginPayload } from '@/app/components/plugins/types'
|
||||
import type { InputVar } from '@/app/components/workflow/types'
|
||||
import type { ExpireNoticeModalPayloadProps } from '@/app/education-apply/expire-notice-modal'
|
||||
import type {
|
||||
ApiBasedExtension,
|
||||
ExternalDataTool,
|
||||
} from '@/models/common'
|
||||
import type { ModerationConfig, PromptVariable } from '@/models/debug'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
|
||||
export type ModalState<T> = {
|
||||
payload: T
|
||||
onCancelCallback?: () => void
|
||||
onSaveCallback?: (newPayload?: T, formValues?: Record<string, any>) => void
|
||||
onRemoveCallback?: (newPayload?: T, formValues?: Record<string, any>) => void
|
||||
onEditCallback?: (newPayload: T) => void
|
||||
onValidateBeforeSaveCallback?: (newPayload: T) => boolean
|
||||
isEditMode?: boolean
|
||||
datasetBindings?: { id: string, name: string }[]
|
||||
}
|
||||
|
||||
export type ModelModalType = {
|
||||
currentProvider: ModelProvider
|
||||
currentConfigurationMethod: ConfigurationMethodEnum
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
|
||||
isModelCredential?: boolean
|
||||
credential?: Credential
|
||||
model?: CustomModel
|
||||
mode?: ModelModalModeEnum
|
||||
}
|
||||
|
||||
export type ModalContextState = {
|
||||
setShowAccountSettingModal: Dispatch<SetStateAction<ModalState<AccountSettingTab> | null>>
|
||||
setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>>
|
||||
setShowModerationSettingModal: Dispatch<SetStateAction<ModalState<ModerationConfig> | null>>
|
||||
setShowExternalDataToolModal: Dispatch<SetStateAction<ModalState<ExternalDataTool> | null>>
|
||||
setShowPricingModal: () => void
|
||||
setShowAnnotationFullModal: () => void
|
||||
setShowModelModal: Dispatch<SetStateAction<ModalState<ModelModalType> | null>>
|
||||
setShowExternalKnowledgeAPIModal: Dispatch<SetStateAction<ModalState<CreateExternalAPIReq> | null>>
|
||||
setShowModelLoadBalancingModal: Dispatch<SetStateAction<ModelLoadBalancingModalProps | null>>
|
||||
setShowOpeningModal: Dispatch<SetStateAction<ModalState<OpeningStatement & {
|
||||
promptVariables?: PromptVariable[]
|
||||
workflowVariables?: InputVar[]
|
||||
onAutoAddPromptVariable?: (variable: PromptVariable[]) => void
|
||||
}> | null>>
|
||||
setShowUpdatePluginModal: Dispatch<SetStateAction<ModalState<UpdatePluginPayload> | null>>
|
||||
setShowEducationExpireNoticeModal: Dispatch<SetStateAction<ModalState<ExpireNoticeModalPayloadProps> | null>>
|
||||
setShowTriggerEventsLimitModal: Dispatch<SetStateAction<ModalState<TriggerEventsLimitModalPayload> | null>>
|
||||
}
|
||||
|
||||
export const ModalContext = createContext<ModalContextState>({
|
||||
setShowAccountSettingModal: noop,
|
||||
setShowApiBasedExtensionModal: noop,
|
||||
setShowModerationSettingModal: noop,
|
||||
setShowExternalDataToolModal: noop,
|
||||
setShowPricingModal: noop,
|
||||
setShowAnnotationFullModal: noop,
|
||||
setShowModelModal: noop,
|
||||
setShowExternalKnowledgeAPIModal: noop,
|
||||
setShowModelLoadBalancingModal: noop,
|
||||
setShowOpeningModal: noop,
|
||||
setShowUpdatePluginModal: noop,
|
||||
setShowEducationExpireNoticeModal: noop,
|
||||
setShowTriggerEventsLimitModal: noop,
|
||||
})
|
||||
|
||||
export const useModalContext = () => useContext(ModalContext)
|
||||
|
||||
// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
|
||||
// https://github.com/microsoft/TypeScript/issues/15713
|
||||
export const useModalContextSelector = <T>(selector: (state: ModalContextState) => T): T =>
|
||||
useContextSelector(ModalContext, selector)
|
||||
|
||||
export default ModalContext
|
||||
@ -1,14 +1,10 @@
|
||||
'use client'
|
||||
|
||||
import type { Plan, UsagePlanInfo, UsageResetInfo } from '@/app/components/billing/type'
|
||||
import type { Model, ModelProvider } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { RETRIEVE_METHOD } from '@/types/app'
|
||||
import type { ReactNode } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import dayjs from 'dayjs'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||
import { defaultPlan } from '@/app/components/billing/config'
|
||||
@ -25,93 +21,13 @@ import {
|
||||
useModelProviders,
|
||||
useSupportRetrievalMethods,
|
||||
} from '@/service/use-common'
|
||||
import {
|
||||
useEducationStatus,
|
||||
} from '@/service/use-education'
|
||||
|
||||
export type ProviderContextState = {
|
||||
modelProviders: ModelProvider[]
|
||||
refreshModelProviders: () => void
|
||||
textGenerationModelList: Model[]
|
||||
supportRetrievalMethods: RETRIEVE_METHOD[]
|
||||
isAPIKeySet: boolean
|
||||
plan: {
|
||||
type: Plan
|
||||
usage: UsagePlanInfo
|
||||
total: UsagePlanInfo
|
||||
reset: UsageResetInfo
|
||||
}
|
||||
isFetchedPlan: boolean
|
||||
enableBilling: boolean
|
||||
onPlanInfoChanged: () => void
|
||||
enableReplaceWebAppLogo: boolean
|
||||
modelLoadBalancingEnabled: boolean
|
||||
datasetOperatorEnabled: boolean
|
||||
enableEducationPlan: boolean
|
||||
isEducationWorkspace: boolean
|
||||
isEducationAccount: boolean
|
||||
allowRefreshEducationVerify: boolean
|
||||
educationAccountExpireAt: number | null
|
||||
isLoadingEducationAccountInfo: boolean
|
||||
isFetchingEducationAccountInfo: boolean
|
||||
webappCopyrightEnabled: boolean
|
||||
licenseLimit: {
|
||||
workspace_members: {
|
||||
size: number
|
||||
limit: number
|
||||
}
|
||||
}
|
||||
refreshLicenseLimit: () => void
|
||||
isAllowTransferWorkspace: boolean
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: boolean
|
||||
humanInputEmailDeliveryEnabled: boolean
|
||||
}
|
||||
|
||||
export const baseProviderContextValue: ProviderContextState = {
|
||||
modelProviders: [],
|
||||
refreshModelProviders: noop,
|
||||
textGenerationModelList: [],
|
||||
supportRetrievalMethods: [],
|
||||
isAPIKeySet: true,
|
||||
plan: defaultPlan,
|
||||
isFetchedPlan: false,
|
||||
enableBilling: false,
|
||||
onPlanInfoChanged: noop,
|
||||
enableReplaceWebAppLogo: false,
|
||||
modelLoadBalancingEnabled: false,
|
||||
datasetOperatorEnabled: false,
|
||||
enableEducationPlan: false,
|
||||
isEducationWorkspace: false,
|
||||
isEducationAccount: false,
|
||||
allowRefreshEducationVerify: false,
|
||||
educationAccountExpireAt: null,
|
||||
isLoadingEducationAccountInfo: false,
|
||||
isFetchingEducationAccountInfo: false,
|
||||
webappCopyrightEnabled: false,
|
||||
licenseLimit: {
|
||||
workspace_members: {
|
||||
size: 0,
|
||||
limit: 0,
|
||||
},
|
||||
},
|
||||
refreshLicenseLimit: noop,
|
||||
isAllowTransferWorkspace: false,
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: false,
|
||||
humanInputEmailDeliveryEnabled: false,
|
||||
}
|
||||
|
||||
const ProviderContext = createContext<ProviderContextState>(baseProviderContextValue)
|
||||
|
||||
export const useProviderContext = () => useContext(ProviderContext)
|
||||
|
||||
// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
|
||||
// https://github.com/microsoft/TypeScript/issues/15713
|
||||
export const useProviderContextSelector = <T,>(selector: (state: ProviderContextState) => T): T =>
|
||||
useContextSelector(ProviderContext, selector)
|
||||
import { useEducationStatus } from '@/service/use-education'
|
||||
import { ProviderContext } from './provider-context'
|
||||
|
||||
type ProviderContextProviderProps = {
|
||||
children: React.ReactNode
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const ProviderContextProvider = ({
|
||||
children,
|
||||
}: ProviderContextProviderProps) => {
|
||||
@ -262,5 +178,3 @@ export const ProviderContextProvider = ({
|
||||
</ProviderContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProviderContext
|
||||
90
web/context/provider-context.ts
Normal file
90
web/context/provider-context.ts
Normal file
@ -0,0 +1,90 @@
|
||||
'use client'
|
||||
|
||||
import type { Plan, UsagePlanInfo, UsageResetInfo } from '@/app/components/billing/type'
|
||||
import type { Model, ModelProvider } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { RETRIEVE_METHOD } from '@/types/app'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { createContext, useContext, useContextSelector } from 'use-context-selector'
|
||||
import { defaultPlan } from '@/app/components/billing/config'
|
||||
|
||||
export type ProviderContextState = {
|
||||
modelProviders: ModelProvider[]
|
||||
refreshModelProviders: () => void
|
||||
textGenerationModelList: Model[]
|
||||
supportRetrievalMethods: RETRIEVE_METHOD[]
|
||||
isAPIKeySet: boolean
|
||||
plan: {
|
||||
type: Plan
|
||||
usage: UsagePlanInfo
|
||||
total: UsagePlanInfo
|
||||
reset: UsageResetInfo
|
||||
}
|
||||
isFetchedPlan: boolean
|
||||
enableBilling: boolean
|
||||
onPlanInfoChanged: () => void
|
||||
enableReplaceWebAppLogo: boolean
|
||||
modelLoadBalancingEnabled: boolean
|
||||
datasetOperatorEnabled: boolean
|
||||
enableEducationPlan: boolean
|
||||
isEducationWorkspace: boolean
|
||||
isEducationAccount: boolean
|
||||
allowRefreshEducationVerify: boolean
|
||||
educationAccountExpireAt: number | null
|
||||
isLoadingEducationAccountInfo: boolean
|
||||
isFetchingEducationAccountInfo: boolean
|
||||
webappCopyrightEnabled: boolean
|
||||
licenseLimit: {
|
||||
workspace_members: {
|
||||
size: number
|
||||
limit: number
|
||||
}
|
||||
}
|
||||
refreshLicenseLimit: () => void
|
||||
isAllowTransferWorkspace: boolean
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: boolean
|
||||
humanInputEmailDeliveryEnabled: boolean
|
||||
}
|
||||
|
||||
export const baseProviderContextValue: ProviderContextState = {
|
||||
modelProviders: [],
|
||||
refreshModelProviders: noop,
|
||||
textGenerationModelList: [],
|
||||
supportRetrievalMethods: [],
|
||||
isAPIKeySet: true,
|
||||
plan: defaultPlan,
|
||||
isFetchedPlan: false,
|
||||
enableBilling: false,
|
||||
onPlanInfoChanged: noop,
|
||||
enableReplaceWebAppLogo: false,
|
||||
modelLoadBalancingEnabled: false,
|
||||
datasetOperatorEnabled: false,
|
||||
enableEducationPlan: false,
|
||||
isEducationWorkspace: false,
|
||||
isEducationAccount: false,
|
||||
allowRefreshEducationVerify: false,
|
||||
educationAccountExpireAt: null,
|
||||
isLoadingEducationAccountInfo: false,
|
||||
isFetchingEducationAccountInfo: false,
|
||||
webappCopyrightEnabled: false,
|
||||
licenseLimit: {
|
||||
workspace_members: {
|
||||
size: 0,
|
||||
limit: 0,
|
||||
},
|
||||
},
|
||||
refreshLicenseLimit: noop,
|
||||
isAllowTransferWorkspace: false,
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: false,
|
||||
humanInputEmailDeliveryEnabled: false,
|
||||
}
|
||||
|
||||
export const ProviderContext = createContext<ProviderContextState>(baseProviderContextValue)
|
||||
|
||||
export const useProviderContext = () => useContext(ProviderContext)
|
||||
|
||||
// Adding a dangling comma to avoid the generic parsing issue in tsx, see:
|
||||
// https://github.com/microsoft/TypeScript/issues/15713
|
||||
export const useProviderContextSelector = <T>(selector: (state: ProviderContextState) => T): T =>
|
||||
useContextSelector(ProviderContext, selector)
|
||||
|
||||
export default ProviderContext
|
||||
24
web/context/workspace-context-provider.tsx
Normal file
24
web/context/workspace-context-provider.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
'use client'
|
||||
|
||||
import type { ReactNode } from 'react'
|
||||
import { useWorkspaces } from '@/service/use-common'
|
||||
import { WorkspacesContext } from './workspace-context'
|
||||
|
||||
type WorkspaceProviderProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const WorkspaceProvider = ({
|
||||
children,
|
||||
}: WorkspaceProviderProps) => {
|
||||
const { data } = useWorkspaces()
|
||||
|
||||
return (
|
||||
<WorkspacesContext.Provider value={{
|
||||
workspaces: data?.workspaces || [],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkspacesContext.Provider>
|
||||
)
|
||||
}
|
||||
16
web/context/workspace-context.ts
Normal file
16
web/context/workspace-context.ts
Normal file
@ -0,0 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import type { IWorkspace } from '@/models/common'
|
||||
import { createContext, useContext } from 'use-context-selector'
|
||||
|
||||
export type WorkspacesContextValue = {
|
||||
workspaces: IWorkspace[]
|
||||
}
|
||||
|
||||
export const WorkspacesContext = createContext<WorkspacesContextValue>({
|
||||
workspaces: [],
|
||||
})
|
||||
|
||||
export const useWorkspacesContext = () => useContext(WorkspacesContext)
|
||||
|
||||
export default WorkspacesContext
|
||||
@ -1,36 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import type { IWorkspace } from '@/models/common'
|
||||
import { createContext, useContext } from 'use-context-selector'
|
||||
import { useWorkspaces } from '@/service/use-common'
|
||||
|
||||
export type WorkspacesContextValue = {
|
||||
workspaces: IWorkspace[]
|
||||
}
|
||||
|
||||
const WorkspacesContext = createContext<WorkspacesContextValue>({
|
||||
workspaces: [],
|
||||
})
|
||||
|
||||
type IWorkspaceProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const WorkspaceProvider = ({
|
||||
children,
|
||||
}: IWorkspaceProviderProps) => {
|
||||
const { data } = useWorkspaces()
|
||||
|
||||
return (
|
||||
<WorkspacesContext.Provider value={{
|
||||
workspaces: data?.workspaces || [],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkspacesContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useWorkspacesContext = () => useContext(WorkspacesContext)
|
||||
|
||||
export default WorkspacesContext
|
||||
Reference in New Issue
Block a user