mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: jyong <718720800@qq.com> Co-authored-by: Yansong Zhang <916125788@qq.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: hj24 <mambahj24@gmail.com> Co-authored-by: hj24 <huangjian@dify.ai> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Ayush Baluni <73417844+aayushbaluni@users.noreply.github.com> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: jimcody1995 <jjimcody@gmail.com> Co-authored-by: James <63717587+jamesrayammons@users.noreply.github.com> Co-authored-by: Yunlu Wen <yunlu.wen@dify.ai> Co-authored-by: Stephen Zhou <hi@hyoban.cc> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: jerryzai <jerryzh8710@protonmail.com> Co-authored-by: NVIDIAN <speedy.hpc@hotmail.com> Co-authored-by: ai-hpc <ai-hpc@users.noreply.github.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: Junghwan <70629228+shaun0927@users.noreply.github.com> Co-authored-by: HeYinKazune <70251095+HeYin-OS@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: Jingyi <jingyi.qi@dify.ai> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: sxxtony <166789813+sxxtony@users.noreply.github.com>
157 lines
4.3 KiB
TypeScript
157 lines
4.3 KiB
TypeScript
import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
|
import type { PromptConfig } from '@/models/debug'
|
|
import type { VisionFile, VisionSettings } from '@/types/app'
|
|
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
|
|
import { TransferMethod } from '@/types/app'
|
|
import { formatBooleanInputs } from '@/utils/model-config'
|
|
|
|
export type ResultInputValue
|
|
= | string
|
|
| boolean
|
|
| number
|
|
| string[]
|
|
| Record<string, unknown>
|
|
| FileEntity
|
|
| FileEntity[]
|
|
| undefined
|
|
|
|
type Translate = (key: string, options?: Record<string, unknown>) => string
|
|
|
|
type ValidationResult = {
|
|
canSend: boolean
|
|
notification?: {
|
|
type: 'error' | 'info'
|
|
message: string
|
|
}
|
|
}
|
|
|
|
type ValidateResultRequestParams = {
|
|
completionFiles: VisionFile[]
|
|
inputs: Record<string, ResultInputValue>
|
|
isCallBatchAPI: boolean
|
|
promptConfig: PromptConfig | null
|
|
t: Translate
|
|
}
|
|
|
|
type BuildResultRequestDataParams = {
|
|
completionFiles: VisionFile[]
|
|
inputs: Record<string, ResultInputValue>
|
|
promptConfig: PromptConfig | null
|
|
visionConfig: VisionSettings
|
|
}
|
|
|
|
const isMissingRequiredInput = (
|
|
variable: PromptConfig['prompt_variables'][number],
|
|
value: ResultInputValue,
|
|
) => {
|
|
if (value === undefined || value === null)
|
|
return true
|
|
|
|
if (variable.type === 'file-list')
|
|
return !Array.isArray(value) || value.length === 0
|
|
|
|
if (['string', 'paragraph', 'number', 'json_object', 'select'].includes(variable.type))
|
|
return typeof value !== 'string' ? false : value.trim() === ''
|
|
|
|
return false
|
|
}
|
|
|
|
const hasPendingLocalFiles = (completionFiles: VisionFile[]) => {
|
|
return completionFiles.some(item => item.transfer_method === TransferMethod.local_file && !item.upload_file_id)
|
|
}
|
|
|
|
export const validateResultRequest = ({
|
|
completionFiles,
|
|
inputs,
|
|
isCallBatchAPI,
|
|
promptConfig,
|
|
t,
|
|
}: ValidateResultRequestParams): ValidationResult => {
|
|
if (isCallBatchAPI)
|
|
return { canSend: true }
|
|
|
|
const promptVariables = promptConfig?.prompt_variables
|
|
if (!promptVariables?.length) {
|
|
if (hasPendingLocalFiles(completionFiles)) {
|
|
return {
|
|
canSend: false,
|
|
notification: {
|
|
type: 'info',
|
|
message: t('errorMessage.waitForFileUpload', { ns: 'appDebug' }),
|
|
},
|
|
}
|
|
}
|
|
|
|
return { canSend: true }
|
|
}
|
|
|
|
const requiredVariables = promptVariables.filter(({ key, name, required, type }) => {
|
|
if (type === 'boolean' || type === 'checkbox')
|
|
return false
|
|
|
|
return (!key || !key.trim()) || (!name || !name.trim()) || required === undefined || required === null || required
|
|
})
|
|
|
|
const missingRequiredVariable = requiredVariables.find(variable => isMissingRequiredInput(variable, inputs[variable.key]))?.name
|
|
if (missingRequiredVariable) {
|
|
return {
|
|
canSend: false,
|
|
notification: {
|
|
type: 'error',
|
|
message: t('errorMessage.valueOfVarRequired', {
|
|
ns: 'appDebug',
|
|
key: missingRequiredVariable,
|
|
}),
|
|
},
|
|
}
|
|
}
|
|
|
|
if (hasPendingLocalFiles(completionFiles)) {
|
|
return {
|
|
canSend: false,
|
|
notification: {
|
|
type: 'info',
|
|
message: t('errorMessage.waitForFileUpload', { ns: 'appDebug' }),
|
|
},
|
|
}
|
|
}
|
|
|
|
return { canSend: true }
|
|
}
|
|
|
|
export const buildResultRequestData = ({
|
|
completionFiles,
|
|
inputs,
|
|
promptConfig,
|
|
visionConfig,
|
|
}: BuildResultRequestDataParams) => {
|
|
const processedInputs = {
|
|
...formatBooleanInputs(promptConfig?.prompt_variables, inputs as Record<string, string | number | boolean | object>),
|
|
}
|
|
|
|
promptConfig?.prompt_variables.forEach((variable) => {
|
|
const value = processedInputs[variable.key]
|
|
if (variable.type === 'file' && value && typeof value === 'object' && !Array.isArray(value)) {
|
|
processedInputs[variable.key] = getProcessedFiles([value as FileEntity])[0]!
|
|
return
|
|
}
|
|
|
|
if (variable.type === 'file-list' && Array.isArray(value) && value.length > 0)
|
|
processedInputs[variable.key] = getProcessedFiles(value as FileEntity[])
|
|
})
|
|
|
|
return {
|
|
inputs: processedInputs,
|
|
...(visionConfig.enabled && completionFiles.length > 0
|
|
? {
|
|
files: completionFiles.map((item) => {
|
|
if (item.transfer_method === TransferMethod.local_file)
|
|
return { ...item, url: '' }
|
|
|
|
return item
|
|
}),
|
|
}
|
|
: {}),
|
|
}
|
|
}
|