refactor(apps): derive product modes from API contracts

Separate five App products, three configuration modes, and workflow-only modes from raw API values. Keep LLM model modes distinct from App modes. Test migrations follow in the dedicated test commit.
This commit is contained in:
yyh
2026-10-15 22:37:06 +08:00
parent f7840ab213
commit e7cc9c55aa
104 changed files with 345 additions and 479 deletions
@@ -20,7 +20,6 @@ import useDocumentTitle from '@/hooks/use-document-title'
import { redirect, usePathname } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { isNotFoundError } from '@/service/http-error'
import { AppModeEnum } from '@/types/app'
import { getRedirectionPath } from '@/utils/app-redirection'
import { getAppACLCapabilities } from '@/utils/permission'
@@ -51,8 +50,7 @@ const getAppDetailRedirectPath = (
permissionOptions: ResourceMaintainerPermissionOptions,
) => {
const appACLCapabilities = getAppACLCapabilities(appDetail.permission_keys, permissionOptions)
const isWorkflowApp =
appDetail.mode === AppModeEnum.WORKFLOW || appDetail.mode === AppModeEnum.ADVANCED_CHAT
const isWorkflowApp = appDetail.mode === 'workflow' || appDetail.mode === 'advanced-chat'
const isLayoutPath = pathname.endsWith('configuration') || pathname.endsWith('workflow')
const isLogsPath = pathname.endsWith('logs')
const isAnnotationsPath = pathname.endsWith('annotations')
@@ -65,8 +63,7 @@ const getAppDetailRedirectPath = (
(isLogsPath && !appACLCapabilities.canAccessLogAndAnnotation) ||
(isAnnotationsPath && !appACLCapabilities.canAccessLogAndAnnotation) ||
(isOverviewPath && !appACLCapabilities.canMonitor) ||
(isAccessConfigPath &&
(appDetail.mode === AppModeEnum.AGENT || !appACLCapabilities.canAccessConfig)) ||
(isAccessConfigPath && (appDetail.mode === 'agent' || !appACLCapabilities.canAccessConfig)) ||
(isAccessPointPath && !appACLCapabilities.canViewAccessPoint) ||
(isDeployPath && (!isWorkflowApp || !appACLCapabilities.canDeploy))
)
@@ -13,7 +13,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { usePathname } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import { AppInfoView } from './app-info'
import AppInfoHeader from './app-info/app-info-header'
@@ -71,11 +70,9 @@ function AppDetailContent({ appId, expand }: { appId: string; expand: boolean })
if (!appDetail || !systemFeatures || !currentUserId) return []
const appId = appDetail.id
const isWorkflowApp =
appDetail.mode === AppModeEnum.WORKFLOW || appDetail.mode === AppModeEnum.ADVANCED_CHAT
const supportsAnnotations =
appDetail.mode !== AppModeEnum.WORKFLOW && appDetail.mode !== AppModeEnum.COMPLETION
const supportsResourceAccess = appDetail.mode !== AppModeEnum.AGENT
const isWorkflowApp = appDetail.mode === 'workflow' || appDetail.mode === 'advanced-chat'
const supportsAnnotations = appDetail.mode !== 'workflow' && appDetail.mode !== 'completion'
const supportsResourceAccess = appDetail.mode !== 'agent'
const appACLCapabilities = getAppACLCapabilities(appDetail.permission_keys, {
currentUserId,
resourceMaintainer: appDetail.maintainer,
@@ -7,7 +7,6 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities, hasPermission } from '@/utils/permission'
import AppInfoHeader from './app-info-header'
import { getAppModeLabel } from './app-mode-labels'
@@ -74,7 +73,7 @@ const AppInfoTrigger = ({
]
: []),
...(appACLCapabilities.canImportExportDSL &&
(appDetail.mode === AppModeEnum.ADVANCED_CHAT || appDetail.mode === AppModeEnum.WORKFLOW)
(appDetail.mode === 'advanced-chat' || appDetail.mode === 'workflow')
? [
{
id: 'import',
@@ -99,8 +98,7 @@ const AppInfoTrigger = ({
: []
const workflowConversionOperations: Operation[] =
appACLCapabilities.canEdit &&
(appDetail.mode === AppModeEnum.COMPLETION || appDetail.mode === AppModeEnum.CHAT)
appACLCapabilities.canEdit && (appDetail.mode === 'completion' || appDetail.mode === 'chat')
? [
{
id: 'switch',
@@ -1,15 +1,14 @@
import type { TFunction } from 'i18next'
import { AppModeEnum } from '@/types/app'
export function getAppModeLabel(mode: string, t: TFunction<['app']>): string {
switch (mode) {
case AppModeEnum.ADVANCED_CHAT:
case 'advanced-chat':
return t(($) => $['types.advanced'], { ns: 'app' })
case AppModeEnum.AGENT_CHAT:
case 'agent-chat':
return t(($) => $['types.agent'], { ns: 'app' })
case AppModeEnum.CHAT:
case 'chat':
return t(($) => $['types.chatbot'], { ns: 'app' })
case AppModeEnum.COMPLETION:
case 'completion':
return t(($) => $['types.completion'], { ns: 'app' })
default:
return t(($) => $['types.workflow'], { ns: 'app' })
@@ -17,7 +17,6 @@ import {
markAppDeletionSucceeded,
} from '@/service/app-deletion'
import { consoleClient, consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
export type AppInfoModalType =
@@ -234,7 +233,7 @@ export function useAppInfoActions({
const exportCheck = useCallback(async () => {
if (isExporting) return
if (appMode !== AppModeEnum.WORKFLOW && appMode !== AppModeEnum.ADVANCED_CHAT) {
if (appMode !== 'workflow' && appMode !== 'advanced-chat') {
onExport()
return
}
@@ -23,7 +23,6 @@ import {
useUpdateAppUserAccessSettings,
} from '@/service/access-control/use-app-access-config'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
type AppAccessConfigPageProps = {
@@ -265,7 +264,7 @@ const AppAccessConfigPage = ({ appId }: AppAccessConfigPageProps) => {
],
)
if (appDetail.mode === AppModeEnum.AGENT || !appACLCapabilities.canAccessConfig) return null
if (appDetail.mode === 'agent' || !appACLCapabilities.canAccessConfig) return null
return <AppAccessConfigContent appId={appId} maintainerId={appDetail.maintainer} />
}
@@ -26,7 +26,6 @@ import {
useMCPServerDetail,
useRefreshMCPServerCode,
} from '@/service/use-tools'
import { AppModeEnum } from '@/types/app'
import { useAccessPointStatusLabel } from '../shared/use-access-point-status-label'
import { getPublishedWorkflowNodes, isAdvancedApp } from '../shared/utils'
@@ -50,7 +49,7 @@ export function MCPAccessPointCard({
const { t } = useTranslation(['appOverview', 'common', 'deployments', 'tools'])
const advancedApp = isAdvancedApp(appInfo)
const basicApp = !advancedApp
const workflowApp = appInfo.mode === AppModeEnum.WORKFLOW
const workflowApp = appInfo.mode === 'workflow'
const [showServerModal, setShowServerModal] = useState(false)
const [showRegenerate, setShowRegenerate] = useState(false)
const basicConfig = appInfo.model_config
@@ -37,7 +37,6 @@ import {
useGetUserCanAccessApp,
} from '@/service/access-control/use-app-access-control'
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'
import {
@@ -122,8 +121,7 @@ export function WebAppAccessPointCard({
: appInfo.enable_site
const running = siteAvailability === 'available' && optimisticEnabled
const actionsAvailable = running && Boolean(webAppUrl) && !toggleSiteMutation.isPending
const supportsEmbedded =
appInfo.mode !== AppModeEnum.COMPLETION && appInfo.mode !== AppModeEnum.WORKFLOW
const supportsEmbedded = appInfo.mode !== 'completion' && appInfo.mode !== 'workflow'
const hiddenLaunchVariables = getHiddenStartInputs(workflow)
const { data: accessSubjects } = useAppWhiteListSubjects(
appInfo.id,
@@ -220,9 +218,7 @@ export function WebAppAccessPointCard({
/>
<SettingsDialog
key={appInfo.id}
isChat={
appInfo.mode !== AppModeEnum.COMPLETION && appInfo.mode !== AppModeEnum.WORKFLOW
}
isChat={appInfo.mode !== 'completion' && appInfo.mode !== 'workflow'}
canDeploy={canDeploy}
appInfo={site ? { id: appInfo.id, mode: appInfo.mode, site } : undefined}
disabled={siteAvailability !== 'available' || !canManageAccessPoint}
@@ -1,10 +1,9 @@
import type { EnvironmentSite } from '@dify/contracts/enterprise-app-deploy/types.gen'
import { AppModeEnum } from '@/types/app'
import { basePath } from '@/utils/var'
export function getEnvironmentWebAppUrl(site?: EnvironmentSite, mode?: string) {
if (!site?.app_base_url || !site.code) return ''
const route = mode === AppModeEnum.ADVANCED_CHAT ? 'chat' : 'workflow'
const route = mode === 'advanced-chat' ? 'chat' : 'workflow'
return `${site.app_base_url.replace(/\/$/, '')}${basePath}/environment/${route}/${site.code}`
}
@@ -16,7 +16,6 @@ import { ACCESS_POINT_ORDER } from '@/app/components/app/deploy/utils/access-poi
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import { BuiltInAccessPoints } from './built-in-access-points'
import { DeployedEnvironmentAccessPoints } from './deployed-environment-access-points'
@@ -162,7 +161,7 @@ export default function AccessPoint({ appId }: AccessPointProps) {
workspacePermissionKeys,
})
const showEnvironmentTabs =
(appDetail?.mode === AppModeEnum.WORKFLOW || appDetail?.mode === AppModeEnum.ADVANCED_CHAT) &&
(appDetail?.mode === 'workflow' || appDetail?.mode === 'advanced-chat') &&
capabilities.canViewAccessPoint
return (
@@ -5,7 +5,6 @@ import type {
import type { InputVar, Node } from '@/app/components/workflow/types'
import type { DocPathWithoutLang } from '@/types/doc-paths'
import { BlockEnum, isTriggerNode } from '@/app/components/workflow/types'
import { AppModeEnum } from '@/types/app'
import { basePath } from '@/utils/var'
export type PublishedWorkflow = WorkflowResponse | null | undefined
@@ -25,7 +24,7 @@ export function getAppApiReferencePath(appMode: AppDetailWithSite['mode']) {
}
export function getPublishedWorkflowState(appInfo: AppDetailWithSite, workflow: PublishedWorkflow) {
const isWorkflowApp = appInfo.mode === AppModeEnum.WORKFLOW
const isWorkflowApp = appInfo.mode === 'workflow'
const nodes = getPublishedWorkflowNodes(workflow)
const hasStartNode = nodes.some((node) => node.data.type === BlockEnum.Start)
const hasTriggerNode = nodes.some((node) => isTriggerNode(node.data.type))
@@ -46,9 +45,7 @@ export function getPublishedWorkflowNodes(workflow: PublishedWorkflow) {
export function getBuiltInAccessUrls(appInfo: AppDetailWithSite) {
const appMode =
appInfo.mode === AppModeEnum.COMPLETION || appInfo.mode === AppModeEnum.WORKFLOW
? appInfo.mode
: AppModeEnum.CHAT
appInfo.mode === 'completion' || appInfo.mode === 'workflow' ? appInfo.mode : 'chat'
return {
api: appInfo.api_base_url ?? '',
@@ -69,5 +66,5 @@ export function getHiddenStartInputs(workflow: PublishedWorkflow) {
}
export function isAdvancedApp(appInfo: AppDetailWithSite) {
return appInfo.mode === AppModeEnum.WORKFLOW || appInfo.mode === AppModeEnum.ADVANCED_CHAT
return appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat'
}
+1 -2
View File
@@ -35,7 +35,6 @@ import {
updateAnnotationStatus,
} from '@/service/annotation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { sleep } from '@/utils'
import PageTitle from '../log-annotation/page-title'
import EmptyElement from './empty-element'
@@ -55,7 +54,7 @@ const Annotation: FC<Props> = (props) => {
const docLink = useDocLink()
const [isShowEdit, setIsShowEdit] = useState(false)
const [annotationConfig, setAnnotationConfig] = useState<AnnotationReplyConfig | null>(null)
const [isChatApp] = useState(appDetail.mode !== AppModeEnum.COMPLETION)
const [isChatApp] = useState(appDetail.mode !== 'completion')
const [controlRefreshSwitch, setControlRefreshSwitch] = useState(() => Date.now())
const deploymentEdition = useAtomValue(deploymentEditionAtom)
const { data: annotationQuota } = useQuery(
@@ -3,7 +3,6 @@ import type { AppPublisherProps } from '../types'
import { cn } from '@langgenius/dify-ui/cn'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { useTranslation } from 'react-i18next'
import { AppModeEnum } from '@/types/app'
import SuggestedAction from '../suggested-action'
import WorkflowToolAction from '../workflow-tool-action'
@@ -58,7 +57,7 @@ export function PublisherActionsSection({
const hasPublishedVersion = Boolean(publishedAt)
const showOpenWebApp = !hasTriggerNode
const showWorkflowTool = appMode === AppModeEnum.WORKFLOW && !hasHumanInputNode && !hasTriggerNode
const showWorkflowTool = appMode === 'workflow' && !hasHumanInputNode && !hasTriggerNode
const navigationDisabled = !hasPublishedVersion
const workflowToolDisabled =
!hasPublishedVersion || !workflowToolAvailable || (toolPublished && workflowToolIsLoading)
@@ -7,13 +7,12 @@ import { useTranslation } from 'react-i18next'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import { PublisherContent } from './publisher-content'
import { appPublisherOpenAtom, AppPublisherStateBoundary } from './state'
export function AppPublisher(props: AppPublisherProps) {
const { t } = useTranslation(['workflow'])
const { t } = useTranslation(['workflow'] as const)
return (
<Suspense
fallback={
@@ -45,8 +44,7 @@ function AppPublisherContent(props: AppPublisherProps) {
workspacePermissionKeys,
})
const supportsMultiEnvironment =
(appDetail.mode === AppModeEnum.WORKFLOW || appDetail.mode === AppModeEnum.ADVANCED_CHAT) &&
canDeploy
(appDetail.mode === 'workflow' || appDetail.mode === 'advanced-chat') && canDeploy
return (
<AppPublisherStateBoundary
@@ -18,7 +18,6 @@ import {
appWorkflowQueryOptions,
appWorkflowVersionsInfiniteQueryOptions,
} from '@/service/workflow-queries'
import { AppModeEnum } from '@/types/app'
type UsePublishControllerParams = Pick<
AppPublisherProps,
@@ -66,11 +65,8 @@ export function usePublishController({
const queryClient = useQueryClient()
const workflowStore = use(WorkflowContext)
const invalidateAppWorkflow = useInvalidateAppWorkflow()
const isWorkflowApp = appMode === AppModeEnum.WORKFLOW || appMode === AppModeEnum.ADVANCED_CHAT
const isChatApp =
appMode === AppModeEnum.CHAT ||
appMode === AppModeEnum.AGENT_CHAT ||
appMode === AppModeEnum.COMPLETION
const isWorkflowApp = appMode === 'workflow' || appMode === 'advanced-chat'
const isChatApp = appMode === 'chat' || appMode === 'agent-chat' || appMode === 'completion'
const {
data: publishedWorkflow,
isError: isPublishedWorkflowError,
@@ -7,7 +7,6 @@ import { useTranslation } from 'react-i18next'
import { useCanManageTools } from '@/app/components/tools/hooks/use-tool-permissions'
import { useConfigureButton } from '@/app/components/tools/workflow-tool/hooks/use-configure-button'
import { appDefaultIconBackground } from '@/config'
import { AppModeEnum } from '@/types/app'
type UseWorkflowToolParams = {
appDescription?: string
@@ -50,10 +49,10 @@ export function useWorkflowTool({
toolPublished,
workflowToolAvailable,
}: UseWorkflowToolParams) {
const { t } = useTranslation(['workflow'])
const { t } = useTranslation(['workflow'] as const)
const [drawerOpen, setDrawerOpen] = useState(false)
const canManageTools = useCanManageTools()
const visible = appMode === AppModeEnum.WORKFLOW && !hasHumanInputNode && !hasTriggerNode
const visible = appMode === 'workflow' && !hasHumanInputNode && !hasTriggerNode
const published = Boolean(toolPublished)
const message =
!hasPublishedVersion || !workflowToolAvailable
@@ -1,10 +1,9 @@
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { TFunction } from 'i18next'
import { AppModeEnum } from '@/types/app'
import { basePath } from '@/utils/var'
export const getPublisherAppMode = (mode?: AppMode) => {
if (mode !== AppModeEnum.COMPLETION && mode !== AppModeEnum.WORKFLOW) return AppModeEnum.CHAT
if (mode !== 'completion' && mode !== 'workflow') return 'chat'
return mode
}
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { ExternalDataTool } from '@/models/common'
import type { PromptRole, PromptVariable } from '@/models/debug'
@@ -20,7 +21,6 @@ import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/promp
import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import { AppModeEnum } from '@/types/app'
import { getNewVar, getVars } from '@/utils/var'
import ConfirmAddVar from './confirm-add-var'
import MessageTypeSelector from './message-type-selector'
@@ -102,7 +102,7 @@ const AdvancedPromptInput: FC<Props> = ({
},
})
}
const isChatApp = mode !== AppModeEnum.COMPLETION
const isChatApp = mode !== 'completion'
const [isCopied, setIsCopied] = React.useState(false)
const promptVariablesObj = (() => {
@@ -1,7 +1,8 @@
'use client'
import type { FC } from 'react'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { PromptItem, PromptVariable } from '@/models/debug'
import type { AppModeEnum } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { RiAddLine } from '@remixicon/react'
import { produce } from 'immer'
@@ -16,7 +17,7 @@ import { ModelModeType } from '@/types/app'
import SimplePromptInput from './simple-prompt-input'
export type IPromptProps = {
mode: AppModeEnum
mode: ConfigurationAppMode
promptTemplate: string
promptVariables: PromptVariable[]
readonly?: boolean
@@ -1,5 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { ExternalDataTool } from '@/models/common'
import type { PromptVariable } from '@/models/debug'
import type { GenRes } from '@/service/debug'
@@ -24,13 +26,12 @@ import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { AppModeEnum } from '@/types/app'
import { getNewVar, getVars } from '@/utils/var'
import ConfirmAddVar from './confirm-add-var'
import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap'
type ISimplePromptInput = {
mode: AppModeEnum
mode: ConfigurationAppMode
promptTemplate: string
promptVariables: PromptVariable[]
readonly?: boolean
@@ -54,7 +55,7 @@ const Prompt: FC<ISimplePromptInput> = ({
const { t } = useTranslation(['appDebug'])
const titleId = useId()
const title =
mode !== AppModeEnum.COMPLETION
mode !== 'completion'
? t(($) => $.chatSubTitle, { ns: 'appDebug' })
: t(($) => $.completionSubTitle, { ns: 'appDebug' })
const media = useBreakpoints()
@@ -66,6 +67,7 @@ const Prompt: FC<ISimplePromptInput> = ({
const {
appId,
modelConfig,
modelModeType,
dataSets,
setModelConfig,
setPrevPromptConfig,
@@ -176,7 +178,7 @@ const Prompt: FC<ISimplePromptInput> = ({
setModelConfig(newModelConfig)
setPrevPromptConfig(modelConfig.configs)
if (mode !== AppModeEnum.COMPLETION) {
if (mode !== 'completion') {
setIntroduction(res.opening_statement || '')
const newFeatures = produce(features, (draft) => {
draft.opening = {
@@ -314,7 +316,7 @@ const Prompt: FC<ISimplePromptInput> = ({
{showAutomatic && (
<GetAutomaticResModal
flowId={appId}
mode={mode as AppModeEnum}
modelMode={modelModeType}
isShow={showAutomatic}
onClose={showAutomaticFalse}
onFinished={handleAutomaticRes}
@@ -1,4 +1,5 @@
'use client'
import type { ChangeEvent, FC } from 'react'
import type { Item as SelectItem } from './type-select'
import type { ConfigModalValidationError } from './utils'
@@ -15,7 +16,6 @@ import ConfigContext from '@/context/debug-configuration'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { commonQueryKeys } from '@/service/use-common'
import { AppModeEnum } from '@/types/app'
import {
checkKeys,
getNewVarInWorkflow,
@@ -69,8 +69,7 @@ const ConfigModal: FC<IConfigModalProps> = ({
input: appId ? { params: { app_id: appId } } : skipToken,
}),
)
const isBasicApp =
appDetail?.mode !== AppModeEnum.ADVANCED_CHAT && appDetail?.mode !== AppModeEnum.WORKFLOW
const isBasicApp = appDetail?.mode !== 'advanced-chat' && appDetail?.mode !== 'workflow'
const jsonSchemaStr = useMemo(
() => getJsonSchemaEditorValue(type, tempPayload.json_schema),
[tempPayload.json_schema, type],
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { InputVar } from '@/app/components/workflow/types'
import type { ExternalDataTool } from '@/models/common'
@@ -27,7 +28,6 @@ import { InputVarType } from '@/app/components/workflow/types'
import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import { AppModeEnum } from '@/types/app'
import { getNewVar, hasDuplicateStr } from '@/utils/var'
import Panel from '../base/feature-panel'
import EditModal from './config-modal'
@@ -244,7 +244,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
(index: number) => {
const removeVar = promptVariables[index]
if (mode === AppModeEnum.COMPLETION && dataSets.length > 0 && removeVar!.is_context_var) {
if (mode === 'completion' && dataSets.length > 0 && removeVar!.is_context_var) {
showDeleteContextVarModal()
setRemoveIndex(index)
return
@@ -1,9 +1,10 @@
'use client'
import type { FC } from 'react'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
// type
import type { GenRes } from '@/service/debug'
import type { AppModeEnum, CompletionParams, Model, ModelModeType } from '@/types/app'
import type { CompletionParams, Model, ModelModeType } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { Dialog, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
import { useQuery } from '@tanstack/react-query'
@@ -31,7 +32,7 @@ import useGenData from './use-gen-data'
const i18nPrefix = 'generate'
type IGetAutomaticResProps = {
mode: AppModeEnum
modelMode: ModelModeType
isShow: boolean
onClose: () => void
onFinished: (res: GenRes) => void
@@ -60,7 +61,7 @@ const TryLabel: FC<{
}
const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
mode,
modelMode,
isShow,
onClose,
flowId,
@@ -84,10 +85,10 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
return {
name: defaultModel?.model ?? '',
provider: defaultModel?.provider.provider ?? '',
mode: mode as unknown as ModelModeType,
mode: modelMode,
completion_params: {} as CompletionParams,
}
}, [defaultModel, mode, selectedModel, storedModel])
}, [defaultModel, modelMode, selectedModel, storedModel])
const tryList = [
{
iconClassName: 'i-ri-terminal-box-line',
@@ -2,7 +2,7 @@ import type { FC } from 'react'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import type { GenRes } from '@/service/debug'
import type { AppModeEnum, CompletionParams, Model, ModelModeType } from '@/types/app'
import type { CompletionParams, Model, ModelModeType } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
import { useQuery } from '@tanstack/react-query'
@@ -42,7 +42,7 @@ type IGetCodeGeneratorResProps = {
flowId: string
nodeId: string
currentCode?: string
mode: AppModeEnum
modelMode: ModelModeType
isShow: boolean
codeLanguages: CodeLanguage
onClose: () => void
@@ -53,7 +53,7 @@ export const GetCodeGeneratorResModal: FC<IGetCodeGeneratorResProps> = ({
flowId,
nodeId,
currentCode,
mode,
modelMode,
isShow,
codeLanguages,
onClose,
@@ -80,10 +80,10 @@ export const GetCodeGeneratorResModal: FC<IGetCodeGeneratorResProps> = ({
return {
name: defaultModel?.model ?? '',
provider: defaultModel?.provider.provider ?? '',
mode: mode as unknown as ModelModeType,
mode: modelMode,
completion_params: defaultCompletionParams,
}
}, [defaultModel, mode, selectedModel, storedModel])
}, [defaultModel, modelMode, selectedModel, storedModel])
const [instructionFromSessionStorage, setInstructionFromSessionStorage] =
useSessionStorageState<string>(`improve-instruction-${flowId}-${nodeId}`)
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { ModelConfig, PromptVariable } from '@/models/debug'
import { produce } from 'immer'
@@ -7,7 +8,7 @@ import { useContext } from 'use-context-selector'
import ConfigPrompt from '@/app/components/app/configuration/config-prompt'
import ConfigVar from '@/app/components/app/configuration/config-var'
import ConfigContext from '@/context/debug-configuration'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
import HistoryPanel from '../config-prompt/conversation-history/history-panel'
import ConfigVision from '../config-vision'
import DatasetConfig from '../dataset-config'
@@ -30,9 +31,7 @@ const Config: FC = () => {
setPrevPromptConfig,
dataSets,
} = useContext(ConfigContext)
const isChatApp = [AppModeEnum.ADVANCED_CHAT, AppModeEnum.AGENT_CHAT, AppModeEnum.CHAT].includes(
mode,
)
const isChatApp = ['advanced-chat', 'agent-chat', 'chat'].includes(mode)
const formattingChangedDispatcher = useFormattingChangedDispatcher()
const promptTemplate = modelConfig.configs.prompt_template
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { ConfigurationViewModel } from '../hooks/configuration-view-model'
import type { InstallBundleCompleteCallback } from '@/app/components/plugins/install-plugin/install-bundle'
@@ -40,7 +41,7 @@ import ModelParameterModal from '@/app/components/header/account-setting/model-p
import PluginDependency from '@/app/components/workflow/plugin-dependency'
import ConfigContext from '@/context/debug-configuration'
import { isAgentV2Enabled } from '@/features/agent-v2/feature-flag'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
import { LegacyAgentBadge } from './legacy-agent-badge'
const ConfigurationView: FC<ConfigurationViewModel> = ({
@@ -80,7 +81,7 @@ const ConfigurationView: FC<ConfigurationViewModel> = ({
}) => {
const { t } = useTranslation(['appDebug', 'common'])
const debugWithMultipleModel = appPublisherProps.debugWithMultipleModel
const showLegacyAgentBadge = isAgentV2Enabled() && contextValue.mode === AppModeEnum.AGENT_CHAT
const showLegacyAgentBadge = isAgentV2Enabled() && contextValue.mode === 'agent-chat'
const handlePluginInstallComplete: InstallBundleCompleteCallback = (plugins, installStatus) => {
if (!installStatus.some((status) => status.success)) return
@@ -289,7 +290,7 @@ const ConfigurationView: FC<ConfigurationViewModel> = ({
show
inWorkflow={false}
showFileUpload={false}
isChatMode={contextValue.mode !== AppModeEnum.COMPLETION}
isChatMode={contextValue.mode !== 'completion'}
disabled={!!contextValue.readonly}
onChange={onFeaturesChange}
onClose={onCloseFeaturePanel}
@@ -34,7 +34,6 @@ import {
import ConfigContext from '@/context/debug-configuration'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { AppModeEnum } from '@/types/app'
import { getDatasetACLCapabilities } from '@/utils/permission'
import FeaturePanel from '../base/feature-panel'
import { OperationButton } from '../base/operation-button'
@@ -269,7 +268,7 @@ const DatasetConfig: FC<Props> = ({ readonly, hideMetadataFilter }) => {
draft.metadata_model_config = {
provider: model.provider,
name: model.modelId,
mode: model.mode || AppModeEnum.CHAT,
mode: model.mode || 'chat',
completion_params: draft.metadata_model_config?.completion_params || { temperature: 0.7 },
}
})
@@ -355,7 +354,7 @@ const DatasetConfig: FC<Props> = ({ readonly, hideMetadataFilter }) => {
</div>
)}
{!readonly && mode === AppModeEnum.COMPLETION && dataSet.length > 0 && (
{!readonly && mode === 'completion' && dataSet.length > 0 && (
<ContextVar
value={selectedContextVar?.key}
options={promptVariablesToSelect}
@@ -17,7 +17,6 @@ import {
} from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useDebugConfigurationContext } from '@/context/debug-configuration'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import ChatItem from './chat-item'
import { useDebugWithMultipleModelContext } from './context'
import ModelParameterTrigger from './model-parameter-trigger'
@@ -124,13 +123,13 @@ const DebugItem: FC<DebugItemProps> = ({ modelAndParameter, className, style })
</DropdownMenu>
</div>
<div style={{ height: 'calc(100% - 40px)' }}>
{(mode === AppModeEnum.CHAT || mode === AppModeEnum.AGENT_CHAT) &&
{(mode === 'chat' || mode === 'agent-chat') &&
currentProvider &&
currentModel &&
currentModel.status === ModelStatusEnum.active && (
<ChatItem modelAndParameter={modelAndParameter} />
)}
{mode === AppModeEnum.COMPLETION &&
{mode === 'completion' &&
currentProvider &&
currentModel &&
currentModel.status === ModelStatusEnum.active && (
@@ -7,7 +7,6 @@ import ChatInputArea from '@/app/components/base/chat/chat/chat-input-area'
import { useFeatures } from '@/app/components/base/features/hooks'
import { useDebugConfigurationContext } from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { AppModeEnum } from '@/types/app'
import { APP_CHAT_WITH_MULTIPLE_MODEL } from '../types'
import { useDebugWithMultipleModelContext } from './context'
import { DebugWithMultipleModelContextProvider } from './context-provider'
@@ -28,7 +27,7 @@ const DebugWithMultipleModel = () => {
const { multipleModelConfigs, checkCanSend } = useDebugWithMultipleModelContext()
const { eventEmitter } = useEventEmitterContextContext()
const isChatMode = mode === AppModeEnum.CHAT || mode === AppModeEnum.AGENT_CHAT
const isChatMode = mode === 'chat' || mode === 'agent-chat'
const handleSend = useCallback(
(message: string, files?: FileEntity[]) => {
@@ -1,4 +1,5 @@
'use client'
import type { AppModelConfigPayload } from '@dify/contracts/api/console/apps/types.gen'
import type { FC } from 'react'
import type { DebugWithSingleModelRefType } from './debug-with-single-model'
@@ -44,7 +45,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
import { consoleQuery } from '@/service/console'
import { sendCompletionMessage } from '@/service/debug'
import { AppSourceType } from '@/service/share'
import { AppModeEnum, ModelModeType, TransferMethod } from '@/types/app'
import { ModelModeType, TransferMethod } from '@/types/app'
import { formatBooleanInputs, promptVariablesToUserInputsForm } from '@/utils/model-config'
import GroupName from '../base/group-name'
import CannotQueryDataset from '../base/warning-mask/cannot-query-dataset'
@@ -147,7 +148,7 @@ const Debug: FC<IDebug> = ({
const [completionFiles, setCompletionFiles] = useState<VisionFile[]>([])
const checkCanSend = useCallback(() => {
if (isAdvancedMode && mode !== AppModeEnum.COMPLETION) {
if (isAdvancedMode && mode !== 'completion') {
if (modelModeType === ModelModeType.completion) {
if (!hasSetBlockStatus.history) {
toast.error(t(($) => $['otherError.historyNoBeEmpty'], { ns: 'appDebug' }))
@@ -413,9 +414,7 @@ const Debug: FC<IDebug> = ({
const handleOpenLog = (item: IChatItem) => {
const container =
debugWithMultipleModel || mode === AppModeEnum.COMPLETION
? ref.current
: singleChatContainerRef.current
debugWithMultipleModel || mode === 'completion' ? ref.current : singleChatContainerRef.current
if (container) setLogModalWidth(document.body.clientWidth - (container.clientWidth + 16) - 8)
setSelectedLogItem(item)
}
@@ -423,9 +422,7 @@ const Debug: FC<IDebug> = ({
useEffect(() => {
if (!selectedLogItem) return
const container =
debugWithMultipleModel || mode === AppModeEnum.COMPLETION
? ref.current
: singleChatContainerRef.current
debugWithMultipleModel || mode === 'completion' ? ref.current : singleChatContainerRef.current
if (!container) return
const adjustModalWidth = () => {
@@ -471,7 +468,7 @@ const Debug: FC<IDebug> = ({
<div className="mx-2 h-3.5 w-px bg-divider-regular" />
</>
) : null}
{mode !== AppModeEnum.COMPLETION && (
{mode !== 'completion' && (
<>
{canTestAndRun && (
<Tooltip>
@@ -525,14 +522,14 @@ const Debug: FC<IDebug> = ({
)}
</div>
</div>
{mode !== AppModeEnum.COMPLETION && (
{mode !== 'completion' && (
<CollapsiblePanel render={<div className="mx-3" />}>
<ChatUserInput inputs={inputs} />
</CollapsiblePanel>
)}
{mode === AppModeEnum.COMPLETION && (
{mode === 'completion' && (
<PromptValuePanel
appType={mode as AppModeEnum}
appType={mode}
onSend={handleSendTextCompletion}
inputs={inputs}
visionConfig={{
@@ -582,7 +579,7 @@ const Debug: FC<IDebug> = ({
</div>
)}
{/* Chat */}
{mode !== AppModeEnum.COMPLETION && (
{mode !== 'completion' && (
<div className="h-0 grow overflow-hidden">
<DebugWithSingleModel
ref={debugWithSingleModelRef}
@@ -593,7 +590,7 @@ const Debug: FC<IDebug> = ({
</div>
)}
{/* Text Generation */}
{mode === AppModeEnum.COMPLETION && (
{mode === 'completion' && (
<>
{(completionRes || isResponding) && (
<>
@@ -4,7 +4,6 @@ import { PromptMode } from '@/models/debug'
import { consoleClient } from '@/service/console'
import { fetchDatasets } from '@/service/datasets'
import { fetchCollectionList } from '@/service/tools'
import { AppModeEnum } from '@/types/app'
import { withCollectionIconBasePath } from '../../utils'
import { buildConfigurationDatasetConfigs } from './dataset'
import { normalizeChatPromptConfig, normalizeCompletionPromptConfig } from './prompt-config'
@@ -24,11 +23,7 @@ export async function loadConfigurationState({
const collectionList = withCollectionIconBasePath(await fetchCollectionList(), basePath)
const response = await consoleClient.apps.byAppId.get({ params: { app_id: appId } })
const mode = response.mode
if (
mode !== AppModeEnum.CHAT &&
mode !== AppModeEnum.AGENT_CHAT &&
mode !== AppModeEnum.COMPLETION
)
if (mode !== 'chat' && mode !== 'agent-chat' && mode !== 'completion')
throw new Error(`App mode ${mode} does not use model configuration`)
const backendModelConfig = response.model_config
if (!backendModelConfig) throw new Error(`App ${appId} has no model configuration`)
@@ -1,11 +1,12 @@
import type { TFunction } from 'i18next'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { ModelConfig } from '@/models/debug'
import type { VisionSettings } from '@/types/app'
import { produce } from 'immer'
import { useMemo } from 'react'
import { toast } from '@/app/components/app/configuration/toast'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'
type ModelChangeHandlerOptions = {
@@ -23,7 +24,7 @@ type ModelChangeHandlerOptions = {
handleSetVisionConfig: (config: VisionSettings, notNoticeFormattingChanged?: boolean) => void
isAdvancedMode: boolean
migrateToDefaultPrompt: (force?: boolean, modelModeType?: ModelModeType) => Promise<void>
mode: AppModeEnum
mode: ConfigurationAppMode
modelConfig: ModelConfig
resolvedModelModeType: ModelModeType
setCompletionParams: (value: FormValue) => void
@@ -61,7 +62,7 @@ export const createModelChangeHandler =
}) => {
if (isAdvancedMode) {
if (nextModelMode === ModelModeType.completion) {
if (mode !== AppModeEnum.COMPLETION) {
if (mode !== 'completion') {
if (
!completionPromptConfig.prompt?.text ||
!completionPromptConfig.conversation_histories_role.assistant_prefix ||
@@ -1,6 +1,7 @@
import type { AppModelConfigPayload } from '@dify/contracts/api/console/apps/types.gen'
import type { TFunction } from 'i18next'
import type { ConfigurationPublishConfig } from './types'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Features as FeaturesData } from '@/app/components/base/features/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { DataSet } from '@/models/datasets'
@@ -21,7 +22,7 @@ import { produce } from 'immer'
import { toast } from '@/app/components/app/configuration/toast'
import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config'
import { PromptMode } from '@/models/debug'
import { AgentStrategy, AppModeEnum, ModelModeType } from '@/types/app'
import { AgentStrategy, ModelModeType } from '@/types/app'
import { promptVariablesToUserInputsForm } from '@/utils/model-config'
import { normalizeChatPromptConfig, normalizeCompletionPromptConfig } from './prompt-config'
@@ -152,7 +153,7 @@ export const createPublishHandler =
hasSetBlockStatus: { history: boolean; query: boolean }
isAdvancedMode: boolean
isFunctionCall: boolean
mode: AppModeEnum
mode: ConfigurationAppMode
modelConfig: ModelConfig
promptEmpty: boolean
promptMode: PromptMode
@@ -178,7 +179,7 @@ export const createPublishHandler =
}
if (
isAdvancedMode &&
mode !== AppModeEnum.COMPLETION &&
mode !== 'completion' &&
resolvedModelModeType === ModelModeType.completion
) {
if (!hasSetBlockStatus.history) {
@@ -3,6 +3,7 @@ import type {
DeletedTool,
} from '@dify/contracts/api/console/apps/types.gen'
import type { ConfigurationPublishConfig } from './types'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Collection } from '@/app/components/tools/types'
import type { DataSet } from '@/models/datasets'
import type { AnnotationReplyConfig, DatasetConfigs, ModelConfig } from '@/models/debug'
@@ -12,7 +13,7 @@ import {
} from '@dify/contracts/api/console/apps/zod.gen'
import { ANNOTATION_DEFAULT, DEFAULT_AGENT_SETTING } from '@/config'
import { PromptMode } from '@/models/debug'
import { AgentStrategy, AppModeEnum } from '@/types/app'
import { AgentStrategy } from '@/types/app'
import { correctModelProvider, correctToolProvider } from '@/utils'
import { userInputsFormToPromptVariables } from '@/utils/model-config'
import { matchesProviderReference } from '@/utils/provider-reference'
@@ -50,7 +51,7 @@ function buildPublishedModelConfig({
backendModelConfig: AppModelConfigResponse
collectionList: Collection[]
deletedTools?: DeletedTool[]
mode: AppModeEnum
mode: ConfigurationAppMode
nextDataSets: DataSet[]
}): ModelConfig {
const model = backendModelConfig.model
@@ -107,7 +108,7 @@ function buildPublishedModelConfig({
external_data_tools: externalDataTools,
dataSets: nextDataSets,
agentConfig:
mode === AppModeEnum.AGENT_CHAT
mode === 'agent-chat'
? {
...backendModelConfig.agent_mode,
enabled: true,
@@ -170,7 +171,7 @@ export function buildPublishedConfig({
collectionList: Collection[]
datasetConfigs: DatasetConfigs
deletedTools?: DeletedTool[]
mode: AppModeEnum
mode: ConfigurationAppMode
nextDataSets: DataSet[]
}): ConfigurationPublishConfig {
const modelConfig = buildPublishedModelConfig({
@@ -1,6 +1,9 @@
import type { AppType } from '@/app/components/apps/app-type'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { DatasetConfigs, ModelConfig, PromptMode } from '@/models/debug'
export type ConfigurationAppMode = Extract<AppType, 'chat' | 'agent-chat' | 'completion'>
export type ConfigurationPublishConfig = {
modelConfig: ModelConfig
completionParams: FormValue
@@ -1,8 +1,8 @@
import type { Dispatch, SetStateAction } from 'react'
import type { ConfigurationPublishConfig } from './types'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Collection } from '@/app/components/tools/types'
import type { AnnotationReplyConfig } from '@/models/debug'
import type { AppModeEnum } from '@/types/app'
import { useEffect, useRef, useState } from 'react'
import { basePath } from '@/utils/var'
import { loadConfigurationState } from './load'
@@ -13,7 +13,7 @@ type ConfigurationLoaderOperations = {
setAnnotationConfig: (config: AnnotationReplyConfig, notSetFormatChanged?: boolean) => void
setCollectionList: Dispatch<SetStateAction<Collection[]>>
setHasFetchedDetail: Dispatch<SetStateAction<boolean>>
setMode: Dispatch<SetStateAction<AppModeEnum>>
setMode: Dispatch<SetStateAction<ConfigurationAppMode>>
setPublishedConfig: Dispatch<SetStateAction<ConfigurationPublishConfig | null>>
syncToPublishedConfig: (config: ConfigurationPublishConfig) => void
}
@@ -2,12 +2,13 @@ import type { TFunction } from 'i18next'
import type { Dispatch, SetStateAction } from 'react'
import type { ConfigurationPublishConfig } from './types'
import type { AppPublisherPublishParams } from '@/app/components/app/app-publisher/types'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Features as FeaturesData } from '@/app/components/base/features/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { DataSet } from '@/models/datasets'
import type { DatasetConfigs, ModelConfig, PromptMode } from '@/models/debug'
import type { ConsoleClient } from '@/service/console'
import type { AppModeEnum, ModelModeType } from '@/types/app'
import type { ModelModeType } from '@/types/app'
import { useCallback } from 'react'
import { createPublishHandler } from './publish'
@@ -25,7 +26,7 @@ type UseConfigurationPublishParams = {
hasSetBlockStatus: { history: boolean; query: boolean }
isAdvancedMode: boolean
isFunctionCall: boolean
mode: AppModeEnum
mode: ConfigurationAppMode
modelConfig: ModelConfig
promptEmpty: boolean
promptMode: PromptMode
@@ -1,3 +1,4 @@
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type {
ChatPromptConfig,
@@ -17,10 +18,10 @@ import {
import { DEFAULT_CHAT_PROMPT_CONFIG, DEFAULT_COMPLETION_PROMPT_CONFIG } from '@/config'
import { PromptMode } from '@/models/debug'
import { fetchPromptTemplate } from '@/service/debug'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
type Param = {
appMode?: AppModeEnum
appMode?: ConfigurationAppMode
modelModeType: ModelModeType
modelName: string
promptMode: PromptMode
@@ -175,9 +176,7 @@ const useAdvancedPromptConfig = ({
)
if (
[AppModeEnum.ADVANCED_CHAT, AppModeEnum.AGENT_CHAT, AppModeEnum.CHAT].includes(
appMode,
) &&
['advanced-chat', 'agent-chat', 'chat'].includes(appMode) &&
completionPromptConfig.conversation_histories_role.assistant_prefix &&
completionPromptConfig.conversation_histories_role.user_prefix
)
@@ -1,6 +1,8 @@
'use client'
import type { ConfigurationPublishConfig } from './configuration-lifecycle/types'
import type { ConfigurationViewModel } from './configuration-view-model'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { OnFeaturesChange } from '@/app/components/base/features/types'
import type { Collection } from '@/app/components/tools/types'
import type { Inputs, ModelConfig, PromptConfig, PromptVariable } from '@/models/debug'
@@ -25,7 +27,7 @@ import {
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { PromptMode } from '@/models/debug'
import { useFileUploadConfig } from '@/service/use-common'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
import { supportFunctionCall } from '@/utils/tool-call'
import { buildConfigurationFeaturesData, getConfigurationPublishingState } from '../utils'
import { buildConfigurationContextValue } from './build-configuration-context'
@@ -61,7 +63,7 @@ export const useConfiguration = (): ConfigurationViewModel => {
const [hasFetchedDetail, setHasFetchedDetail] = useState(false)
// oxlint-disable-next-line eslint-react/use-state -- This custom hook returns a state object.
const featureConfiguration = useFeatureConfigurationState()
const [mode, setMode] = useState<AppModeEnum>(AppModeEnum.CHAT)
const [mode, setMode] = useState<ConfigurationAppMode>('chat')
const [publishedConfig, setPublishedConfig] = useState<ConfigurationPublishConfig | null>(null)
const [conversationId, setConversationId] = useState<string | null>('')
@@ -106,7 +108,7 @@ export const useConfiguration = (): ConfigurationViewModel => {
visionConfig,
} = modelConfiguration
const modelModeType = modelConfig.mode
const isAgent = mode === AppModeEnum.AGENT_CHAT
const isAgent = mode === 'agent-chat'
const [collectionList, setCollectionList] = useState<Collection[]>([])
// oxlint-disable-next-line eslint-react/use-state -- This custom hook returns a state object.
@@ -1,5 +1,7 @@
'use client'
import type { FC } from 'react'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Inputs } from '@/models/debug'
import type { VisionFile, VisionSettings } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
@@ -25,10 +27,10 @@ import FeatureBar from '@/app/components/base/features/new-feature-panel/feature
import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader'
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
import ConfigContext from '@/context/debug-configuration'
import { AppModeEnum, ModelModeType } from '@/types/app'
import { ModelModeType } from '@/types/app'
export type IPromptValuePanelProps = {
appType: AppModeEnum
appType: ConfigurationAppMode
onSend?: () => void
inputs: Inputs
visionConfig: VisionSettings
@@ -93,7 +95,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
}, [promptVariables, inputs, setInputs])
const canNotRun = useMemo(() => {
if (mode !== AppModeEnum.COMPLETION) return true
if (mode !== 'completion') return true
if (isAdvancedMode) {
if (modelModeType === ModelModeType.chat)
@@ -320,7 +322,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
<div className="mx-3">
<FeatureBar
showFileUpload={false}
isChatMode={appType !== AppModeEnum.COMPLETION}
isChatMode={appType !== 'completion'}
onFeatureBarClick={onOpenFeatures}
disabled={readonly}
hideEditEntrance={readonly}
@@ -1,3 +1,4 @@
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { Features as FeaturesData, FileUpload } from '@/app/components/base/features/types'
import type { Collection } from '@/app/components/tools/types'
import type {
@@ -8,7 +9,7 @@ import type {
} from '@/models/debug'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import { AppModeEnum, ModelModeType, Resolution } from '@/types/app'
import { ModelModeType, Resolution } from '@/types/app'
export const withCollectionIconBasePath = (collectionList: Collection[], prefix?: string) => {
if (!prefix) return collectionList
@@ -84,12 +85,12 @@ export const getConfigurationPublishingState = ({
hasSetContextVar: boolean
hasSelectedDataSets: boolean
isAdvancedMode: boolean
mode: AppModeEnum
mode: ConfigurationAppMode
modelModeType: ModelModeType
promptTemplate: string
}) => {
const promptEmpty = (() => {
if (mode !== AppModeEnum.COMPLETION) return false
if (mode !== 'completion') return false
if (isAdvancedMode) {
if (modelModeType === ModelModeType.chat)
@@ -102,7 +103,7 @@ export const getConfigurationPublishingState = ({
})()
const cannotPublish = (() => {
if (mode !== AppModeEnum.COMPLETION) {
if (mode !== 'completion') {
if (!isAdvancedMode) return false
if (modelModeType === ModelModeType.completion) {
@@ -118,6 +119,6 @@ export const getConfigurationPublishingState = ({
return {
promptEmpty,
cannotPublish,
contextVarEmpty: mode === AppModeEnum.COMPLETION && hasSelectedDataSets && !hasSetContextVar,
contextVarEmpty: mode === 'completion' && hasSelectedDataSets && !hasSetContextVar,
}
}
@@ -1,6 +1,7 @@
'use client'
import type { RecommendedAppResponse } from '@dify/contracts/api/console/explore/types.gen'
import type { AppType } from '@/app/components/apps/app-type'
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
import { IconButton } from '@langgenius/dify-ui/icon-button'
import { InputGroup, InputGroupAddon, InputGroupInput } from '@langgenius/dify-ui/input-group'
@@ -23,7 +24,6 @@ import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { useCanImportAgents } from '@/features/agent-v2/permissions'
import { useImportDSL } from '@/hooks/use-import-dsl'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { hasPermission } from '@/utils/permission'
import AppCard from '../app-card'
@@ -62,7 +62,7 @@ const Apps = ({ onClose, onCreateFromBlank, templateMode }: AppsProps) => {
searchInputRef.current?.focus()
}
const [currentType, setCurrentType] = useState<AppModeEnum[]>([])
const [currentType, setCurrentType] = useState<AppType[]>([])
const [currCategory, setCurrCategory] = useState<AppCategories | string>(allCategoriesEn)
const { data, isLoading } = useQuery(
@@ -74,7 +74,7 @@ const Apps = ({ onClose, onCreateFromBlank, templateMode }: AppsProps) => {
() =>
[...(data?.recommended_apps ?? [])]
.filter((item) =>
templateMode ? item.app?.mode === templateMode : item.app?.mode !== AppModeEnum.AGENT,
templateMode ? item.app?.mode === templateMode : item.app?.mode !== 'agent',
)
.sort((a, b) => (a.position ?? 0) - (b.position ?? 0)),
[data?.recommended_apps, templateMode],
@@ -101,18 +101,11 @@ const Apps = ({ onClose, onCreateFromBlank, templateMode }: AppsProps) => {
})
if (currentType.length === 0) return filteredByCategory
return filteredByCategory.filter((item) => {
if (currentType.includes(AppModeEnum.CHAT) && item.app?.mode === AppModeEnum.CHAT) return true
if (
currentType.includes(AppModeEnum.ADVANCED_CHAT) &&
item.app?.mode === AppModeEnum.ADVANCED_CHAT
)
return true
if (currentType.includes(AppModeEnum.AGENT_CHAT) && item.app?.mode === AppModeEnum.AGENT_CHAT)
return true
if (currentType.includes(AppModeEnum.COMPLETION) && item.app?.mode === AppModeEnum.COMPLETION)
return true
if (currentType.includes(AppModeEnum.WORKFLOW) && item.app?.mode === AppModeEnum.WORKFLOW)
return true
if (currentType.includes('chat') && item.app?.mode === 'chat') return true
if (currentType.includes('advanced-chat') && item.app?.mode === 'advanced-chat') return true
if (currentType.includes('agent-chat') && item.app?.mode === 'agent-chat') return true
if (currentType.includes('completion') && item.app?.mode === 'completion') return true
if (currentType.includes('workflow') && item.app?.mode === 'workflow') return true
return false
})
}, [currentType, activeCategory, allCategoriesEn, data, allList])
@@ -152,7 +145,7 @@ const Apps = ({ onClose, onCreateFromBlank, templateMode }: AppsProps) => {
})
if (
!canCreateTemplate(detail.mode) ||
(templateMode ? detail.mode !== templateMode : detail.mode === AppModeEnum.AGENT)
(templateMode ? detail.mode !== templateMode : detail.mode === 'agent')
)
throw new Error('Template mode does not match this picker')
await handleImportDSL(
@@ -1,6 +1,7 @@
'use client'
import type { Hotkey } from '@tanstack/react-hotkeys'
import type { AppType } from '@/app/components/apps/app-type'
import type { IconPickerValue } from '@/app/components/base/icon-picker'
import { zPostAppsBody } from '@dify/contracts/api/console/apps/zod.gen'
import { Button } from '@langgenius/dify-ui/button'
@@ -29,7 +30,6 @@ import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import useTheme from '@/hooks/use-theme'
import { useRouter } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { trackCreateApp } from '@/utils/create-app-tracking'
import { hasPermission } from '@/utils/permission'
@@ -39,17 +39,13 @@ import { CreateAppDialogShell } from '../create-app-dialog-shell'
type CreateAppProps = {
onClose: () => void
onCreateFromTemplate?: () => void
defaultAppMode?: AppModeEnum
defaultAppMode?: AppType
}
const CREATE_APP_HOTKEY = 'Mod+Enter' satisfies Hotkey
const shouldExpandBeginnerAppTypes = (appMode?: AppModeEnum) => {
return (
appMode === AppModeEnum.CHAT ||
appMode === AppModeEnum.AGENT_CHAT ||
appMode === AppModeEnum.COMPLETION
)
const shouldExpandBeginnerAppTypes = (appMode?: AppType) => {
return appMode === 'chat' || appMode === 'agent-chat' || appMode === 'completion'
}
function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppProps) {
@@ -58,7 +54,7 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
const nameInputId = useId()
const contentRef = useRef<HTMLDivElement>(null)
const [appMode, setAppMode] = useState<AppModeEnum>(defaultAppMode || AppModeEnum.ADVANCED_CHAT)
const [appMode, setAppMode] = useState<AppType>(defaultAppMode || 'advanced-chat')
const [appIcon, setAppIcon] = useState<IconPickerValue>({
type: 'emoji',
icon: '🤖',
@@ -209,7 +205,7 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
<div>
<div className="flex flex-row gap-2">
<AppTypeCard
active={appMode === AppModeEnum.WORKFLOW}
active={appMode === 'workflow'}
title={t(($) => $['types.workflow'], { ns: 'app' })}
description={t(($) => $['newApp.workflowShortDescription'], { ns: 'app' })}
icon={
@@ -221,11 +217,11 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
</div>
}
onClick={() => {
setAppMode(AppModeEnum.WORKFLOW)
setAppMode('workflow')
}}
/>
<AppTypeCard
active={appMode === AppModeEnum.ADVANCED_CHAT}
active={appMode === 'advanced-chat'}
title={t(($) => $['types.advanced'], { ns: 'app' })}
description={t(($) => $['newApp.advancedShortDescription'], { ns: 'app' })}
icon={
@@ -237,7 +233,7 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
</div>
}
onClick={() => {
setAppMode(AppModeEnum.ADVANCED_CHAT)
setAppMode('advanced-chat')
}}
/>
</div>
@@ -261,7 +257,7 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
{isAppTypeExpanded && (
<div className="flex flex-row gap-2">
<AppTypeCard
active={appMode === AppModeEnum.CHAT}
active={appMode === 'chat'}
title={t(($) => $['types.chatbot'], { ns: 'app' })}
description={t(($) => $['newApp.chatbotShortDescription'], { ns: 'app' })}
icon={
@@ -273,11 +269,11 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
</div>
}
onClick={() => {
setAppMode(AppModeEnum.CHAT)
setAppMode('chat')
}}
/>
<AppTypeCard
active={appMode === AppModeEnum.AGENT_CHAT}
active={appMode === 'agent-chat'}
title={t(($) => $['types.agent'], { ns: 'app' })}
description={t(($) => $['newApp.agentShortDescription'], { ns: 'app' })}
icon={
@@ -289,11 +285,11 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
</div>
}
onClick={() => {
setAppMode(AppModeEnum.AGENT_CHAT)
setAppMode('agent-chat')
}}
/>
<AppTypeCard
active={appMode === AppModeEnum.COMPLETION}
active={appMode === 'completion'}
title={t(($) => $['newApp.completeApp'], { ns: 'app' })}
description={t(($) => $['newApp.completionShortDescription'], { ns: 'app' })}
icon={
@@ -305,7 +301,7 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
</div>
}
onClick={() => {
setAppMode(AppModeEnum.COMPLETION)
setAppMode('completion')
}}
/>
</div>
@@ -400,20 +396,11 @@ function CreateApp({ onClose, onCreateFromTemplate, defaultAppMode }: CreateAppP
'repeating-linear-gradient(135deg, transparent, transparent 2px, rgba(16,24,40,0.04) 4px,transparent 3px, transparent 6px)',
}}
>
<AppScreenShot show={appMode === AppModeEnum.CHAT} mode={AppModeEnum.CHAT} />
<AppScreenShot
show={appMode === AppModeEnum.ADVANCED_CHAT}
mode={AppModeEnum.ADVANCED_CHAT}
/>
<AppScreenShot
show={appMode === AppModeEnum.AGENT_CHAT}
mode={AppModeEnum.AGENT_CHAT}
/>
<AppScreenShot
show={appMode === AppModeEnum.COMPLETION}
mode={AppModeEnum.COMPLETION}
/>
<AppScreenShot show={appMode === AppModeEnum.WORKFLOW} mode={AppModeEnum.WORKFLOW} />
<AppScreenShot show={appMode === 'chat'} mode={'chat'} />
<AppScreenShot show={appMode === 'advanced-chat'} mode={'advanced-chat'} />
<AppScreenShot show={appMode === 'agent-chat'} mode={'agent-chat'} />
<AppScreenShot show={appMode === 'completion'} mode={'completion'} />
<AppScreenShot show={appMode === 'workflow'} mode={'workflow'} />
</div>
<div className="absolute inset-x-0 border-b border-b-divider-subtle"></div>
</div>
@@ -479,31 +466,31 @@ function AppTypeCard({ icon, title, description, active, onClick }: AppTypeCardP
)
}
function AppPreview({ mode }: { mode: AppModeEnum }) {
function AppPreview({ mode }: { mode: AppType }) {
const { t } = useTranslation(['app'])
const previewInfo = (() => {
switch (mode) {
case AppModeEnum.CHAT:
case 'chat':
return {
title: t(($) => $['types.chatbot'], { ns: 'app' }),
description: t(($) => $['newApp.chatbotUserDescription'], { ns: 'app' }),
}
case AppModeEnum.ADVANCED_CHAT:
case 'advanced-chat':
return {
title: t(($) => $['types.advanced'], { ns: 'app' }),
description: t(($) => $['newApp.advancedUserDescription'], { ns: 'app' }),
}
case AppModeEnum.AGENT_CHAT:
case 'agent-chat':
return {
title: t(($) => $['types.agent'], { ns: 'app' }),
description: t(($) => $['newApp.agentUserDescription'], { ns: 'app' }),
}
case AppModeEnum.COMPLETION:
case 'completion':
return {
title: t(($) => $['newApp.completeApp'], { ns: 'app' }),
description: t(($) => $['newApp.completionUserDescription'], { ns: 'app' }),
}
case AppModeEnum.WORKFLOW:
case 'workflow':
return {
title: t(($) => $['types.workflow'], { ns: 'app' }),
description: t(($) => $['newApp.workflowUserDescription'], { ns: 'app' }),
@@ -525,14 +512,14 @@ function AppPreview({ mode }: { mode: AppModeEnum }) {
)
}
function AppScreenShot({ mode, show }: { mode: AppModeEnum; show: boolean }) {
function AppScreenShot({ mode, show }: { mode: AppType; show: boolean }) {
const { theme } = useTheme()
const modeToImageMap = {
[AppModeEnum.CHAT]: 'Chatbot',
[AppModeEnum.ADVANCED_CHAT]: 'Chatflow',
[AppModeEnum.AGENT_CHAT]: 'Agent',
[AppModeEnum.COMPLETION]: 'TextGenerator',
[AppModeEnum.WORKFLOW]: 'Workflow',
chat: 'Chatbot',
'advanced-chat': 'Chatflow',
'agent-chat': 'Agent',
completion: 'TextGenerator',
workflow: 'Workflow',
}
return (
<picture>
@@ -1,8 +1,7 @@
'use client'
import type { AppImportPayload, Import } from '@dify/contracts/api/console/apps/types.gen'
import type { AppImportPayload, AppMode, Import } from '@dify/contracts/api/console/apps/types.gen'
import type { Hotkey } from '@tanstack/react-hotkeys'
import type { AppModeEnum } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import {
Dialog,
@@ -30,7 +29,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useRouter } from '@/next/navigation'
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'
import { getErrorMessage } from '@/utils/error-message'
@@ -65,20 +63,20 @@ type ImportSource =
const CREATE_FROM_DSL_HOTKEY = 'Mod+Enter' satisfies Hotkey
function getImportedAppMode(mode?: string | null): AppModeEnum | undefined {
function getImportedAppMode(mode?: string | null): AppMode | undefined {
switch (mode) {
case AppMode.COMPLETION:
return AppMode.COMPLETION
case AppMode.WORKFLOW:
return AppMode.WORKFLOW
case AppMode.CHAT:
return AppMode.CHAT
case AppMode.ADVANCED_CHAT:
return AppMode.ADVANCED_CHAT
case AppMode.AGENT_CHAT:
return AppMode.AGENT_CHAT
case AppMode.AGENT:
return AppMode.AGENT
case 'completion':
return 'completion'
case 'workflow':
return 'workflow'
case 'chat':
return 'chat'
case 'advanced-chat':
return 'advanced-chat'
case 'agent-chat':
return 'agent-chat'
case 'agent':
return 'agent'
default:
return undefined
}
+1 -5
View File
@@ -18,7 +18,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { getDocLanguage } from '@/i18n/language'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import { BuiltInEnvironmentCard } from './built-in-environment-card'
import { EnvironmentTable } from './environment-table'
@@ -170,10 +169,7 @@ export default function AppDeploy() {
workspacePermissionKeys,
})
if (
(appDetail.mode !== AppModeEnum.WORKFLOW && appDetail.mode !== AppModeEnum.ADVANCED_CHAT) ||
!canDeploy
)
if ((appDetail.mode !== 'workflow' && appDetail.mode !== 'advanced-chat') || !canDeploy)
return null
return (
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import { useSuspenseQuery } from '@tanstack/react-query'
import * as React from 'react'
@@ -7,7 +8,6 @@ import Log from '@/app/components/app/log'
import WorkflowLog from '@/app/components/app/workflow-log'
import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
type Props = Readonly<{
appId: string
@@ -24,11 +24,11 @@ const LogAnnotation: FC<Props> = ({ appId, pageType }) => {
return (
<div className="flex h-full flex-col px-6 pt-3">
<div className="h-0 grow">
{pageType === PageType.log && appDetail.mode !== AppModeEnum.WORKFLOW && (
{pageType === PageType.log && appDetail.mode !== 'workflow' && (
<Log appDetail={appDetail} />
)}
{pageType === PageType.annotation && <Annotation appDetail={appDetail} />}
{pageType === PageType.log && appDetail.mode === AppModeEnum.WORKFLOW && (
{pageType === PageType.log && appDetail.mode === 'workflow' && (
<WorkflowLog appDetail={appDetail} />
)}
</div>
+1 -3
View File
@@ -10,7 +10,6 @@ import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import Link from '@/next/link'
import { AppModeEnum } from '@/types/app'
import { getRedirectionPath } from '@/utils/app-redirection'
import { basePath } from '@/utils/var'
@@ -46,8 +45,7 @@ const EmptyElement: FC<{ appDetail: AppDetailWithSite }> = ({ appDetail }) => {
const isRbacEnabled = systemFeatures.rbac_enabled
const getWebAppType = (appType: AppDetailWithSite['mode']) => {
if (appType !== AppModeEnum.COMPLETION && appType !== AppModeEnum.WORKFLOW)
return AppModeEnum.CHAT
if (appType !== 'completion' && appType !== 'workflow') return 'chat'
return appType
}
+1 -2
View File
@@ -14,7 +14,6 @@ import { APP_PAGE_LIMIT } from '@/config'
import { useDocLink } from '@/context/i18n'
import { usePathname, useRouter, useSearchParams } from '@/next/navigation'
import { useChatConversations, useCompletionConversations } from '@/service/use-log'
import { AppModeEnum } from '@/types/app'
import PageTitle from '../log-annotation/page-title'
import {
resolveLogTimePeriod,
@@ -96,7 +95,7 @@ const Logs: FC<ILogsProps> = ({ appDetail }) => {
}, [appDetail.id, currPage, limit, queryParams])
// Get the app type first
const isChatMode = appDetail.mode !== AppModeEnum.COMPLETION
const isChatMode = appDetail.mode !== 'completion'
const query = {
page: currPage + 1,
+5 -11
View File
@@ -61,7 +61,6 @@ import {
} from '@/service/log'
import { AppSourceType } from '@/service/share'
import { useChatConversationDetail, useCompletionConversationDetail } from '@/service/use-log'
import { AppModeEnum } from '@/types/app'
import PromptLogModal from '../../base/prompt-log-modal'
import {
applyAnnotationAdded,
@@ -301,12 +300,7 @@ function DetailPanel({ appDetail, detail, onClose, onFeedback }: IDetailPanel) {
// Only load initial messages, don't auto-load more
useEffect(() => {
if (
appDetail.id &&
detail.id &&
appDetail.mode !== AppModeEnum.COMPLETION &&
!fetchInitiated.current
) {
if (appDetail.id && detail.id && appDetail.mode !== 'completion' && !fetchInitiated.current) {
// Mark as initialized, but don't auto-load more messages
fetchInitiated.current = true
// Still call fetchData to get initial messages
@@ -400,8 +394,8 @@ function DetailPanel({ appDetail, detail, onClose, onFeedback }: IDetailPanel) {
}
}, [hasMore, isLoading, loadMoreMessages])
const isChatMode = appDetail.mode !== AppModeEnum.COMPLETION
const isAdvanced = appDetail.mode === AppModeEnum.ADVANCED_CHAT
const isChatMode = appDetail.mode !== 'completion'
const isAdvanced = appDetail.mode === 'advanced-chat'
const logKind = selectedLogItem?.workflow_run_id
? 'workflow'
: selectedLogItem?.agent_thoughts?.length
@@ -752,8 +746,8 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
const closingConversationIdRef = useRef<string | null>(null)
const pendingConversationIdRef = useRef<string | null>(null)
const pendingConversationCacheRef = useRef<ConversationSelection | undefined>(undefined)
const isChatMode = appDetail.mode !== AppModeEnum.COMPLETION // Whether the app is a chat app
const isChatflow = appDetail.mode === AppModeEnum.ADVANCED_CHAT // Whether the app is a chatflow app
const isChatMode = appDetail.mode !== 'completion' // Whether the app is a chat app
const isChatflow = appDetail.mode === 'advanced-chat' // Whether the app is a chatflow app
const activeConversationId =
conversationIdInUrl ?? pendingConversationIdRef.current ?? currentConversation?.id
@@ -1,4 +1,5 @@
'use client'
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { ReactNode } from 'react'
import { Button, buttonVariants } from '@langgenius/dify-ui/button'
@@ -14,7 +15,6 @@ import {
import { IconButton } from '@langgenius/dify-ui/icon-button'
import { useTranslation } from 'react-i18next'
import { useDocLink } from '@/context/i18n'
import { AppModeEnum } from '@/types/app'
type CustomizeDialogProps = {
disabled?: boolean
@@ -62,7 +62,7 @@ export function CustomizeDialog({
}: CustomizeDialogProps) {
const { t } = useTranslation(['appOverview', 'common'])
const docLink = useDocLink()
const isChatApp = mode === AppModeEnum.CHAT || mode === AppModeEnum.ADVANCED_CHAT
const isChatApp = mode === 'chat' || mode === 'advanced-chat'
const repository =
sourceCodeRepository ?? (isChatApp ? 'webapp-conversation' : 'webapp-text-generator')
const apiDocLink = docLink('/api-reference/guides/get-started')
@@ -63,7 +63,6 @@ import { deploymentEditionAtom } from '@/features/system-features/state'
import { languages } from '@/i18n/language'
import Link from '@/next/link'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
type SettingsDialogProps = {
isChat: boolean
@@ -110,10 +109,10 @@ export type SettingsAppInfo = {
const INPUT_PLACEHOLDER_MAX_LENGTH = 64
const INPUT_PLACEHOLDER_SUPPORTED_MODES: ReadonlyArray<AppDetailWithSite['mode']> = [
AppModeEnum.CHAT,
AppModeEnum.AGENT_CHAT,
AppModeEnum.ADVANCED_CHAT,
]
'chat',
'agent-chat',
'advanced-chat',
] as const
const prefixSettings = 'overview.appInfo.settings'
type SelectOption = {
@@ -484,12 +483,7 @@ function SettingsForm({
</FieldLabel>
<Switch
readOnly={pending}
disabled={
!(
appInfo.mode === AppModeEnum.WORKFLOW ||
appInfo.mode === AppModeEnum.ADVANCED_CHAT
)
}
disabled={!(appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat')}
checked={inputInfo.show_workflow_steps}
onCheckedChange={(v) =>
setInputInfo((item) => ({ ...item, show_workflow_steps: v }))
@@ -30,7 +30,6 @@ import { toast } from '@/app/notifications'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { useRouter } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
type SwitchAppModalProps = {
@@ -105,10 +104,7 @@ const SwitchAppModal = ({ show, sourceApp, onClose }: SwitchAppModalProps) => {
getRedirection(
{
id: newAppID,
mode:
sourceApp.mode === AppModeEnum.COMPLETION
? AppModeEnum.WORKFLOW
: AppModeEnum.ADVANCED_CHAT,
mode: sourceApp.mode === 'completion' ? 'workflow' : 'advanced-chat',
permission_keys,
},
removeOriginal ? replace : push,
+15 -20
View File
@@ -1,3 +1,4 @@
import type { AppType } from '@/app/components/apps/app-type'
import { cn } from '@langgenius/dify-ui/cn'
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
import {
@@ -8,20 +9,14 @@ import {
} from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { AppModeEnum } from '@/types/app'
import { APP_TYPES } from '@/app/components/apps/app-type'
type AppSelectorProps = {
value: Array<AppModeEnum>
value: Array<AppType>
onChange: (value: AppSelectorProps['value']) => void
}
const allTypes: AppModeEnum[] = [
AppModeEnum.WORKFLOW,
AppModeEnum.ADVANCED_CHAT,
AppModeEnum.CHAT,
AppModeEnum.AGENT_CHAT,
AppModeEnum.COMPLETION,
]
const allTypes = APP_TYPES
const AppTypeSelector = ({ value, onChange }: AppSelectorProps) => {
const { t } = useTranslation(['app', 'common'])
@@ -92,7 +87,7 @@ export const AppTypeIcon = React.memo(
wrapperClassName,
)
const iconClassNames = cn('size-3.5 text-components-avatar-shape-fill-stop-100', className)
if (type === AppModeEnum.CHAT) {
if (type === 'chat') {
return (
<div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-blue-solid')}>
<span
@@ -105,7 +100,7 @@ export const AppTypeIcon = React.memo(
</div>
)
}
if (type === AppModeEnum.AGENT_CHAT || type === AppModeEnum.AGENT) {
if (type === 'agent-chat' || type === 'agent') {
return (
<div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-violet-solid')}>
<span
@@ -115,7 +110,7 @@ export const AppTypeIcon = React.memo(
</div>
)
}
if (type === AppModeEnum.ADVANCED_CHAT) {
if (type === 'advanced-chat') {
return (
<div
style={style}
@@ -131,14 +126,14 @@ export const AppTypeIcon = React.memo(
</div>
)
}
if (type === AppModeEnum.WORKFLOW) {
if (type === 'workflow') {
return (
<div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-indigo-solid')}>
<RiExchange2Fill className={iconClassNames} />
</div>
)
}
if (type === AppModeEnum.COMPLETION) {
if (type === 'completion') {
return (
<div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-teal-solid')}>
<span
@@ -197,7 +192,7 @@ function AppTypeSelectTrigger({ values }: { readonly values: AppSelectorProps['v
type AppTypeSelectorItemProps = {
checked: boolean
type: AppModeEnum
type: AppType
onClick: () => void
}
function AppTypeSelectorItem({ checked, type, onClick }: AppTypeSelectorItemProps) {
@@ -230,12 +225,12 @@ function AppTypeSelectorItem({ checked, type, onClick }: AppTypeSelectorItemProp
}
function getAppTypeLabel(type: string, t: ReturnType<typeof useTranslation>['t']) {
if (type === AppModeEnum.CHAT) return t(($) => $['typeSelector.chatbot'], { ns: 'app' })
if (type === AppModeEnum.AGENT_CHAT || type === AppModeEnum.AGENT)
if (type === 'chat') return t(($) => $['typeSelector.chatbot'], { ns: 'app' })
if (type === 'agent-chat' || type === 'agent')
return t(($) => $['typeSelector.agent'], { ns: 'app' })
if (type === AppModeEnum.COMPLETION) return t(($) => $['typeSelector.completion'], { ns: 'app' })
if (type === AppModeEnum.ADVANCED_CHAT) return t(($) => $['typeSelector.advanced'], { ns: 'app' })
if (type === AppModeEnum.WORKFLOW) return t(($) => $['typeSelector.workflow'], { ns: 'app' })
if (type === 'completion') return t(($) => $['typeSelector.completion'], { ns: 'app' })
if (type === 'advanced-chat') return t(($) => $['typeSelector.advanced'], { ns: 'app' })
if (type === 'workflow') return t(($) => $['typeSelector.workflow'], { ns: 'app' })
return ''
}
+1 -2
View File
@@ -25,7 +25,6 @@ import { useTranslation } from 'react-i18next'
import { LoadingPlaceholder } from '@/app/components/base/loading-placeholder'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import useTimestamp from '@/hooks/use-timestamp'
import { AppModeEnum } from '@/types/app'
import DetailPanel from './detail'
import TriggerByDisplay from './trigger-by-display'
@@ -67,7 +66,7 @@ const WorkflowAppLogList: FC<ILogs> = ({ logs, appDetail, onRefresh }) => {
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')
}
const isWorkflow = appDetail?.mode === AppModeEnum.WORKFLOW
const isWorkflow = appDetail?.mode === 'workflow'
const statusTdRender = (status: string) => {
if (status === 'succeeded') {
+5 -6
View File
@@ -16,7 +16,6 @@ import { userProfileQueryOptions } from '@/features/account-profile/client'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AppCardTags } from '@/features/tag-management/components/app-card-tags'
import Link from '@/next/link'
import { AppModeEnum } from '@/types/app'
import { getRedirectionPath } from '@/utils/app-redirection'
import {
getAppACLCapabilities,
@@ -86,15 +85,15 @@ export const AppCard = memo(
const appModeLabel = useMemo(() => {
switch (app.mode) {
case AppModeEnum.CHAT:
case 'chat':
return t(($) => $['types.chatbot'], { ns: 'app' })
case AppModeEnum.ADVANCED_CHAT:
case 'advanced-chat':
return t(($) => $['types.advanced'], { ns: 'app' })
case AppModeEnum.AGENT_CHAT:
case 'agent-chat':
return t(($) => $['types.agent'], { ns: 'app' })
case AppModeEnum.COMPLETION:
case 'completion':
return t(($) => $['types.completion'], { ns: 'app' })
case AppModeEnum.WORKFLOW:
case 'workflow':
return t(($) => $['types.workflow'], { ns: 'app' })
default:
return app.mode
@@ -58,7 +58,6 @@ import { AccessMode } from '@/models/access-control'
import { useRouter } from '@/next/navigation'
import { useGetUserCanAccessApp } from '@/service/access-control/use-app-access-control'
import { consoleClient, consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirection } from '@/utils/app-redirection'
import { getAppACLCapabilities, hasPermission } from '@/utils/permission'
import { basePath } from '@/utils/var'
@@ -78,9 +77,9 @@ const AppExportConfirmModal = dynamic(() => import('@/app/components/app/export-
const OPERATIONS_MENU_POPUP_CLASS_NAME = 'min-w-[216px]'
const APP_MODES_REQUIRING_PUBLISHED_WORKFLOW_IN_EXPLORE = new Set<AppPartial['mode']>([
AppModeEnum.ADVANCED_CHAT,
AppModeEnum.WORKFLOW,
])
'advanced-chat',
'workflow',
] as const)
function requiresPublishedWorkflowInExplore(app: AppPartial) {
return APP_MODES_REQUIRING_PUBLISHED_WORKFLOW_IN_EXPLORE.has(app.mode)
@@ -477,8 +476,7 @@ export function AppCardInteractions({
if (isExporting) return
setIsOperationsMenuOpen(false)
const isWorkflowApp =
app.mode === AppModeEnum.WORKFLOW || app.mode === AppModeEnum.ADVANCED_CHAT
const isWorkflowApp = app.mode === 'workflow' || app.mode === 'advanced-chat'
const result = isWorkflowApp
? await exportWorkflowAppDsl({ appId: app.id, appName: app.name })
: await exportAppDsl({ appId: app.id, appName: app.name })
@@ -515,8 +513,7 @@ export function AppCardInteractions({
const shouldShowDuplicateOption = canCreateApp
const shouldShowExportOption = appACLCapabilities.canImportExportDSL
const shouldShowSwitchOption =
appACLCapabilities.canEdit &&
(app.mode === AppModeEnum.COMPLETION || app.mode === AppModeEnum.CHAT)
appACLCapabilities.canEdit && (app.mode === 'completion' || app.mode === 'chat')
const shouldShowAccessConfigOption = appACLCapabilities.canAccessConfig
const shouldShowDeleteOption = appACLCapabilities.canDelete
const shouldShowOperationsMenu =
+1 -3
View File
@@ -17,7 +17,6 @@ import { InfiniteScrollSentinel } from '@/app/components/base/infinite-scroll-se
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/console'
import { AppModeEnum } from '@/types/app'
import { AppCard } from './app-card'
import { AppCardSkeleton } from './app-card-skeleton'
import { APP_LIST_GRID_CLASS_NAME } from './constants'
@@ -104,8 +103,7 @@ function AppListCatalogContent({
const workflowOnlineUserAppIds = useMemo(() => {
const appIds = new Set<string>()
apps.forEach((app) => {
if (app.mode === AppModeEnum.WORKFLOW || app.mode === AppModeEnum.ADVANCED_CHAT)
appIds.add(app.id)
if (app.mode === 'workflow' || app.mode === 'advanced-chat') appIds.add(app.id)
})
return Array.from(appIds)
}, [apps])
+16
View File
@@ -0,0 +1,16 @@
import type { CreateAppPayload } from '@dify/contracts/api/console/apps/types.gen'
export type AppType = CreateAppPayload['mode']
export type WorkflowAppMode = Extract<AppType, 'workflow' | 'advanced-chat'>
export const APP_TYPES = [
'workflow',
'advanced-chat',
'chat',
'agent-chat',
'completion',
] as const satisfies readonly AppType[]
export function isWorkflowAppMode(mode: string): mode is WorkflowAppMode {
return mode === 'workflow' || mode === 'advanced-chat'
}
+2 -5
View File
@@ -2,17 +2,14 @@ import type { GetAppsData } from '@dify/contracts/api/console/apps/types.gen'
import type { inferParserType } from 'nuqs'
import { zGetAppsQuery } from '@dify/contracts/api/console/apps/zod.gen'
import { createParser, debounce, parseAsString, parseAsStringLiteral } from 'nuqs'
import { APP_TYPES } from './app-type'
import { APP_LIST_SEARCH_DEBOUNCE_MS } from './constants'
type AppListMode = NonNullable<NonNullable<GetAppsData['query']>['mode']>
export const studioAppListCategories = [
'all',
'workflow',
'advanced-chat',
'chat',
'agent-chat',
'completion',
...APP_TYPES,
] as const satisfies readonly AppListMode[]
const studioAppListCategorySchema = zGetAppsQuery.shape.mode
@@ -1,13 +1,12 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import type { RelatedApp } from '@/models/datasets'
import { AppModeEnum } from '@/types/app'
import LinkedAppsPanel from '.'
const mockRelatedApps: RelatedApp[] = [
{
id: 'app-cx',
name: 'Customer Support Assistant',
mode: AppModeEnum.CHAT,
mode: 'chat' as const,
icon_type: 'emoji',
icon: '\u{1F4AC}',
icon_background: '#EEF2FF',
@@ -16,7 +15,7 @@ const mockRelatedApps: RelatedApp[] = [
{
id: 'app-ops',
name: 'Ops Workflow Orchestrator',
mode: AppModeEnum.WORKFLOW,
mode: 'workflow' as const,
icon_type: 'emoji',
icon: '\u{1F6E0}\u{FE0F}',
icon_background: '#ECFDF3',
@@ -25,7 +24,7 @@ const mockRelatedApps: RelatedApp[] = [
{
id: 'app-research',
name: 'Research Synthesizer',
mode: AppModeEnum.ADVANCED_CHAT,
mode: 'advanced-chat' as const,
icon_type: 'emoji',
icon: '\u{1F9E0}',
icon_background: '#FDF2FA',
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { RelatedApp } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
@@ -6,7 +7,6 @@ import { RiArrowRightUpLine } from '@remixicon/react'
import * as React from 'react'
import AppIcon from '@/app/components/base/app-icon'
import Link from '@/next/link'
import { AppModeEnum } from '@/types/app'
type ILikedItemProps = Readonly<{
appStatus?: boolean
@@ -14,12 +14,12 @@ type ILikedItemProps = Readonly<{
isMobile: boolean
}>
const appTypeMap = {
[AppModeEnum.CHAT]: 'Chatbot',
[AppModeEnum.COMPLETION]: 'Completion',
[AppModeEnum.AGENT_CHAT]: 'Agent',
[AppModeEnum.ADVANCED_CHAT]: 'Chatflow',
[AppModeEnum.WORKFLOW]: 'Workflow',
const appTypeMap: Partial<Record<RelatedApp['mode'], string>> = {
chat: 'Chatbot',
completion: 'Completion',
'agent-chat': 'Agent',
'advanced-chat': 'Chatflow',
workflow: 'Workflow',
}
const LikedItem = ({ detail, isMobile }: ILikedItemProps) => {
@@ -1,4 +1,5 @@
'use client'
import type {
AppDetailWithSite,
UpdateAppPayload,
@@ -29,7 +30,6 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { toast } from '@/app/notifications'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
export type CreateAppModalProps = {
show: boolean
@@ -269,9 +269,7 @@ const CreateAppModal = ({
</div>
{/* answer icon */}
{isEditModal &&
(appMode === AppModeEnum.CHAT ||
appMode === AppModeEnum.ADVANCED_CHAT ||
appMode === AppModeEnum.AGENT_CHAT) && (
(appMode === 'chat' || appMode === 'advanced-chat' || appMode === 'agent-chat') && (
<div className="pt-2">
<div className="flex items-center justify-between">
<div className="py-2 text-sm leading-5 font-medium text-text-primary">
@@ -1,32 +1,24 @@
import type { AppPartial } from '@dify/contracts/api/console/apps/types.gen'
import type { ActionItem, AppSearchResult, SearchQueryOptions, SearchResult } from './types'
import type { AppModeEnum as AppMode } from '@/types/app'
import { isWorkflowAppMode } from '@/app/components/apps/app-type'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getRedirectionPath } from '@/utils/app-redirection'
import { AppTypeIcon } from '../../app/type-selector'
import AppIcon from '../../base/app-icon'
const WORKFLOW_MODES = new Set([AppModeEnum.WORKFLOW, AppModeEnum.ADVANCED_CHAT])
const APP_MODES = new Set<string>(Object.values(AppModeEnum))
type AppSection = { id: string; label: string; path: string; iconClassName: string }
function getAppMode(app: AppPartial): AppMode {
return APP_MODES.has(app.mode) ? (app.mode as AppMode) : AppModeEnum.CHAT
}
function getAppPath(app: AppPartial) {
return getRedirectionPath({
id: app.id,
mode: getAppMode(app),
mode: app.mode,
permission_keys: app.permission_keys,
})
}
const getAppSections = (app: AppPartial): AppSection[] => {
const base = `/app/${app.id}`
if (WORKFLOW_MODES.has(getAppMode(app))) {
if (isWorkflowAppMode(app.mode)) {
return [
{
id: 'workflow',
@@ -76,7 +68,7 @@ const appIcon = (app: AppPartial) => (
<AppTypeIcon
wrapperClassName="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-sm border border-divider-regular outline-solid outline-components-panel-on-panel-item-bg"
className="size-3"
type={getAppMode(app)}
type={app.mode}
/>
</div>
)
@@ -28,7 +28,6 @@ import {
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
import { AppModeEnum } from '@/types/app'
type AppPickerProps = Pick<ComboboxPositionerProps, 'placement'> & {
scope?: string
@@ -48,15 +47,15 @@ type AppPickerProps = Pick<ComboboxPositionerProps, 'placement'> & {
function getAppTypeLabel(app: AppPartial) {
switch (app.mode) {
case AppModeEnum.ADVANCED_CHAT:
case 'advanced-chat':
return 'chatflow'
case AppModeEnum.AGENT_CHAT:
case 'agent-chat':
return 'agent'
case AppModeEnum.CHAT:
case 'chat':
return 'chat'
case AppModeEnum.COMPLETION:
case 'completion':
return 'completion'
case AppModeEnum.WORKFLOW:
case 'workflow':
return 'workflow'
default:
return app.mode
@@ -1,4 +1,5 @@
'use client'
import type {
AppDetailWithSite,
AppPartial,
@@ -13,7 +14,7 @@ import { BlockEnum, InputVarType, SupportUploadFileTypes } from '@/app/component
import { consoleQuery } from '@/service/console'
import { useFileUploadConfig } from '@/service/use-common'
import { useAppWorkflow } from '@/service/use-workflow'
import { AppModeEnum, Resolution } from '@/types/app'
import { Resolution } from '@/types/app'
const BASIC_INPUT_TYPE_MAP: Record<string, string> = {
paragraph: 'paragraph',
@@ -49,11 +50,11 @@ type WorkflowNodeWithVariables = {
}
function isBasicAppMode(mode: string): boolean {
return mode !== AppModeEnum.ADVANCED_CHAT && mode !== AppModeEnum.WORKFLOW
return mode !== 'advanced-chat' && mode !== 'workflow'
}
function supportsImageUpload(mode: string): boolean {
return mode === AppModeEnum.COMPLETION || mode === AppModeEnum.WORKFLOW
return mode === 'completion' || mode === 'workflow'
}
function buildFileConfig(fileConfig: FileUpload | undefined) {
@@ -1,7 +1,6 @@
import { skipToken, useQuery } from '@tanstack/react-query'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
export const useIsChatMode = () => {
const { appId } = useParams<{ appId?: string }>()
@@ -12,5 +11,5 @@ export const useIsChatMode = () => {
}),
)
return appMode === AppModeEnum.ADVANCED_CHAT
return appMode === 'advanced-chat'
}
@@ -1,3 +1,4 @@
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { Node, WorkflowDataUpdater } from '@/app/components/workflow/types'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
@@ -6,7 +7,6 @@ import startPlaceholderDefault from '@/app/components/workflow/nodes/start-place
import { BlockEnum } from '@/app/components/workflow/types'
import { generateNewNode } from '@/app/components/workflow/utils'
import { normalizeWorkflowNodes } from '@/app/components/workflow/utils/normalize-workflow-nodes'
import { AppModeEnum } from '@/types/app'
type HydrateWorkflowDraftGraphOptions = {
localStartPlaceholderNodes?: Node[]
@@ -26,16 +26,12 @@ const hasStartPlaceholderNode = (nodes: Node[] = []): boolean => {
return nodes.some((node) => node?.data?.type === BlockEnum.StartPlaceholder)
}
export const useWorkflowDraftGraphForCanvas = (appMode?: AppModeEnum | string) => {
export const useWorkflowDraftGraphForCanvas = (appMode?: AppMode | string) => {
const { t } = useTranslation(['workflow'])
const getNodesWithLocalStartPlaceholder = useCallback(
(nodes: Node[] = [], localStartPlaceholderNodes?: Node[]) => {
if (
appMode !== AppModeEnum.WORKFLOW ||
hasWorkflowEntryNode(nodes) ||
hasStartPlaceholderNode(nodes)
)
if (appMode !== 'workflow' || hasWorkflowEntryNode(nodes) || hasStartPlaceholderNode(nodes))
return nodes
if (localStartPlaceholderNodes?.length) return [...localStartPlaceholderNodes, ...nodes]
@@ -14,7 +14,6 @@ import { consoleQuery } from '@/service/console'
import { useWorkflowConfig } from '@/service/use-workflow'
import { fetchNodesDefaultConfigs, fetchWorkflowDraft, syncWorkflowDraft } from '@/service/workflow'
import { appWorkflowQueryOptions } from '@/service/workflow-queries'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import { useWorkflowDraftGraphForCanvas } from './use-workflow-draft-graph-for-canvas'
import { useWorkflowTemplate } from './use-workflow-template'
@@ -133,7 +132,7 @@ export const useWorkflowInit = () => {
} catch (error: unknown) {
if (error instanceof ORPCError) {
if (error.code === 'draft_workflow_not_exist') {
const isAdvancedChat = appDetail.mode === AppModeEnum.ADVANCED_CHAT
const isAdvancedChat = appDetail.mode === 'advanced-chat'
const initialGraph = {
nodes: isAdvancedChat ? nodesTemplate : [],
edges: isAdvancedChat ? edgesTemplate : [],
@@ -10,7 +10,6 @@ import { WorkflowRunningStatus } from '@/app/components/workflow/types'
import { toast } from '@/app/notifications'
import { handleStream, post } from '@/service/base'
import { ContentType } from '@/service/fetch'
import { AppModeEnum } from '@/types/app'
type HandleRunMode = TriggerType
export type HandleRunOptions = {
@@ -116,7 +115,7 @@ export const createFailedWorkflowState = (error: string) => {
}
export const buildRunHistoryUrl = (appDetail?: AppDetailLike) => {
return appDetail?.mode === AppModeEnum.ADVANCED_CHAT
return appDetail?.mode === 'advanced-chat'
? `/apps/${appDetail.id}/advanced-chat/workflow-runs`
: `/apps/${appDetail?.id}/workflow-runs`
}
@@ -148,7 +147,7 @@ export const resolveWorkflowRunUrl = (
return `/apps/${appDetail.id}/workflows/draft/trigger/run-all`
}
if (appDetail?.mode === AppModeEnum.ADVANCED_CHAT)
if (appDetail?.mode === 'advanced-chat')
return `/apps/${appDetail.id}/advanced-chat/workflows/draft/run`
if (isInWorkflowDebug && appDetail?.id) return `/apps/${appDetail.id}/workflows/draft/run`
@@ -22,7 +22,6 @@ import { ssePost } from '@/service/base'
import { consoleQuery } from '@/service/console'
import { useInvalidAllLastRun, useInvalidateWorkflowRunHistory } from '@/service/use-workflow'
import { stopWorkflowRun } from '@/service/workflow'
import { AppModeEnum } from '@/types/app'
import { useConfigsMap } from './use-configs-map'
import { useNodesSyncDraft, useNodesSyncDraftByCanEdit } from './use-nodes-sync-draft'
import {
@@ -235,7 +234,7 @@ const useWorkflowRunBase = (doSyncWorkflowDraft: DoSyncWorkflowDraft) => {
const { clientWidth, clientHeight } = workflowContainer!
const isInWorkflowDebug = appDetail.mode === AppModeEnum.WORKFLOW
const isInWorkflowDebug = appDetail.mode === 'workflow'
const url = resolveWorkflowRunUrl(appDetail, runMode, isInWorkflowDebug)
const requestBody = buildWorkflowRunRequestBody(runMode, resolvedParams, options)
@@ -9,7 +9,6 @@ import startDefault from '@/app/components/workflow/nodes/start/default'
import { generateNewNode } from '@/app/components/workflow/utils'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { useIsChatMode } from './use-is-chat-mode'
export const useWorkflowTemplate = () => {
@@ -89,7 +88,7 @@ export const useWorkflowTemplate = () => {
edges: [startToLlmEdge, llmToAnswerEdge],
}
}
if (appDetail.mode === AppModeEnum.WORKFLOW) {
if (appDetail.mode === 'workflow') {
const { newNode: startPlaceholderNode } = generateNewNode({
data: {
...startPlaceholderDefault.defaultValue,
+1 -2
View File
@@ -19,7 +19,6 @@ import { useParams, useSearchParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { fetchRunDetail } from '@/service/log'
import { useAppTriggers } from '@/service/use-tools'
import { AppModeEnum } from '@/types/app'
import { getAppACLCapabilities } from '@/utils/permission'
import WorkflowAppMain from './components/workflow-main'
import { useGetRunAndTraceUrl } from './hooks/use-get-run-and-trace-url'
@@ -53,7 +52,7 @@ const WorkflowAppWithAdditionalContext = () => {
}),
[appDetail.maintainer, appDetail.permission_keys, currentUserId, workspacePermissionKeys],
)
const isWorkflowMode = appDetail.mode === AppModeEnum.WORKFLOW
const isWorkflowMode = appDetail.mode === 'workflow'
const { data: triggersResponse } = useAppTriggers(isWorkflowMode ? appId : undefined, {
staleTime: 5 * 60 * 1000, // 5 minutes cache
refetchOnWindowFocus: false,
@@ -45,7 +45,6 @@ import {
useAllWorkflowTools,
} from '@/service/use-tools'
import { useAllTriggerPlugins } from '@/service/use-triggers'
import { AppModeEnum } from '@/types/app'
import { FlowType } from '@/types/common'
import { CUSTOM_NODE } from '../constants'
import { useDatasetsDetailStore } from '../datasets-detail-store/store'
@@ -190,8 +189,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[], options?: { flowType?
select: (appDetail) => appDetail.mode,
}),
)
const shouldCheckStartNode =
appMode === AppModeEnum.WORKFLOW || appMode === AppModeEnum.ADVANCED_CHAT
const shouldCheckStartNode = appMode === 'workflow' || appMode === 'advanced-chat'
const { data: modelProviders = EMPTY_MODEL_PROVIDERS } = useQuery(
consoleQuery.workspaces.current.modelProviders.summary.get.queryOptions({
select: (response) => response.data,
@@ -664,8 +662,7 @@ export const useChecklistBeforePublish = () => {
select: (appDetail) => appDetail.mode,
}),
)
const shouldCheckStartNode =
appMode === AppModeEnum.WORKFLOW || appMode === AppModeEnum.ADVANCED_CHAT
const shouldCheckStartNode = appMode === 'workflow' || appMode === 'advanced-chat'
const getCheckData = useCallback(
(
@@ -9,7 +9,6 @@ import { getIncomers, getOutgoers } from 'reactflow'
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
import { CUSTOM_LOOP_START_NODE } from '@/app/components/workflow/nodes/loop-start/constants'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { SUPPORT_OUTPUT_VARS_NODE } from '../constants'
import { useHooksStore } from '../hooks-store'
import {
@@ -31,7 +30,7 @@ export const useIsChatMode = () => {
const { data: isChatMode } = useQuery(
consoleQuery.apps.byAppId.get.queryOptions({
input: appId ? { params: { app_id: appId } } : skipToken,
select: (app) => app.mode === AppModeEnum.ADVANCED_CHAT,
select: (app) => app.mode === 'advanced-chat',
}),
)
@@ -37,7 +37,6 @@ import Form from '@/app/components/header/account-setting/model-provider-page/mo
import { useDocLink } from '@/context/i18n'
import { useRenderI18nObject } from '@/hooks/use-i18n'
import Link from '@/next/link'
import { AppModeEnum } from '@/types/app'
import { useWorkflowStore } from '../../../store'
import { AgentStrategySelector } from './agent-strategy-selector'
import Field from './field'
@@ -172,7 +171,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
modelConfig={
defaultModel.data
? {
mode: AppModeEnum.CHAT,
mode: 'chat',
name: defaultModel.data.model,
provider: defaultModel.data.provider.provider,
completion_params: {},
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { CodeLanguage } from '../../code/types'
import type { GenRes } from '@/service/debug'
@@ -8,7 +9,6 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { GetCodeGeneratorResModal } from '@/app/components/app/configuration/config/code-generator/get-code-generator-res'
import { AppModeEnum } from '@/types/app'
import { useHooksStore } from '../../../hooks-store'
type Props = Readonly<{
@@ -48,7 +48,7 @@ const CodeGenerateBtn: FC<Props> = ({
</IconButton>
{showAutomatic && (
<GetCodeGeneratorResModal
mode={AppModeEnum.CHAT}
modelMode="chat"
isShow={showAutomatic}
codeLanguages={codeLanguages}
onClose={() => setShowAutomatic(false)}
@@ -64,7 +64,6 @@ import { resolveVarType } from '@/app/components/workflow/nodes/tool/output-sche
import PluginTriggerNodeDefault from '@/app/components/workflow/nodes/trigger-plugin/default'
import { BlockEnum, InputVarType, VarType } from '@/app/components/workflow/types'
import { VAR_REGEX } from '@/config'
import { AppModeEnum } from '@/types/app'
import { OUTPUT_FILE_SUB_VARIABLES } from '../../../constants'
import { Type } from '../../../llm/types'
@@ -1232,7 +1231,7 @@ export const getNodeUsedVars = (node: Node, { forExecution = false } = {}): Valu
}
case BlockEnum.LLM: {
const payload = data as LLMNodeType
const isChatModel = payload.model?.mode === AppModeEnum.CHAT
const isChatModel = payload.model?.mode === 'chat'
let prompts: string[] = []
if (isChatModel) {
prompts = (payload.prompt_template as PromptItem[])?.flatMap(getPromptItemTexts) || []
@@ -1571,7 +1570,7 @@ export const updateNodeVars = (
}
case BlockEnum.LLM: {
const payload = data as LLMNodeType
const isChatModel = payload.model?.mode === AppModeEnum.CHAT
const isChatModel = payload.model?.mode === 'chat'
if (isChatModel) {
payload.prompt_template = (payload.prompt_template as PromptItem[]).map((prompt) =>
replaceOldVarInPromptItem(prompt, oldVarSelector, newVarSelector),
@@ -10,7 +10,6 @@ import { getProcessedHumanInputFormInputs } from '@/app/components/base/chat/cha
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { fetchHumanInputNodeStepRunForm, submitHumanInputNodeStepRunForm } from '@/service/workflow'
import { AppModeEnum } from '@/types/app'
import useNodeCrud from '../../_base/hooks/use-node-crud'
import { getHumanInputFormDependencySelectors, isOutput } from '../utils'
@@ -77,7 +76,7 @@ const useSingleRunFormParams = ({
select: (appDetail) => appDetail.mode,
}),
)
const isWorkflowMode = appMode === AppModeEnum.WORKFLOW
const isWorkflowMode = appMode === 'workflow'
const fetchURL = useMemo(() => {
if (!appId) return ''
if (!isWorkflowMode) {
@@ -13,7 +13,6 @@ import { useCallback } from 'react'
import { v4 as uuid4 } from 'uuid'
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
import { VarType } from '@/app/components/workflow/types'
import { AppModeEnum } from '@/types/app'
import { ComparisonOperator, LogicalOperator, MetadataFilteringVariableType } from '../types'
type Params = {
@@ -115,7 +114,7 @@ const useKnowledgeMetadataConfig = ({ id, inputRef, setInputs }: Params) => {
draft.metadata_model_config = {
provider: model.provider,
name: model.modelId,
mode: model.mode || AppModeEnum.CHAT,
mode: model.mode || 'chat',
completion_params: draft.metadata_model_config?.completion_params || { temperature: 0.7 },
}
})
@@ -6,7 +6,7 @@ import { isEqual } from 'es-toolkit/predicate'
import { produce } from 'immer'
import { useCallback, useEffect } from 'react'
import { DATASET_DEFAULT } from '@/config'
import { AppModeEnum, RETRIEVE_TYPE } from '@/types/app'
import { RETRIEVE_TYPE } from '@/types/app'
import { getMultipleRetrievalConfig } from '../utils'
type ModelIdentity = {
@@ -67,7 +67,7 @@ const useKnowledgeModelConfig = ({
const draftModel = draft.single_retrieval_config!.model
draftModel.provider = model.provider
draftModel.name = model.modelId
draftModel.mode = model.mode || AppModeEnum.CHAT
draftModel.mode = model.mode || 'chat'
})
setInputs(nextInputs)
},
@@ -120,7 +120,7 @@ const useKnowledgeModelConfig = ({
draft.single_retrieval_config = createSingleRetrievalConfig({
provider: currentProvider.provider,
name: currentModel.model,
mode: currentModel.model_properties?.mode || AppModeEnum.CHAT,
mode: currentModel.model_properties?.mode || 'chat',
completion_params: {},
})
}
@@ -168,7 +168,7 @@ const useKnowledgeModelConfig = ({
draft.single_retrieval_config = createSingleRetrievalConfig({
provider: currentProvider?.provider || '',
name: currentModel?.model || '',
mode: currentModel?.model_properties?.mode || AppModeEnum.CHAT,
mode: currentModel?.model_properties?.mode || 'chat',
completion_params: {},
})
}
@@ -1,4 +1,5 @@
'use client'
import type { FC } from 'react'
import type { ModelConfig } from '@/app/components/workflow/types'
import type { GenRes } from '@/service/debug'
@@ -8,7 +9,6 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
import { AppModeEnum } from '@/types/app'
import { useHooksStore } from '../../../hooks-store'
type Props = Readonly<{
@@ -48,7 +48,7 @@ const PromptGeneratorBtn: FC<Props> = ({
</IconButton>
{showAutomatic && (
<GetAutomaticResModal
mode={AppModeEnum.CHAT}
modelMode="chat"
isShow={showAutomatic}
onClose={() => setShowAutomatic(false)}
onFinished={handleAutomaticRes}
@@ -3,7 +3,6 @@ import type { EnvironmentVariable, NodeDefault, PromptItem } from '../../types'
import type { LLMNodeType } from './types'
import { genNodeMetaData } from '@/app/components/workflow/utils'
// import { RETRIEVAL_OUTPUT_STRUCT } from '../../constants'
import { AppModeEnum } from '@/types/app'
import { FlowType } from '@/types/common'
import { BlockEnum, EditionType, PromptRole } from '../../types'
import {
@@ -45,7 +44,7 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
model: {
provider: '',
name: '',
mode: AppModeEnum.CHAT,
mode: 'chat',
completion_params: {
temperature: 0.7,
},
@@ -100,7 +99,7 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
})
if (!errorMessages && !payload.memory) {
const isChatModel = model?.mode === AppModeEnum.CHAT
const isChatModel = model?.mode === 'chat'
const isPromptEmpty = isChatModel
? !(payload.prompt_template as PromptItem[]).some((t) => {
if (t.edition_type === EditionType.jinja2) return t.jinja2_text !== ''
@@ -118,7 +117,7 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
}
if (!errorMessages && !!payload.memory) {
const isChatModel = model?.mode === AppModeEnum.CHAT
const isChatModel = model?.mode === 'chat'
// payload.memory.query_prompt_template not pass is default: {{#sys.query#}}
if (
!isSnippetFlow &&
@@ -130,7 +129,7 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
}
if (!errorMessages) {
const isChatModel = model?.mode === AppModeEnum.CHAT
const isChatModel = model?.mode === 'chat'
const isShowVars = (() => {
if (isChatModel)
return (payload.prompt_template as PromptItem[]).some(
@@ -6,7 +6,6 @@ import { useCallback, useEffect, useState } from 'react'
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 useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
import { AppModeEnum } from '@/types/app'
import useConfigVision from '../../hooks/use-config-vision'
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
import { useIsChatMode, useNodesReadOnly } from '../../hooks/use-workflow'
@@ -45,7 +44,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
name: '',
}
const modelMode = model.mode
const isChatModel = modelMode === AppModeEnum.CHAT
const isChatModel = modelMode === 'chat'
const isCompletionModel = !isChatModel
const { inputRef, setInputs, appendDefaultPromptConfig } = useLLMInputManager({
@@ -91,7 +90,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
draft.model_selector = modelSelector
const isModeChange = model.mode !== inputRef.current.model.mode
if (isModeChange && defaultConfig && Object.keys(defaultConfig).length > 0)
appendDefaultPromptConfig(draft, defaultConfig, model.mode === AppModeEnum.CHAT)
appendDefaultPromptConfig(draft, defaultConfig, model.mode === 'chat')
})
setInputs(nextInputs)
setModelChanged(true)
@@ -7,7 +7,6 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useHooksStore } from '@/app/components/workflow/hooks-store/store'
import { InputVarType, VarType } from '@/app/components/workflow/types'
import { AppModeEnum } from '@/types/app'
import { FlowType } from '@/types/common'
import useConfigVision from '../../hooks/use-config-vision'
import { useIsChatMode } from '../../hooks/use-workflow'
@@ -71,7 +70,7 @@ const useSingleRunFormParams = ({
// model
const model = inputs.model
const modelMode = inputs.model?.mode
const isChatModel = modelMode === AppModeEnum.CHAT
const isChatModel = modelMode === 'chat'
const { isVisionModel } = useConfigVision(model, {
payload: inputs.vision,
onChange: noop,
@@ -4,7 +4,6 @@ import type { ParameterExtractorNodeType } from './types'
import { BlockClassification } from '@/app/components/workflow/block-selector/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { genNodeMetaData } from '@/app/components/workflow/utils'
import { AppModeEnum } from '@/types/app'
import { ReasoningModeType } from './types'
const i18nPrefix = ''
@@ -21,7 +20,7 @@ const nodeDefault: NodeDefault<ParameterExtractorNodeType> = {
model: {
provider: '',
name: '',
mode: AppModeEnum.CHAT,
mode: 'chat',
completion_params: {
temperature: 0.7,
},
@@ -10,7 +10,6 @@ import {
} from '@/app/components/header/account-setting/model-provider-page/hooks'
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
import { AppModeEnum } from '@/types/app'
import { supportFunctionCall } from '@/utils/tool-call'
import useConfigVision from '../../hooks/use-config-vision'
import useInspectVarsCrud from '../../hooks/use-inspect-vars-crud'
@@ -109,13 +108,13 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
const model = inputs.model || {
provider: '',
name: '',
mode: AppModeEnum.CHAT,
mode: 'chat',
completion_params: {
temperature: 0.7,
},
}
const modelMode = inputs.model?.mode
const isChatModel = modelMode === AppModeEnum.CHAT
const isChatModel = modelMode === 'chat'
const isCompletionModel = !isChatModel
const {
@@ -159,7 +158,7 @@ const useConfig = (id: string, payload: ParameterExtractorNodeType) => {
draft.model.mode = model.mode!
const isModeChange = model.mode !== inputRef.current.model?.mode
if (isModeChange && defaultConfig && Object.keys(defaultConfig).length > 0)
appendDefaultPromptConfig(draft, defaultConfig, model.mode === AppModeEnum.CHAT)
appendDefaultPromptConfig(draft, defaultConfig, model.mode === 'chat')
})
setInputs(newInputs)
setModelChanged(true)
@@ -4,7 +4,6 @@ import type { QuestionClassifierNodeType } from './types'
import { BlockClassification } from '@/app/components/workflow/block-selector/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { genNodeMetaData } from '@/app/components/workflow/utils'
import { AppModeEnum } from '@/types/app'
const i18nPrefix = ''
@@ -20,7 +19,7 @@ const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
model: {
provider: '',
name: '',
mode: AppModeEnum.CHAT,
mode: 'chat',
completion_params: {
temperature: 0.7,
},
@@ -9,7 +9,6 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { useHooksStore } from '@/app/components/workflow/hooks-store/store'
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
import { AppModeEnum } from '@/types/app'
import { FlowType } from '@/types/common'
import useConfigVision from '../../hooks/use-config-vision'
import { useIsChatMode, useNodesReadOnly, useWorkflow } from '../../hooks/use-workflow'
@@ -49,7 +48,7 @@ const useConfig = (id: string, payload: QuestionClassifierNodeType) => {
const model = inputs.model
const modelMode = inputs.model?.mode
const isChatModel = modelMode === AppModeEnum.CHAT
const isChatModel = modelMode === 'chat'
const handleVisionChange = useCallback(
(newPayload: QuestionClassifierNodeType['vision']) => {
@@ -3,7 +3,6 @@ import type { TFunction } from 'i18next'
import type { CommonNodeType, Node } from './types'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
import { DSLImportStatus } from '@/models/app'
import { AppModeEnum } from '@/types/app'
import { loadYaml } from '@/utils/yaml'
import { BlockEnum, SupportUploadFileTypes } from './types'
@@ -46,7 +45,7 @@ type ImportNotificationPayload = {
}
export const getInvalidNodeTypes = (mode?: AppMode): BlockEnum[] => {
if (mode === AppModeEnum.ADVANCED_CHAT) {
if (mode === 'advanced-chat') {
return [
BlockEnum.End,
BlockEnum.TriggerWebhook,
@@ -1,11 +1,10 @@
import { AppModeEnum } from '@/types/app'
import { BlockEnum } from '../types'
export const normalizeWorkflowNodes = <T extends { data: Record<string, unknown> }>(
nodes: T[],
appMode?: string,
): T[] => {
if (appMode !== AppModeEnum.WORKFLOW) return nodes
if (appMode !== 'workflow') return nodes
return nodes.map((node) => {
if (node.data.type !== BlockEnum.LLM || !('memory' in node.data)) return node
@@ -14,7 +14,6 @@ import { LoadingPlaceholder } from '@/app/components/base/loading-placeholder'
import BlockIcon from '@/app/components/workflow/block-icon'
import { VariableIconWithColor } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { AppModeEnum } from '@/types/app'
import { VarInInspectType } from '@/types/workflow'
import GetCodeGeneratorResModal from '../../app/configuration/config/code-generator/get-code-generator-res'
import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '../../base/prompt-editor/plugins/update-block'
@@ -329,7 +328,7 @@ const Right = ({ nodeId, currentNodeVar, handleOpenMenu, isValueFetching }: Prop
(isCodeBlock ? (
<GetCodeGeneratorResModal
isShow
mode={AppModeEnum.CHAT}
modelMode="chat"
onClose={handleHidePromptGenerator}
flowId={configsMap?.flowId || ''}
nodeId={nodeId}
@@ -339,7 +338,7 @@ const Right = ({ nodeId, currentNodeVar, handleOpenMenu, isValueFetching }: Prop
/>
) : (
<GetAutomaticResModal
mode={AppModeEnum.CHAT}
modelMode="chat"
isShow
onClose={handleHidePromptGenerator}
onFinished={handleUpdatePrompt}
@@ -1,5 +1,5 @@
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { GeneratedGraph, WorkflowGeneratorMode } from './types'
import type { AppModeEnum } from '@/types/app'
import { normalizeWorkflowNodes } from '@/app/components/workflow/utils/normalize-workflow-nodes'
import { consoleClient } from '@/service/console'
import { getHttpErrorStatus } from '@/service/http-error'
@@ -8,7 +8,7 @@ import { fetchWorkflowDraft, syncWorkflowDraft } from '@/service/workflow'
const MODE_TO_APP_MODE = {
workflow: 'workflow',
'advanced-chat': 'advanced-chat',
} as const satisfies Record<WorkflowGeneratorMode, AppModeEnum>
} as const satisfies Record<WorkflowGeneratorMode, AppMode>
/**
* Thrown by ``applyToCurrentApp`` when the backend rejects the sync because
@@ -86,7 +86,7 @@ export const applyToNewApp = async ({
icon,
}: ApplyToNewAppParams): Promise<{
appId: string
appMode: AppModeEnum
appMode: AppMode
permissionKeys?: string[]
}> => {
const appMode = MODE_TO_APP_MODE[mode]
@@ -134,7 +134,7 @@ export const applyToNewApp = async ({
type ApplyToCurrentAppParams = {
appId: string
appMode?: AppModeEnum
appMode?: AppMode
graph: GeneratedGraph
}
+4 -3
View File
@@ -1,4 +1,5 @@
import type { RefObject } from 'react'
import type { ConfigurationAppMode } from '@/app/components/app/configuration/hooks/configuration-lifecycle/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Collection } from '@/app/components/tools/types'
import type { ExternalDataTool } from '@/models/common'
@@ -31,7 +32,7 @@ import {
DEFAULT_COMPLETION_PROMPT_CONFIG,
} from '@/config'
import { PromptMode } from '@/models/debug'
import { AppModeEnum, ModelModeType, Resolution, RETRIEVE_TYPE, TransferMethod } from '@/types/app'
import { ModelModeType, Resolution, RETRIEVE_TYPE, TransferMethod } from '@/types/app'
type IDebugConfiguration = {
readonly?: boolean
@@ -39,7 +40,7 @@ type IDebugConfiguration = {
onOpenFeatures: () => void
appId: string
isTrailFinished: boolean
mode: AppModeEnum
mode: ConfigurationAppMode
modelModeType: ModelModeType
promptMode: PromptMode
setPromptMode: (promptMode: PromptMode) => void
@@ -122,7 +123,7 @@ const DebugConfigurationContext = createContext<IDebugConfiguration>({
appId: '',
onOpenFeatures: noop,
isTrailFinished: false,
mode: AppModeEnum.CHAT,
mode: 'chat' as const,
modelModeType: ModelModeType.chat,
promptMode: PromptMode.simple,
setPromptMode: noop,
@@ -23,7 +23,6 @@ import AppIcon from '@/app/components/base/app-icon'
import { toast } from '@/app/notifications'
import { getAgentACLCapabilities } from '@/features/agent-v2/acl'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
import { getAgentWebAppUrl } from '../../web-app-access'
import { useWebAppAccessControl } from './use-web-app-access-control'
@@ -325,7 +324,7 @@ function createSettingsAppInfo(agent: AgentAppDetailWithSite): SettingsAppInfo |
return {
id: appId,
mode: AppModeEnum.CHAT,
mode: 'chat' as const,
site: {
title: site.title ?? agent.name,
description: site.description ?? '',
@@ -1,4 +1,5 @@
'use client'
import type { AgentKnowledgeDatasetConfig } from '@dify/contracts/api/console/agent/types.gen'
import type { ReactNode } from 'react'
import type {
@@ -46,7 +47,7 @@ import {
} from '@/features/agent-v2/agent-composer/knowledge-validation'
import { agentComposerKnowledgeRetrievalsAtom } from '@/features/agent-v2/agent-composer/store-modules/knowledge'
import { ChunkingMode, DatasetPermission, DataSourceType } from '@/models/datasets'
import { AppModeEnum, RETRIEVE_METHOD, RETRIEVE_TYPE } from '@/types/app'
import { RETRIEVE_METHOD, RETRIEVE_TYPE } from '@/types/app'
type KnowledgeRetrievalQueryMode = 'agent' | 'custom'
type MetadataFilteringConditions = {
@@ -576,7 +577,7 @@ function AgentKnowledgeRetrievalDialogContent({
model: {
provider: model.provider,
name: model.modelId,
mode: model.mode ?? singleRetrievalConfig?.model.mode ?? AppModeEnum.CHAT,
mode: model.mode ?? singleRetrievalConfig?.model.mode ?? 'chat',
completion_params: singleRetrievalConfig?.model.completion_params ?? {
temperature: 0.7,
},
@@ -590,7 +591,7 @@ function AgentKnowledgeRetrievalDialogContent({
model: {
provider: singleRetrievalConfig?.model.provider ?? '',
name: singleRetrievalConfig?.model.name ?? '',
mode: singleRetrievalConfig?.model.mode ?? AppModeEnum.CHAT,
mode: singleRetrievalConfig?.model.mode ?? 'chat',
completion_params: completionParams,
},
},
@@ -688,7 +689,7 @@ function AgentKnowledgeRetrievalDialogContent({
metadataModelConfig: {
provider: model.provider,
name: model.modelId,
mode: model.mode ?? metadataModelConfig?.mode ?? AppModeEnum.CHAT,
mode: model.mode ?? metadataModelConfig?.mode ?? 'chat',
completion_params: metadataModelConfig?.completion_params ?? { temperature: 0.7 },
},
})
@@ -698,7 +699,7 @@ function AgentKnowledgeRetrievalDialogContent({
metadataModelConfig: {
provider: metadataModelConfig?.provider ?? '',
name: metadataModelConfig?.name ?? '',
mode: metadataModelConfig?.mode ?? AppModeEnum.CHAT,
mode: metadataModelConfig?.mode ?? 'chat',
completion_params: completionParams,
},
})
+1 -2
View File
@@ -2,7 +2,6 @@ import { skipToken, useQuery } from '@tanstack/react-query'
import { trackEvent } from '@/app/components/base/amplitude'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
import { AppModeEnum } from '@/types/app'
export type AgentScope = (typeof AgentScope)[keyof typeof AgentScope]
export const AgentScope = {
@@ -20,7 +19,7 @@ export const useInlineAgentScope = () => {
}),
)
return appMode === AppModeEnum.ADVANCED_CHAT ? AgentScope.InChatflow : AgentScope.InWorkflow
return appMode === 'advanced-chat' ? AgentScope.InChatflow : AgentScope.InWorkflow
}
export const trackAgentBuildModeRun = (agentScope: AgentScope) => {
+6 -6
View File
@@ -1,4 +1,5 @@
'use client'
import type { RecommendedAppResponse } from '@dify/contracts/api/console/explore/types.gen'
import { cn } from '@langgenius/dify-ui/cn'
import { useSuspenseQuery } from '@tanstack/react-query'
@@ -8,7 +9,6 @@ import { AppTypeIcon } from '@/app/components/app/type-selector'
import { trackEvent } from '@/app/components/base/amplitude'
import AppIcon from '@/app/components/base/app-icon'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { AppModeEnum } from '@/types/app'
type TemplateCardProps = {
app: RecommendedAppResponse
@@ -91,27 +91,27 @@ export function TemplateCard({ app, canCreate, onCreate, onTry }: TemplateCardPr
</div>
</div>
<div className="flex items-center system-2xs-medium-uppercase text-text-tertiary">
{appMode === AppModeEnum.ADVANCED_CHAT && (
{appMode === 'advanced-chat' && (
<div className="truncate">
{t(($) => $['types.advanced'], { ns: 'app' }).toUpperCase()}
</div>
)}
{appMode === AppModeEnum.CHAT && (
{appMode === 'chat' && (
<div className="truncate">
{t(($) => $['types.chatbot'], { ns: 'app' }).toUpperCase()}
</div>
)}
{(appMode === AppModeEnum.AGENT_CHAT || appMode === AppModeEnum.AGENT) && (
{(appMode === 'agent-chat' || appMode === 'agent') && (
<div className="truncate">
{t(($) => $['types.agent'], { ns: 'app' }).toUpperCase()}
</div>
)}
{appMode === AppModeEnum.WORKFLOW && (
{appMode === 'workflow' && (
<div className="truncate">
{t(($) => $['types.workflow'], { ns: 'app' }).toUpperCase()}
</div>
)}
{appMode === AppModeEnum.COMPLETION && (
{appMode === 'completion' && (
<div className="truncate">
{t(($) => $['types.completion'], { ns: 'app' }).toUpperCase()}
</div>
+3 -2
View File
@@ -1,10 +1,11 @@
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { TagResponse as Tag } from '@dify/contracts/api/console/tags/types.gen'
import type { DataSourceNotionPage, DataSourceProvider } from './common'
import type { DatasourceType } from './pipeline'
import type { IndexingType } from '@/app/components/datasets/create/step-two'
import type { MetadataItemWithValue } from '@/app/components/datasets/metadata/types'
import type { MetadataFilteringVariableType } from '@/app/components/workflow/nodes/knowledge-retrieval/types'
import type { AppIconType, AppModeEnum, RetrievalConfig, TransferMethod } from '@/types/app'
import type { AppIconType, RetrievalConfig, TransferMethod } from '@/types/app'
import type { SegmentImportStatus } from '@/types/dataset'
import type { I18nKeysByPrefix } from '@/types/i18n'
import { PermissionLevel } from './permission'
@@ -689,7 +690,7 @@ export type ExternalKnowledgeBaseHitTestingResponse = {
export type RelatedApp = {
id: string
name: string
mode: AppModeEnum
mode: AppMode
icon_type: AppIconType | null
icon: string
icon_background: string
+3 -2
View File
@@ -1,6 +1,7 @@
import type { AppMode } from '@dify/contracts/api/console/apps/types.gen'
import type { IOnCompleted, IOnData, IOnError, IOnMessageReplace } from './base'
import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug'
import type { AppModeEnum, ModelModeType } from '@/types/app'
import type { ModelModeType } from '@/types/app'
import { get, post, ssePost } from './base'
type BasicAppFirstRes = {
@@ -95,7 +96,7 @@ export const fetchPromptTemplate = ({
modelName,
hasSetDataSet,
}: {
appMode: AppModeEnum
appMode: AppMode
mode: ModelModeType
modelName: string
hasSetDataSet: boolean
+1 -3
View File
@@ -24,7 +24,6 @@ import type {
} 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 { useInvalid } from './use-base'
import { getFlowPrefix } from './utils'
@@ -279,8 +278,7 @@ export const useUpdateWorkflow = () => {
if (params.appId) syncAppWorkflowVersionCaches(queryClient, params.appId, updatedWorkflow)
const environmentDeploymentsQueryKey =
params.appId &&
(params.appMode === AppModeEnum.WORKFLOW || params.appMode === AppModeEnum.ADVANCED_CHAT)
params.appId && (params.appMode === 'workflow' || params.appMode === 'advanced-chat')
? syncWorkflowDeploymentCaches(queryClient, params.appId, updatedWorkflow)
: undefined
const invalidations = [

Some files were not shown because too many files have changed in this diff Show More