fix: Validate transfer method in file mapping and improve file input handling (#26848)

Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>
This commit is contained in:
Guangdong Liu 2025-10-14 10:10:31 +08:00 committed by GitHub
parent b745839bdb
commit 9d21772820
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 10 deletions

View File

@ -64,7 +64,10 @@ def build_from_mapping(
config: FileUploadConfig | None = None,
strict_type_validation: bool = False,
) -> File:
transfer_method = FileTransferMethod.value_of(mapping.get("transfer_method"))
transfer_method_value = mapping.get("transfer_method")
if not transfer_method_value:
raise ValueError("transfer_method is required in file mapping")
transfer_method = FileTransferMethod.value_of(transfer_method_value)
build_functions: dict[FileTransferMethod, Callable] = {
FileTransferMethod.LOCAL_FILE: _build_from_local_file,
@ -104,6 +107,8 @@ def build_from_mappings(
) -> Sequence[File]:
# TODO(QuantumGhost): Performance concern - each mapping triggers a separate database query.
# Implement batch processing to reduce database load when handling multiple files.
# Filter out None/empty mappings to avoid errors
valid_mappings = [m for m in mappings if m and m.get("transfer_method")]
files = [
build_from_mapping(
mapping=mapping,
@ -111,7 +116,7 @@ def build_from_mappings(
config=config,
strict_type_validation=strict_type_validation,
)
for mapping in mappings
for mapping in valid_mappings
]
if (

View File

@ -20,7 +20,9 @@ import type { SiteInfo } from '@/models/share'
import { TEXT_GENERATION_TIMEOUT_MS } from '@/config'
import {
getFilesInLogs,
getProcessedFiles,
} from '@/app/components/base/file-uploader/utils'
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { formatBooleanInputs } from '@/utils/model-config'
export type IResultProps = {
@ -160,8 +162,22 @@ const Result: FC<IResultProps> = ({
if (!checkCanSend())
return
// Process inputs: convert file entities to API format
const processedInputs = { ...formatBooleanInputs(promptConfig?.prompt_variables, inputs) }
promptConfig?.prompt_variables.forEach((variable) => {
const value = processedInputs[variable.key]
if (variable.type === 'file' && value && typeof value === 'object' && !Array.isArray(value)) {
// Convert single file entity to API format
processedInputs[variable.key] = getProcessedFiles([value as FileEntity])[0]
}
else if (variable.type === 'file-list' && Array.isArray(value) && value.length > 0) {
// Convert file entity array to API format
processedInputs[variable.key] = getProcessedFiles(value as FileEntity[])
}
})
const data: Record<string, any> = {
inputs: formatBooleanInputs(promptConfig?.prompt_variables, inputs),
inputs: processedInputs,
}
if (visionConfig.enabled && completionFiles && completionFiles?.length > 0) {
data.files = completionFiles.map((item) => {

View File

@ -15,7 +15,6 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config'
import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader'
import type { VisionFile, VisionSettings } from '@/types/app'
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import cn from '@/utils/classnames'
import BoolInput from '@/app/components/workflow/nodes/_base/components/before-run-form/bool-input'
@ -82,9 +81,9 @@ const RunOnce: FC<IRunOnceProps> = ({
else if (item.type === 'checkbox')
newInputs[item.key] = item.default || false
else if (item.type === 'file')
newInputs[item.key] = item.default
newInputs[item.key] = undefined
else if (item.type === 'file-list')
newInputs[item.key] = item.default || []
newInputs[item.key] = []
else
newInputs[item.key] = undefined
})
@ -148,8 +147,8 @@ const RunOnce: FC<IRunOnceProps> = ({
)}
{item.type === 'file' && (
<FileUploaderInAttachmentWrapper
value={inputs[item.key] ? [inputs[item.key]] : []}
onChange={(files) => { handleInputsChange({ ...inputsRef.current, [item.key]: getProcessedFiles(files)[0] }) }}
value={(inputs[item.key] && typeof inputs[item.key] === 'object') ? [inputs[item.key]] : []}
onChange={(files) => { handleInputsChange({ ...inputsRef.current, [item.key]: files[0] }) }}
fileConfig={{
...item.config,
fileUploadConfig: (visionConfig as any).fileUploadConfig,
@ -158,8 +157,8 @@ const RunOnce: FC<IRunOnceProps> = ({
)}
{item.type === 'file-list' && (
<FileUploaderInAttachmentWrapper
value={inputs[item.key]}
onChange={(files) => { handleInputsChange({ ...inputsRef.current, [item.key]: getProcessedFiles(files) }) }}
value={Array.isArray(inputs[item.key]) ? inputs[item.key] : []}
onChange={(files) => { handleInputsChange({ ...inputsRef.current, [item.key]: files }) }}
fileConfig={{
...item.config,
fileUploadConfig: (visionConfig as any).fileUploadConfig,