Skip to content

Commit 0db8777

Browse files
committed
fix(mistral): restore mistral configs for v2 version
1 parent 8d846c5 commit 0db8777

File tree

5 files changed

+222
-73
lines changed

5 files changed

+222
-73
lines changed

apps/sim/blocks/blocks/mistral_parse.ts

Lines changed: 139 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,16 @@ export const MistralParseBlock: BlockConfig<MistralParserOutput> = {
143143
},
144144
}
145145

146+
/**
147+
* V2 Block - Restored from main branch for backwards compatibility
148+
* Hidden from toolbar, uses filePath subblock ID for advanced mode
149+
*/
146150
export const MistralParseV2Block: BlockConfig<MistralParserOutput> = {
147151
...MistralParseBlock,
148152
type: 'mistral_parse_v2',
149153
name: 'Mistral Parser',
150154
description: 'Extract text from PDF documents',
151-
hideFromToolbar: false,
155+
hideFromToolbar: true,
152156
subBlocks: [
153157
{
154158
id: 'fileUpload',
@@ -159,16 +163,14 @@ export const MistralParseV2Block: BlockConfig<MistralParserOutput> = {
159163
placeholder: 'Upload a PDF document',
160164
mode: 'basic',
161165
maxSize: 50,
162-
required: true,
163166
},
164167
{
165-
id: 'fileReference',
166-
title: 'File Reference',
168+
id: 'filePath',
169+
title: 'PDF Document',
167170
type: 'short-input' as SubBlockType,
168171
canonicalParamId: 'document',
169-
placeholder: 'File reference from previous block',
172+
placeholder: 'Document URL',
170173
mode: 'advanced',
171-
required: true,
172174
},
173175
{
174176
id: 'resultType',
@@ -213,6 +215,137 @@ export const MistralParseV2Block: BlockConfig<MistralParserOutput> = {
213215
resultType: params.resultType || 'markdown',
214216
}
215217

218+
// Original V2 pattern: fileUpload (basic) or filePath (advanced) or document (wired)
219+
const documentInput = params.fileUpload || params.filePath || params.document
220+
if (!documentInput) {
221+
throw new Error('PDF document is required')
222+
}
223+
// Smart handling: object → fileUpload param, string → filePath param
224+
if (typeof documentInput === 'object') {
225+
parameters.fileUpload = documentInput
226+
} else if (typeof documentInput === 'string') {
227+
parameters.filePath = documentInput.trim()
228+
}
229+
230+
let pagesArray: number[] | undefined
231+
if (params.pages && params.pages.trim() !== '') {
232+
try {
233+
pagesArray = params.pages
234+
.split(',')
235+
.map((p: string) => p.trim())
236+
.filter((p: string) => p.length > 0)
237+
.map((p: string) => {
238+
const num = Number.parseInt(p, 10)
239+
if (Number.isNaN(num) || num < 0) {
240+
throw new Error(`Invalid page number: ${p}`)
241+
}
242+
return num
243+
})
244+
245+
if (pagesArray && pagesArray.length === 0) {
246+
pagesArray = undefined
247+
}
248+
} catch (error: unknown) {
249+
const errorMessage = error instanceof Error ? error.message : String(error)
250+
throw new Error(`Page number format error: ${errorMessage}`)
251+
}
252+
}
253+
254+
if (pagesArray && pagesArray.length > 0) {
255+
parameters.pages = pagesArray
256+
}
257+
258+
return parameters
259+
},
260+
},
261+
},
262+
inputs: {
263+
document: { type: 'json', description: 'Document input (file upload or URL reference)' },
264+
filePath: { type: 'string', description: 'PDF document URL (advanced mode)' },
265+
fileUpload: { type: 'json', description: 'Uploaded PDF file (basic mode)' },
266+
apiKey: { type: 'string', description: 'Mistral API key' },
267+
resultType: { type: 'string', description: 'Output format type' },
268+
pages: { type: 'string', description: 'Page selection' },
269+
},
270+
outputs: {
271+
pages: { type: 'array', description: 'Array of page objects from Mistral OCR' },
272+
model: { type: 'string', description: 'Mistral OCR model identifier' },
273+
usage_info: { type: 'json', description: 'Usage statistics from the API' },
274+
document_annotation: { type: 'string', description: 'Structured annotation data' },
275+
},
276+
}
277+
278+
/**
279+
* V3 Block - New file handling pattern with UserFile normalization
280+
* Uses fileReference subblock ID with canonicalParamId for proper file handling
281+
*/
282+
export const MistralParseV3Block: BlockConfig<MistralParserOutput> = {
283+
...MistralParseBlock,
284+
type: 'mistral_parse_v3',
285+
name: 'Mistral Parser',
286+
description: 'Extract text from PDF documents',
287+
hideFromToolbar: false,
288+
subBlocks: [
289+
{
290+
id: 'fileUpload',
291+
title: 'PDF Document',
292+
type: 'file-upload' as SubBlockType,
293+
canonicalParamId: 'document',
294+
acceptedTypes: 'application/pdf',
295+
placeholder: 'Upload a PDF document',
296+
mode: 'basic',
297+
maxSize: 50,
298+
required: true,
299+
},
300+
{
301+
id: 'fileReference',
302+
title: 'File Reference',
303+
type: 'short-input' as SubBlockType,
304+
canonicalParamId: 'document',
305+
placeholder: 'File reference from previous block',
306+
mode: 'advanced',
307+
required: true,
308+
},
309+
{
310+
id: 'resultType',
311+
title: 'Output Format',
312+
type: 'dropdown',
313+
options: [
314+
{ id: 'markdown', label: 'Markdown' },
315+
{ id: 'text', label: 'Plain Text' },
316+
{ id: 'json', label: 'JSON' },
317+
],
318+
},
319+
{
320+
id: 'pages',
321+
title: 'Specific Pages',
322+
type: 'short-input',
323+
placeholder: 'e.g. 0,1,2 (leave empty for all pages)',
324+
},
325+
{
326+
id: 'apiKey',
327+
title: 'API Key',
328+
type: 'short-input' as SubBlockType,
329+
placeholder: 'Enter your Mistral API key',
330+
password: true,
331+
required: true,
332+
},
333+
],
334+
tools: {
335+
access: ['mistral_parser_v3'],
336+
config: {
337+
tool: () => 'mistral_parser_v3',
338+
params: (params) => {
339+
if (!params || !params.apiKey || params.apiKey.trim() === '') {
340+
throw new Error('Mistral API key is required')
341+
}
342+
343+
const parameters: Record<string, unknown> = {
344+
apiKey: params.apiKey.trim(),
345+
resultType: params.resultType || 'markdown',
346+
}
347+
348+
// V3 pattern: normalize file inputs from basic/advanced modes
216349
const documentInput = normalizeFileInput(
217350
params.fileUpload || params.fileReference || params.document,
218351
{ single: true }

apps/sim/blocks/registry.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ import { MemoryBlock } from '@/blocks/blocks/memory'
7979
import { MicrosoftExcelBlock, MicrosoftExcelV2Block } from '@/blocks/blocks/microsoft_excel'
8080
import { MicrosoftPlannerBlock } from '@/blocks/blocks/microsoft_planner'
8181
import { MicrosoftTeamsBlock } from '@/blocks/blocks/microsoft_teams'
82-
import { MistralParseBlock, MistralParseV2Block } from '@/blocks/blocks/mistral_parse'
82+
import {
83+
MistralParseBlock,
84+
MistralParseV2Block,
85+
MistralParseV3Block,
86+
} from '@/blocks/blocks/mistral_parse'
8387
import { MongoDBBlock } from '@/blocks/blocks/mongodb'
8488
import { MySQLBlock } from '@/blocks/blocks/mysql'
8589
import { Neo4jBlock } from '@/blocks/blocks/neo4j'
@@ -255,6 +259,7 @@ export const registry: Record<string, BlockConfig> = {
255259
microsoft_teams: MicrosoftTeamsBlock,
256260
mistral_parse: MistralParseBlock,
257261
mistral_parse_v2: MistralParseV2Block,
262+
mistral_parse_v3: MistralParseV3Block,
258263
mongodb: MongoDBBlock,
259264
mysql: MySQLBlock,
260265
neo4j: Neo4jBlock,

apps/sim/tools/mistral/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { mistralParserTool, mistralParserV2Tool } from '@/tools/mistral/parser'
1+
import { mistralParserTool, mistralParserV2Tool, mistralParserV3Tool } from '@/tools/mistral/parser'
22

3-
export { mistralParserTool, mistralParserV2Tool }
3+
export { mistralParserTool, mistralParserV2Tool, mistralParserV3Tool }

apps/sim/tools/mistral/parser.ts

Lines changed: 73 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -349,74 +349,14 @@ export const mistralParserTool: ToolConfig<MistralParserInput, MistralParserOutp
349349
},
350350
}
351351

352-
const mistralParserV2Params = {
353-
file: {
354-
type: 'file',
355-
required: true,
356-
visibility: 'hidden',
357-
description: 'File data from a previous block',
358-
},
359-
resultType: mistralParserTool.params.resultType,
360-
includeImageBase64: mistralParserTool.params.includeImageBase64,
361-
pages: mistralParserTool.params.pages,
362-
imageLimit: mistralParserTool.params.imageLimit,
363-
imageMinSize: mistralParserTool.params.imageMinSize,
364-
apiKey: mistralParserTool.params.apiKey,
365-
} satisfies ToolConfig['params']
366-
367-
export const mistralParserV2Tool: ToolConfig<MistralParserV2Input, MistralParserV2Output> = {
352+
export const mistralParserV2Tool: ToolConfig<MistralParserInput, MistralParserV2Output> = {
368353
id: 'mistral_parser_v2',
369354
name: 'Mistral PDF Parser',
370355
description: 'Parse PDF documents using Mistral OCR API',
371356
version: '2.0.0',
372357

373-
params: mistralParserV2Params,
374-
request: {
375-
url: '/api/tools/mistral/parse',
376-
method: 'POST',
377-
headers: (params) => {
378-
return {
379-
'Content-Type': 'application/json',
380-
Accept: 'application/json',
381-
Authorization: `Bearer ${params.apiKey}`,
382-
}
383-
},
384-
body: (params) => {
385-
if (!params || typeof params !== 'object') {
386-
throw new Error('Invalid parameters: Parameters must be provided as an object')
387-
}
388-
if (!params.apiKey || typeof params.apiKey !== 'string' || params.apiKey.trim() === '') {
389-
throw new Error('Missing or invalid API key: A valid Mistral API key is required')
390-
}
391-
392-
const file = params.file
393-
if (!file || typeof file !== 'object') {
394-
throw new Error('File input is required')
395-
}
396-
397-
const requestBody: Record<string, unknown> = {
398-
apiKey: params.apiKey,
399-
resultType: params.resultType || 'markdown',
400-
}
401-
402-
requestBody.file = file
403-
404-
if (params.pages) {
405-
requestBody.pages = params.pages
406-
}
407-
if (params.includeImageBase64 !== undefined) {
408-
requestBody.includeImageBase64 = params.includeImageBase64
409-
}
410-
if (params.imageLimit !== undefined) {
411-
requestBody.imageLimit = params.imageLimit
412-
}
413-
if (params.imageMinSize !== undefined) {
414-
requestBody.imageMinSize = params.imageMinSize
415-
}
416-
417-
return requestBody
418-
},
419-
},
358+
params: mistralParserTool.params,
359+
request: mistralParserTool.request,
420360

421361
transformResponse: async (response: Response) => {
422362
let ocrResult
@@ -543,3 +483,73 @@ export const mistralParserV2Tool: ToolConfig<MistralParserV2Input, MistralParser
543483
},
544484
},
545485
}
486+
487+
/**
488+
* V3 tool - Updated for new file handling pattern with UserFile normalization
489+
* Used by MistralParseV3Block which uses fileUpload (basic) and fileReference (advanced) subblocks
490+
*/
491+
export const mistralParserV3Tool: ToolConfig<MistralParserV2Input, MistralParserV2Output> = {
492+
...mistralParserV2Tool,
493+
id: 'mistral_parser_v3',
494+
version: '3.0.0',
495+
params: {
496+
file: {
497+
type: 'file',
498+
required: true,
499+
visibility: 'hidden',
500+
description: 'Normalized UserFile from file upload or file reference',
501+
},
502+
resultType: mistralParserTool.params.resultType,
503+
includeImageBase64: mistralParserTool.params.includeImageBase64,
504+
pages: mistralParserTool.params.pages,
505+
imageLimit: mistralParserTool.params.imageLimit,
506+
imageMinSize: mistralParserTool.params.imageMinSize,
507+
apiKey: mistralParserTool.params.apiKey,
508+
},
509+
request: {
510+
url: '/api/tools/mistral/parse',
511+
method: 'POST',
512+
headers: (params) => {
513+
return {
514+
'Content-Type': 'application/json',
515+
Accept: 'application/json',
516+
Authorization: `Bearer ${params.apiKey}`,
517+
}
518+
},
519+
body: (params) => {
520+
if (!params || typeof params !== 'object') {
521+
throw new Error('Invalid parameters: Parameters must be provided as an object')
522+
}
523+
if (!params.apiKey || typeof params.apiKey !== 'string' || params.apiKey.trim() === '') {
524+
throw new Error('Missing or invalid API key: A valid Mistral API key is required')
525+
}
526+
527+
// V3 expects normalized UserFile object via `file` param
528+
const file = params.file
529+
if (!file || typeof file !== 'object') {
530+
throw new Error('File input is required: provide a file upload or file reference')
531+
}
532+
533+
const requestBody: Record<string, unknown> = {
534+
apiKey: params.apiKey,
535+
resultType: params.resultType || 'markdown',
536+
file: file,
537+
}
538+
539+
if (params.pages) {
540+
requestBody.pages = params.pages
541+
}
542+
if (params.includeImageBase64 !== undefined) {
543+
requestBody.includeImageBase64 = params.includeImageBase64
544+
}
545+
if (params.imageLimit !== undefined) {
546+
requestBody.imageLimit = params.imageLimit
547+
}
548+
if (params.imageMinSize !== undefined) {
549+
requestBody.imageMinSize = params.imageMinSize
550+
}
551+
552+
return requestBody
553+
},
554+
},
555+
}

apps/sim/tools/registry.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ import {
10931093
microsoftTeamsWriteChannelTool,
10941094
microsoftTeamsWriteChatTool,
10951095
} from '@/tools/microsoft_teams'
1096-
import { mistralParserTool, mistralParserV2Tool } from '@/tools/mistral'
1096+
import { mistralParserTool, mistralParserV2Tool, mistralParserV3Tool } from '@/tools/mistral'
10971097
import {
10981098
mongodbDeleteTool,
10991099
mongodbExecuteTool,
@@ -2684,6 +2684,7 @@ export const tools: Record<string, ToolConfig> = {
26842684
apollo_email_accounts: apolloEmailAccountsTool,
26852685
mistral_parser: mistralParserTool,
26862686
mistral_parser_v2: mistralParserV2Tool,
2687+
mistral_parser_v3: mistralParserV3Tool,
26872688
reducto_parser: reductoParserTool,
26882689
reducto_parser_v2: reductoParserV2Tool,
26892690
textract_parser: textractParserTool,

0 commit comments

Comments
 (0)