update single file blocks

This commit is contained in:
Vikhyath Mondreti
2026-02-03 12:09:55 -08:00
parent ff0753a298
commit 47c9604577
16 changed files with 75 additions and 47 deletions

View File

@@ -652,7 +652,7 @@ export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
if (operation === 'upload_attachment') {
const fileInput = attachmentFileUpload || attachmentFileReference || attachmentFile
const normalizedFile = normalizeFileInput(fileInput)
const normalizedFile = normalizeFileInput(fileInput, { single: true })
if (!normalizedFile) {
throw new Error('File is required for upload attachment operation.')
}

View File

@@ -320,7 +320,7 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
// Normalize file input for upload operation
// normalizeFileInput handles JSON stringified values from advanced mode
if (params.fileContent) {
params.fileContent = normalizeFileInput(params.fileContent)
params.fileContent = normalizeFileInput(params.fileContent, { single: true })
}
switch (params.operation) {

View File

@@ -620,12 +620,12 @@ export const FirefliesV2Block: BlockConfig<FirefliesResponse> = {
}
if (params.operation === 'fireflies_upload_audio') {
const audioFiles =
normalizeFileInput(params.audioFile) || normalizeFileInput(params.audioFileReference)
if (!audioFiles || audioFiles.length === 0) {
const audioFile =
normalizeFileInput(params.audioFile, { single: true }) ||
normalizeFileInput(params.audioFileReference, { single: true })
if (!audioFile) {
throw new Error('Audio file is required.')
}
const audioFile = audioFiles[0]
const audioUrl = resolveHttpsUrlFromFileInput(audioFile)
if (!audioUrl) {
throw new Error('Audio file must include a https URL.')

View File

@@ -793,7 +793,7 @@ Return ONLY the message text - no subject line, no greetings/signatures, no extr
} = params
// Normalize file input - handles both basic (file-upload) and advanced (short-input) modes
const normalizedFile = normalizeFileInput(file ?? fileUpload)
const normalizedFile = normalizeFileInput(file ?? fileUpload, { single: true })
// Use folderSelector if provided, otherwise use manualFolderId
const effectiveFolderId = (folderSelector || manualFolderId || '').trim()

View File

@@ -1775,10 +1775,10 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
throw new Error('Issue ID is required.')
}
// Normalize file inputs - handles JSON stringified values from advanced mode
const normalizedUpload = normalizeFileInput(params.attachmentFileUpload)
const normalizedFile = normalizeFileInput(params.file)
// Take the first file from whichever input has data (Linear only accepts single file)
const attachmentFile = normalizedUpload?.[0] || normalizedFile?.[0]
const attachmentFile =
normalizeFileInput(params.attachmentFileUpload, { single: true }) ||
normalizeFileInput(params.file, { single: true })
// Check for multiple files
if (
(normalizedUpload && normalizedUpload.length > 1) ||

View File

@@ -371,7 +371,7 @@ export const OneDriveBlock: BlockConfig<OneDriveResponse> = {
}
// Normalize file input from both basic (file-upload) and advanced (short-input) modes
const normalizedFile = normalizeFileInput(file || fileReference)
const normalizedFile = normalizeFileInput(file || fileReference, { single: true })
return {
credential,

View File

@@ -273,7 +273,7 @@ export const S3Block: BlockConfig<S3Response> = {
}
// Use file from uploadFile if in basic mode, otherwise use file reference
// normalizeFileInput handles JSON stringified values from advanced mode
const fileParam = normalizeFileInput(params.uploadFile || params.file)
const fileParam = normalizeFileInput(params.uploadFile || params.file, { single: true })
return {
accessKeyId: params.accessKeyId,

View File

@@ -788,7 +788,7 @@ export const SpotifyBlock: BlockConfig<ToolResponse> = {
}
// Normalize file input for cover image
if (params.coverImage !== undefined) {
params.coverImage = normalizeFileInput(params.coverImage)
params.coverImage = normalizeFileInput(params.coverImage, { single: true })
}
return params.operation || 'spotify_search'
},

View File

@@ -260,8 +260,9 @@ export const SttBlock: BlockConfig<SttBlockResponse> = {
},
params: (params) => {
// Normalize file input from basic (file-upload) or advanced (short-input) mode
const normalizedFiles = normalizeFileInput(params.audioFile || params.audioFileReference)
const audioFile = normalizedFiles?.[0]
const audioFile = normalizeFileInput(params.audioFile || params.audioFileReference, {
single: true,
})
return {
provider: params.provider,
@@ -393,8 +394,9 @@ export const SttV2Block: BlockConfig<SttBlockResponse> = {
}),
params: (params) => {
// Normalize file input from basic (file-upload) or advanced (short-input) mode
const normalizedFiles = normalizeFileInput(params.audioFile || params.audioFileReference)
const audioFile = normalizedFiles?.[0]
const audioFile = normalizeFileInput(params.audioFile || params.audioFileReference, {
single: true,
})
return {
provider: params.provider,

View File

@@ -982,7 +982,9 @@ Return ONLY the PostgREST filter expression - no explanations, no markdown, no e
// Normalize file input for storage_upload operation
// normalizeFileInput handles JSON stringified values from advanced mode
const normalizedFileData = normalizeFileInput(file || fileContent || fileData)
const normalizedFileData = normalizeFileInput(file || fileContent || fileData, {
single: true,
})
// Parse JSON data if it's a string
let parsedData

View File

@@ -269,46 +269,54 @@ export const TelegramBlock: BlockConfig<TelegramResponse> = {
messageId: params.messageId,
}
case 'telegram_send_photo': {
const photoSource = normalizeFileInput(params.photoFile || params.photo)
if (!photoSource || photoSource.length === 0) {
const photoSource = normalizeFileInput(params.photoFile || params.photo, {
single: true,
})
if (!photoSource) {
throw new Error('Photo is required.')
}
return {
...commonParams,
photo: photoSource[0],
photo: photoSource,
caption: params.caption,
}
}
case 'telegram_send_video': {
const videoSource = normalizeFileInput(params.videoFile || params.video)
if (!videoSource || videoSource.length === 0) {
const videoSource = normalizeFileInput(params.videoFile || params.video, {
single: true,
})
if (!videoSource) {
throw new Error('Video is required.')
}
return {
...commonParams,
video: videoSource[0],
video: videoSource,
caption: params.caption,
}
}
case 'telegram_send_audio': {
const audioSource = normalizeFileInput(params.audioFile || params.audio)
if (!audioSource || audioSource.length === 0) {
const audioSource = normalizeFileInput(params.audioFile || params.audio, {
single: true,
})
if (!audioSource) {
throw new Error('Audio is required.')
}
return {
...commonParams,
audio: audioSource[0],
audio: audioSource,
caption: params.caption,
}
}
case 'telegram_send_animation': {
const animationSource = normalizeFileInput(params.animationFile || params.animation)
if (!animationSource || animationSource.length === 0) {
const animationSource = normalizeFileInput(params.animationFile || params.animation, {
single: true,
})
if (!animationSource) {
throw new Error('Animation is required.')
}
return {
...commonParams,
animation: animationSource[0],
animation: animationSource,
caption: params.caption,
}
}

View File

@@ -265,13 +265,14 @@ export const TextractV2Block: BlockConfig<TextractParserOutput> = {
}
parameters.s3Uri = params.s3Uri.trim()
} else {
const files = normalizeFileInput(
params.fileUpload || params.fileReference || params.document
const file = normalizeFileInput(
params.fileUpload || params.fileReference || params.document,
{ single: true }
)
if (!files || files.length === 0) {
if (!file) {
throw new Error('Document file is required')
}
parameters.file = files[0]
parameters.file = file
}
const featureTypes: string[] = []

View File

@@ -746,7 +746,7 @@ export const VideoGeneratorV2Block: BlockConfig<VideoBlockResponse> = {
duration: params.duration ? Number(params.duration) : undefined,
aspectRatio: params.aspectRatio,
resolution: params.resolution,
visualReference: normalizeFileInput(visualRef),
visualReference: normalizeFileInput(visualRef, { single: true }),
consistencyMode: params.consistencyMode,
stylePreset: params.stylePreset,
promptOptimizer: params.promptOptimizer,

View File

@@ -118,9 +118,10 @@ export const VisionV2Block: BlockConfig<VisionResponse> = {
}),
params: (params) => {
// normalizeFileInput handles JSON stringified values from advanced mode
const normalizedFiles = normalizeFileInput(params.imageFile || params.imageFileReference)
// Vision expects a single file, take the first from the normalized array
const imageFile = normalizedFiles?.[0]
// Vision expects a single file
const imageFile = normalizeFileInput(params.imageFile || params.imageFileReference, {
single: true,
})
return {
...params,
imageFile,

View File

@@ -770,7 +770,7 @@ export const WordPressBlock: BlockConfig<WordPressResponse> = {
case 'wordpress_upload_media':
return {
...baseParams,
file: normalizeFileInput(params.fileUpload || params.file),
file: normalizeFileInput(params.fileUpload || params.file, { single: true }),
filename: params.filename,
title: params.mediaTitle,
caption: params.caption,

View File

@@ -251,7 +251,7 @@ export function createVersionedToolSelector<TParams extends Record<string, any>>
}
/**
* Normalizes file input from block params.
* Normalizes file input from block params to a consistent format.
* Handles the case where template resolution JSON.stringify's arrays/objects
* when they're placed in short-input fields (advanced mode).
*
@@ -260,9 +260,21 @@ export function createVersionedToolSelector<TParams extends Record<string, any>>
* - An array of file objects (basic mode or properly resolved)
* - A single file object
* - A JSON string of file(s) (from advanced mode template resolution)
* @returns Normalized array of file objects, or undefined if no files
* @param options.single - If true, returns only the first file object instead of an array
* @returns Normalized file(s), or undefined if no files
*/
export function normalizeFileInput(fileParam: unknown): object[] | undefined {
export function normalizeFileInput(
fileParam: unknown,
options: { single: true }
): object | undefined
export function normalizeFileInput(
fileParam: unknown,
options?: { single?: false }
): object[] | undefined
export function normalizeFileInput(
fileParam: unknown,
options?: { single?: boolean }
): object | object[] | undefined {
if (!fileParam) return undefined
if (typeof fileParam === 'string') {
@@ -273,13 +285,15 @@ export function normalizeFileInput(fileParam: unknown): object[] | undefined {
}
}
let files: object[] | undefined
if (Array.isArray(fileParam)) {
return fileParam.length > 0 ? fileParam : undefined
files = fileParam.length > 0 ? fileParam : undefined
} else if (typeof fileParam === 'object' && fileParam !== null) {
files = [fileParam]
}
if (typeof fileParam === 'object' && fileParam !== null) {
return [fileParam]
}
if (!files) return undefined
return undefined
return options?.single ? files[0] : files
}