From 42767fc4f4da7b262729f9706e00e36916094763 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Mon, 2 Feb 2026 17:13:23 -0800 Subject: [PATCH] fix types --- .../api/tools/github/latest-commit/route.ts | 31 ++++++++++- .../api/tools/google_drive/download/route.ts | 33 +++++++++--- apps/sim/app/api/tools/image/route.ts | 8 +-- .../app/api/tools/onedrive/download/route.ts | 24 +++++++-- .../app/api/tools/onedrive/upload/route.ts | 53 ++++++++++++++++--- .../api/tools/pipedrive/get-files/route.ts | 14 ++++- .../sim/app/api/tools/textract/parse/route.ts | 3 +- .../api/tools/twilio/get-recording/route.ts | 37 +++++++++++-- .../api/tools/zoom/get-recordings/route.ts | 40 ++++++++++++-- apps/sim/blocks/blocks/discord.ts | 2 +- apps/sim/blocks/blocks/google_slides.ts | 8 +-- apps/sim/blocks/blocks/jira.ts | 2 +- apps/sim/blocks/blocks/outlook.ts | 2 +- apps/sim/blocks/blocks/sendgrid.ts | 2 +- apps/sim/blocks/blocks/sftp.ts | 2 +- apps/sim/blocks/blocks/smtp.ts | 2 +- apps/sim/blocks/blocks/telegram.ts | 2 +- 17 files changed, 224 insertions(+), 41 deletions(-) diff --git a/apps/sim/app/api/tools/github/latest-commit/route.ts b/apps/sim/app/api/tools/github/latest-commit/route.ts index 23df8cf90..39d088dbe 100644 --- a/apps/sim/app/api/tools/github/latest-commit/route.ts +++ b/apps/sim/app/api/tools/github/latest-commit/route.ts @@ -12,6 +12,33 @@ export const dynamic = 'force-dynamic' const logger = createLogger('GitHubLatestCommitAPI') +interface GitHubErrorResponse { + message?: string +} + +interface GitHubCommitResponse { + sha: string + html_url: string + commit: { + message: string + author: { name: string; email: string; date: string } + committer: { name: string; email: string; date: string } + } + author?: { login: string; avatar_url: string; html_url: string } + committer?: { login: string; avatar_url: string; html_url: string } + stats?: { additions: number; deletions: number; total: number } + files?: Array<{ + filename: string + status: string + additions: number + deletions: number + changes: number + patch?: string + raw_url?: string + blob_url?: string + }> +} + const GitHubLatestCommitSchema = z.object({ owner: z.string().min(1, 'Owner is required'), repo: z.string().min(1, 'Repo is required'), @@ -61,7 +88,7 @@ export async function POST(request: NextRequest) { }) if (!response.ok) { - const errorData = await response.json().catch(() => ({})) + const errorData = (await response.json().catch(() => ({}))) as GitHubErrorResponse logger.error(`[${requestId}] GitHub API error`, { status: response.status, error: errorData, @@ -72,7 +99,7 @@ export async function POST(request: NextRequest) { ) } - const data = await response.json() + const data = (await response.json()) as GitHubCommitResponse const content = `Latest commit: "${data.commit.message}" by ${data.commit.author.name} on ${data.commit.author.date}. SHA: ${data.sha}` diff --git a/apps/sim/app/api/tools/google_drive/download/route.ts b/apps/sim/app/api/tools/google_drive/download/route.ts index 1341d54d8..2a9730dca 100644 --- a/apps/sim/app/api/tools/google_drive/download/route.ts +++ b/apps/sim/app/api/tools/google_drive/download/route.ts @@ -19,6 +19,21 @@ export const dynamic = 'force-dynamic' const logger = createLogger('GoogleDriveDownloadAPI') +/** Google API error response structure */ +interface GoogleApiErrorResponse { + error?: { + message?: string + code?: number + status?: string + } +} + +/** Google Drive revisions list response */ +interface GoogleDriveRevisionsResponse { + revisions?: GoogleDriveRevision[] + nextPageToken?: string +} + const GoogleDriveDownloadSchema = z.object({ accessToken: z.string().min(1, 'Access token is required'), fileId: z.string().min(1, 'File ID is required'), @@ -76,7 +91,9 @@ export async function POST(request: NextRequest) { ) if (!metadataResponse.ok) { - const errorDetails = await metadataResponse.json().catch(() => ({})) + const errorDetails = (await metadataResponse + .json() + .catch(() => ({}))) as GoogleApiErrorResponse logger.error(`[${requestId}] Failed to get file metadata`, { status: metadataResponse.status, error: errorDetails, @@ -87,7 +104,7 @@ export async function POST(request: NextRequest) { ) } - const metadata: GoogleDriveFile = await metadataResponse.json() + const metadata = (await metadataResponse.json()) as GoogleDriveFile const fileMimeType = metadata.mimeType let fileBuffer: Buffer @@ -119,7 +136,9 @@ export async function POST(request: NextRequest) { ) if (!exportResponse.ok) { - const exportError = await exportResponse.json().catch(() => ({})) + const exportError = (await exportResponse + .json() + .catch(() => ({}))) as GoogleApiErrorResponse logger.error(`[${requestId}] Failed to export file`, { status: exportResponse.status, error: exportError, @@ -154,7 +173,9 @@ export async function POST(request: NextRequest) { ) if (!downloadResponse.ok) { - const downloadError = await downloadResponse.json().catch(() => ({})) + const downloadError = (await downloadResponse + .json() + .catch(() => ({}))) as GoogleApiErrorResponse logger.error(`[${requestId}] Failed to download file`, { status: downloadResponse.status, error: downloadError, @@ -182,8 +203,8 @@ export async function POST(request: NextRequest) { ) if (revisionsResponse.ok) { - const revisionsData = await revisionsResponse.json() - metadata.revisions = revisionsData.revisions as GoogleDriveRevision[] + const revisionsData = (await revisionsResponse.json()) as GoogleDriveRevisionsResponse + metadata.revisions = revisionsData.revisions logger.info(`[${requestId}] Fetched file revisions`, { fileId, revisionCount: metadata.revisions?.length || 0, diff --git a/apps/sim/app/api/tools/image/route.ts b/apps/sim/app/api/tools/image/route.ts index 86192958f..475a9de5c 100644 --- a/apps/sim/app/api/tools/image/route.ts +++ b/apps/sim/app/api/tools/image/route.ts @@ -68,14 +68,14 @@ export async function GET(request: NextRequest) { const contentType = imageResponse.headers.get('content-type') || 'image/jpeg' - const imageBlob = await imageResponse.blob() + const imageArrayBuffer = await imageResponse.arrayBuffer() - if (imageBlob.size === 0) { - logger.error(`[${requestId}] Empty image blob received`) + if (imageArrayBuffer.byteLength === 0) { + logger.error(`[${requestId}] Empty image received`) return new NextResponse('Empty image received', { status: 404 }) } - return new NextResponse(imageBlob, { + return new NextResponse(imageArrayBuffer, { headers: { 'Content-Type': contentType, 'Access-Control-Allow-Origin': '*', diff --git a/apps/sim/app/api/tools/onedrive/download/route.ts b/apps/sim/app/api/tools/onedrive/download/route.ts index c4ebf5b29..a50338af5 100644 --- a/apps/sim/app/api/tools/onedrive/download/route.ts +++ b/apps/sim/app/api/tools/onedrive/download/route.ts @@ -10,6 +10,24 @@ import { generateRequestId } from '@/lib/core/utils/request' export const dynamic = 'force-dynamic' +/** Microsoft Graph API error response structure */ +interface GraphApiError { + error?: { + code?: string + message?: string + } +} + +/** Microsoft Graph API drive item metadata response */ +interface DriveItemMetadata { + id?: string + name?: string + folder?: Record + file?: { + mimeType?: string + } +} + const logger = createLogger('OneDriveDownloadAPI') const OneDriveDownloadSchema = z.object({ @@ -61,7 +79,7 @@ export async function POST(request: NextRequest) { ) if (!metadataResponse.ok) { - const errorDetails = await metadataResponse.json().catch(() => ({})) + const errorDetails = (await metadataResponse.json().catch(() => ({}))) as GraphApiError logger.error(`[${requestId}] Failed to get file metadata`, { status: metadataResponse.status, error: errorDetails, @@ -72,7 +90,7 @@ export async function POST(request: NextRequest) { ) } - const metadata = await metadataResponse.json() + const metadata = (await metadataResponse.json()) as DriveItemMetadata if (metadata.folder && !metadata.file) { logger.error(`[${requestId}] Attempted to download a folder`, { @@ -110,7 +128,7 @@ export async function POST(request: NextRequest) { ) if (!downloadResponse.ok) { - const downloadError = await downloadResponse.json().catch(() => ({})) + const downloadError = (await downloadResponse.json().catch(() => ({}))) as GraphApiError logger.error(`[${requestId}] Failed to download file`, { status: downloadResponse.status, error: downloadError, diff --git a/apps/sim/app/api/tools/onedrive/upload/route.ts b/apps/sim/app/api/tools/onedrive/upload/route.ts index 2dbad9ef0..691812bc7 100644 --- a/apps/sim/app/api/tools/onedrive/upload/route.ts +++ b/apps/sim/app/api/tools/onedrive/upload/route.ts @@ -5,7 +5,6 @@ import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' import { secureFetchWithPinnedIP, - validateMicrosoftGraphId, validateUrlWithDNS, } from '@/lib/core/security/input-validation.server' import { generateRequestId } from '@/lib/core/utils/request' @@ -41,6 +40,48 @@ const OneDriveUploadSchema = z.object({ conflictBehavior: z.enum(['fail', 'replace', 'rename']).optional().nullable(), }) +/** Microsoft Graph DriveItem response */ +interface OneDriveFileData { + id: string + name: string + size: number + webUrl: string + createdDateTime: string + lastModifiedDateTime: string + file?: { mimeType: string } + parentReference?: { id: string; path: string } + '@microsoft.graph.downloadUrl'?: string +} + +/** Microsoft Graph Excel range response */ +interface ExcelRangeData { + address?: string + addressLocal?: string + values?: unknown[][] +} + +/** Validates Microsoft Graph item IDs (alphanumeric with some special chars) */ +function validateMicrosoftGraphId( + id: string, + paramName: string +): { isValid: boolean; error?: string } { + // Microsoft Graph IDs are typically alphanumeric, may include hyphens and exclamation marks + const validIdPattern = /^[a-zA-Z0-9!-]+$/ + if (!validIdPattern.test(id)) { + return { + isValid: false, + error: `Invalid ${paramName}: contains invalid characters`, + } + } + if (id.length > 256) { + return { + isValid: false, + error: `Invalid ${paramName}: exceeds maximum length`, + } + } + return { isValid: true } +} + async function secureFetchGraph( url: string, options: { @@ -215,7 +256,7 @@ export async function POST(request: NextRequest) { ) } - const fileData = await uploadResponse.json() + const fileData = (await uploadResponse.json()) as OneDriveFileData let excelWriteResult: any | undefined const shouldWriteExcelContent = @@ -241,7 +282,7 @@ export async function POST(request: NextRequest) { ) if (sessionResp.ok) { - const sessionData = await sessionResp.json() + const sessionData = (await sessionResp.json()) as { id?: string } workbookSessionId = sessionData?.id } @@ -262,7 +303,7 @@ export async function POST(request: NextRequest) { 'listUrl' ) if (listResp.ok) { - const listData = await listResp.json() + const listData = (await listResp.json()) as { value?: Array<{ name?: string }> } const firstSheetName = listData?.value?.[0]?.name if (firstSheetName) { sheetName = firstSheetName @@ -348,7 +389,7 @@ export async function POST(request: NextRequest) { details: errorText, } } else { - const writeData = await excelWriteResponse.json() + const writeData = (await excelWriteResponse.json()) as ExcelRangeData const addr = writeData.address || writeData.addressLocal const v = writeData.values || [] excelWriteResult = { @@ -356,7 +397,7 @@ export async function POST(request: NextRequest) { updatedRange: addr, updatedRows: Array.isArray(v) ? v.length : undefined, updatedColumns: Array.isArray(v) && v[0] ? v[0].length : undefined, - updatedCells: Array.isArray(v) && v[0] ? v.length * (v[0] as any[]).length : undefined, + updatedCells: Array.isArray(v) && v[0] ? v.length * v[0].length : undefined, } } diff --git a/apps/sim/app/api/tools/pipedrive/get-files/route.ts b/apps/sim/app/api/tools/pipedrive/get-files/route.ts index b2332454c..93111c94b 100644 --- a/apps/sim/app/api/tools/pipedrive/get-files/route.ts +++ b/apps/sim/app/api/tools/pipedrive/get-files/route.ts @@ -13,6 +13,18 @@ export const dynamic = 'force-dynamic' const logger = createLogger('PipedriveGetFilesAPI') +interface PipedriveFile { + id?: number + name?: string + url?: string +} + +interface PipedriveApiResponse { + success: boolean + data?: PipedriveFile[] + error?: string +} + const PipedriveGetFilesSchema = z.object({ accessToken: z.string().min(1, 'Access token is required'), deal_id: z.string().optional().nullable(), @@ -70,7 +82,7 @@ export async function POST(request: NextRequest) { }, }) - const data = await response.json() + const data = (await response.json()) as PipedriveApiResponse if (!data.success) { logger.error(`[${requestId}] Pipedrive API request failed`, { data }) diff --git a/apps/sim/app/api/tools/textract/parse/route.ts b/apps/sim/app/api/tools/textract/parse/route.ts index eb40ff2f2..ad19aeb95 100644 --- a/apps/sim/app/api/tools/textract/parse/route.ts +++ b/apps/sim/app/api/tools/textract/parse/route.ts @@ -3,10 +3,9 @@ import { createLogger } from '@sim/logger' import { type NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { checkInternalAuth } from '@/lib/auth/hybrid' +import { validateAwsRegion, validateS3BucketName } from '@/lib/core/security/input-validation' import { secureFetchWithPinnedIP, - validateAwsRegion, - validateS3BucketName, validateUrlWithDNS, } from '@/lib/core/security/input-validation.server' import { generateRequestId } from '@/lib/core/utils/request' diff --git a/apps/sim/app/api/tools/twilio/get-recording/route.ts b/apps/sim/app/api/tools/twilio/get-recording/route.ts index 5909b1e64..b5562307e 100644 --- a/apps/sim/app/api/tools/twilio/get-recording/route.ts +++ b/apps/sim/app/api/tools/twilio/get-recording/route.ts @@ -13,6 +13,36 @@ export const dynamic = 'force-dynamic' const logger = createLogger('TwilioGetRecordingAPI') +interface TwilioRecordingResponse { + sid?: string + call_sid?: string + duration?: string + status?: string + channels?: number + source?: string + price?: string + price_unit?: string + uri?: string + error_code?: number + message?: string + error_message?: string +} + +interface TwilioErrorResponse { + message?: string +} + +interface TwilioTranscription { + transcription_text?: string + status?: string + price?: string + price_unit?: string +} + +interface TwilioTranscriptionsResponse { + transcriptions?: TwilioTranscription[] +} + const TwilioGetRecordingSchema = z.object({ accountSid: z.string().min(1, 'Account SID is required'), authToken: z.string().min(1, 'Auth token is required'), @@ -67,7 +97,7 @@ export async function POST(request: NextRequest) { }) if (!infoResponse.ok) { - const errorData = await infoResponse.json().catch(() => ({})) + const errorData = (await infoResponse.json().catch(() => ({}))) as TwilioErrorResponse logger.error(`[${requestId}] Twilio API error`, { status: infoResponse.status, error: errorData, @@ -78,7 +108,7 @@ export async function POST(request: NextRequest) { ) } - const data = await infoResponse.json() + const data = (await infoResponse.json()) as TwilioRecordingResponse if (data.error_code) { return NextResponse.json({ @@ -126,7 +156,8 @@ export async function POST(request: NextRequest) { ) if (transcriptionResponse.ok) { - const transcriptionData = await transcriptionResponse.json() + const transcriptionData = + (await transcriptionResponse.json()) as TwilioTranscriptionsResponse if (transcriptionData.transcriptions && transcriptionData.transcriptions.length > 0) { const transcription = transcriptionData.transcriptions[0] diff --git a/apps/sim/app/api/tools/zoom/get-recordings/route.ts b/apps/sim/app/api/tools/zoom/get-recordings/route.ts index ed5d08604..2247612fd 100644 --- a/apps/sim/app/api/tools/zoom/get-recordings/route.ts +++ b/apps/sim/app/api/tools/zoom/get-recordings/route.ts @@ -13,6 +13,40 @@ export const dynamic = 'force-dynamic' const logger = createLogger('ZoomGetRecordingsAPI') +interface ZoomRecordingFile { + id?: string + meeting_id?: string + recording_start?: string + recording_end?: string + file_type?: string + file_extension?: string + file_size?: number + play_url?: string + download_url?: string + status?: string + recording_type?: string +} + +interface ZoomRecordingsResponse { + uuid?: string + id?: string | number + account_id?: string + host_id?: string + topic?: string + type?: number + start_time?: string + duration?: number + total_size?: number + recording_count?: number + share_url?: string + recording_files?: ZoomRecordingFile[] +} + +interface ZoomErrorResponse { + message?: string + code?: number +} + const ZoomGetRecordingsSchema = z.object({ accessToken: z.string().min(1, 'Access token is required'), meetingId: z.string().min(1, 'Meeting ID is required'), @@ -72,7 +106,7 @@ export async function POST(request: NextRequest) { }) if (!response.ok) { - const errorData = await response.json().catch(() => ({})) + const errorData = (await response.json().catch(() => ({}))) as ZoomErrorResponse logger.error(`[${requestId}] Zoom API error`, { status: response.status, error: errorData, @@ -83,7 +117,7 @@ export async function POST(request: NextRequest) { ) } - const data = await response.json() + const data = (await response.json()) as ZoomRecordingsResponse const files: Array<{ name: string mimeType: string @@ -152,7 +186,7 @@ export async function POST(request: NextRequest) { total_size: data.total_size, recording_count: data.recording_count, share_url: data.share_url, - recording_files: (data.recording_files || []).map((file: any) => ({ + recording_files: (data.recording_files || []).map((file: ZoomRecordingFile) => ({ id: file.id, meeting_id: file.meeting_id, recording_start: file.recording_start, diff --git a/apps/sim/blocks/blocks/discord.ts b/apps/sim/blocks/blocks/discord.ts index 998570b06..94c27d448 100644 --- a/apps/sim/blocks/blocks/discord.ts +++ b/apps/sim/blocks/blocks/discord.ts @@ -779,7 +779,7 @@ export const DiscordBlock: BlockConfig = { reason: { type: 'string', description: 'Reason for moderation action' }, archived: { type: 'string', description: 'Archive status (true/false)' }, attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' }, - files: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + files: { type: 'array', description: 'Files to attach (UserFile array)' }, limit: { type: 'number', description: 'Message limit' }, autoArchiveDuration: { type: 'number', description: 'Thread auto-archive duration in minutes' }, channelType: { type: 'number', description: 'Discord channel type (0=text, 2=voice, etc.)' }, diff --git a/apps/sim/blocks/blocks/google_slides.ts b/apps/sim/blocks/blocks/google_slides.ts index 4360bc4ff..42bd78961 100644 --- a/apps/sim/blocks/blocks/google_slides.ts +++ b/apps/sim/blocks/blocks/google_slides.ts @@ -924,10 +924,10 @@ const googleSlidesV2SubBlocks = (GoogleSlidesBlock.subBlocks || []).flatMap((sub { id: 'imageFileReference', title: 'Image', - type: 'short-input', + type: 'short-input' as const, canonicalParamId: 'imageFile', placeholder: 'Reference image from previous blocks', - mode: 'advanced', + mode: 'advanced' as const, required: true, condition: { field: 'operation', value: 'add_image' }, }, @@ -950,9 +950,9 @@ export const GoogleSlidesV2Block: BlockConfig = { hideFromToolbar: false, subBlocks: googleSlidesV2SubBlocks, tools: { - ...GoogleSlidesBlock.tools, + access: GoogleSlidesBlock.tools!.access, config: { - ...GoogleSlidesBlock.tools?.config, + tool: GoogleSlidesBlock.tools!.config!.tool, params: (params) => { const baseParams = GoogleSlidesBlock.tools?.config?.params if (!baseParams) { diff --git a/apps/sim/blocks/blocks/jira.ts b/apps/sim/blocks/blocks/jira.ts index 16f7b9ddf..c2e64ce1e 100644 --- a/apps/sim/blocks/blocks/jira.ts +++ b/apps/sim/blocks/blocks/jira.ts @@ -1025,7 +1025,7 @@ Return ONLY the comment text - no explanations.`, commentId: { type: 'string', description: 'Comment ID for update/delete operations' }, // Attachment operation inputs attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' }, - files: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + files: { type: 'array', description: 'Files to attach (UserFile array)' }, attachmentId: { type: 'string', description: 'Attachment ID for delete operation' }, // Worklog operation inputs timeSpentSeconds: { diff --git a/apps/sim/blocks/blocks/outlook.ts b/apps/sim/blocks/blocks/outlook.ts index e35f425f5..cfbe25304 100644 --- a/apps/sim/blocks/blocks/outlook.ts +++ b/apps/sim/blocks/blocks/outlook.ts @@ -392,7 +392,7 @@ export const OutlookBlock: BlockConfig = { body: { type: 'string', description: 'Email content' }, contentType: { type: 'string', description: 'Content type (Text or HTML)' }, attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' }, - attachments: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + attachments: { type: 'array', description: 'Files to attach (UserFile array)' }, // Forward operation inputs messageId: { type: 'string', description: 'Message ID to forward' }, comment: { type: 'string', description: 'Optional comment for forwarding' }, diff --git a/apps/sim/blocks/blocks/sendgrid.ts b/apps/sim/blocks/blocks/sendgrid.ts index d50beb707..422f9b57f 100644 --- a/apps/sim/blocks/blocks/sendgrid.ts +++ b/apps/sim/blocks/blocks/sendgrid.ts @@ -600,7 +600,7 @@ Return ONLY the HTML content.`, mailTemplateId: { type: 'string', description: 'Template ID for sending mail' }, dynamicTemplateData: { type: 'json', description: 'Dynamic template data' }, attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' }, - attachments: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + attachments: { type: 'array', description: 'Files to attach (UserFile array)' }, // Contact inputs email: { type: 'string', description: 'Contact email' }, firstName: { type: 'string', description: 'Contact first name' }, diff --git a/apps/sim/blocks/blocks/sftp.ts b/apps/sim/blocks/blocks/sftp.ts index c738e4592..3621ee5b4 100644 --- a/apps/sim/blocks/blocks/sftp.ts +++ b/apps/sim/blocks/blocks/sftp.ts @@ -279,7 +279,7 @@ export const SftpBlock: BlockConfig = { privateKey: { type: 'string', description: 'Private key for authentication' }, passphrase: { type: 'string', description: 'Passphrase for encrypted key' }, remotePath: { type: 'string', description: 'Remote path on the SFTP server' }, - files: { type: 'file[]', description: 'Files to upload (UserFile array)' }, + files: { type: 'array', description: 'Files to upload (UserFile array)' }, fileContent: { type: 'string', description: 'Direct content to upload' }, fileName: { type: 'string', description: 'File name for direct content' }, overwrite: { type: 'boolean', description: 'Overwrite existing files' }, diff --git a/apps/sim/blocks/blocks/smtp.ts b/apps/sim/blocks/blocks/smtp.ts index 3f22ae04c..c292281b6 100644 --- a/apps/sim/blocks/blocks/smtp.ts +++ b/apps/sim/blocks/blocks/smtp.ts @@ -196,7 +196,7 @@ export const SmtpBlock: BlockConfig = { cc: { type: 'string', description: 'CC recipients (comma-separated)' }, bcc: { type: 'string', description: 'BCC recipients (comma-separated)' }, replyTo: { type: 'string', description: 'Reply-to email address' }, - attachments: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + attachments: { type: 'array', description: 'Files to attach (UserFile array)' }, }, outputs: { diff --git a/apps/sim/blocks/blocks/telegram.ts b/apps/sim/blocks/blocks/telegram.ts index 40f94c484..65b18677a 100644 --- a/apps/sim/blocks/blocks/telegram.ts +++ b/apps/sim/blocks/blocks/telegram.ts @@ -351,7 +351,7 @@ export const TelegramBlock: BlockConfig = { type: 'json', description: 'Files to attach (UI upload)', }, - files: { type: 'file[]', description: 'Files to attach (UserFile array)' }, + files: { type: 'array', description: 'Files to attach (UserFile array)' }, caption: { type: 'string', description: 'Caption for media' }, messageId: { type: 'string', description: 'Message ID to delete' }, },