mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-22 05:18:08 -05:00
updated the rest of the old file patterns, updated mistral outputs for v2
This commit is contained in:
@@ -144,7 +144,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
calendly: CalendlyIcon,
|
||||
circleback: CirclebackIcon,
|
||||
clay: ClayIcon,
|
||||
confluence: ConfluenceIcon,
|
||||
confluence_v2: ConfluenceIcon,
|
||||
cursor_v2: CursorIcon,
|
||||
datadog: DatadogIcon,
|
||||
discord: DiscordIcon,
|
||||
@@ -246,7 +246,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
||||
twilio_sms: TwilioIcon,
|
||||
twilio_voice: TwilioIcon,
|
||||
typeform: TypeformIcon,
|
||||
video_generator: VideoIcon,
|
||||
video_generator_v2: VideoIcon,
|
||||
vision: EyeIcon,
|
||||
wealthbox: WealthboxIcon,
|
||||
webflow: WebflowIcon,
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Interact with Confluence
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="confluence"
|
||||
type="confluence_v2"
|
||||
color="#E0E0E0"
|
||||
/>
|
||||
|
||||
|
||||
@@ -54,8 +54,37 @@ Parse PDF documents using Mistral OCR API
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Whether the PDF was parsed successfully |
|
||||
| `content` | string | Extracted content in the requested format \(markdown, text, or JSON\) |
|
||||
| `metadata` | object | Processing metadata including jobId, fileType, pageCount, and usage info |
|
||||
| `pages` | array | Array of page objects from Mistral OCR |
|
||||
| ↳ `index` | number | Page index \(zero-based\) |
|
||||
| ↳ `markdown` | string | Extracted markdown content |
|
||||
| ↳ `images` | array | Images extracted from this page with bounding boxes |
|
||||
| ↳ `id` | string | Image identifier \(e.g., img-0.jpeg\) |
|
||||
| ↳ `top_left_x` | number | Top-left X coordinate in pixels |
|
||||
| ↳ `top_left_y` | number | Top-left Y coordinate in pixels |
|
||||
| ↳ `bottom_right_x` | number | Bottom-right X coordinate in pixels |
|
||||
| ↳ `bottom_right_y` | number | Bottom-right Y coordinate in pixels |
|
||||
| ↳ `image_base64` | string | Base64-encoded image data \(when include_image_base64=true\) |
|
||||
| ↳ `id` | string | Image identifier \(e.g., img-0.jpeg\) |
|
||||
| ↳ `top_left_x` | number | Top-left X coordinate in pixels |
|
||||
| ↳ `top_left_y` | number | Top-left Y coordinate in pixels |
|
||||
| ↳ `bottom_right_x` | number | Bottom-right X coordinate in pixels |
|
||||
| ↳ `bottom_right_y` | number | Bottom-right Y coordinate in pixels |
|
||||
| ↳ `image_base64` | string | Base64-encoded image data \(when include_image_base64=true\) |
|
||||
| ↳ `dimensions` | object | Page dimensions |
|
||||
| ↳ `dpi` | number | Dots per inch |
|
||||
| ↳ `height` | number | Page height in pixels |
|
||||
| ↳ `width` | number | Page width in pixels |
|
||||
| ↳ `dpi` | number | Dots per inch |
|
||||
| ↳ `height` | number | Page height in pixels |
|
||||
| ↳ `width` | number | Page width in pixels |
|
||||
| ↳ `tables` | array | Extracted tables as HTML/markdown \(when table_format is set\). Referenced via placeholders like \[tbl-0.html\] |
|
||||
| ↳ `hyperlinks` | array | Array of URL strings detected in the page \(e.g., \[ |
|
||||
| ↳ `header` | string | Page header content \(when extract_header=true\) |
|
||||
| ↳ `footer` | string | Page footer content \(when extract_footer=true\) |
|
||||
| `model` | string | Mistral OCR model identifier \(e.g., mistral-ocr-latest\) |
|
||||
| `usage_info` | object | Usage and processing statistics |
|
||||
| ↳ `pages_processed` | number | Total number of pages processed |
|
||||
| ↳ `doc_size_bytes` | number | Document file size in bytes |
|
||||
| `document_annotation` | string | Structured annotation data as JSON string \(when applicable\) |
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Generate videos from text using AI
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
|
||||
<BlockInfoCard
|
||||
type="video_generator"
|
||||
type="video_generator_v2"
|
||||
color="#181C1E"
|
||||
/>
|
||||
|
||||
|
||||
@@ -85,14 +85,47 @@ export function FileUpload({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a file's MIME type matches the accepted types
|
||||
* Supports exact matches, wildcard patterns (e.g., 'image/*'), and '*' for all types
|
||||
*/
|
||||
const isFileTypeAccepted = (fileType: string, accepted: string): boolean => {
|
||||
if (accepted === '*') return true
|
||||
|
||||
const acceptedList = accepted.split(',').map((t) => t.trim().toLowerCase())
|
||||
const normalizedFileType = fileType.toLowerCase()
|
||||
|
||||
return acceptedList.some((acceptedType) => {
|
||||
if (acceptedType === normalizedFileType) return true
|
||||
|
||||
if (acceptedType.endsWith('/*')) {
|
||||
const typePrefix = acceptedType.slice(0, -1) // 'image/' from 'image/*'
|
||||
return normalizedFileType.startsWith(typePrefix)
|
||||
}
|
||||
|
||||
if (acceptedType.startsWith('.')) {
|
||||
const extension = acceptedType.slice(1) // 'pdf' from '.pdf'
|
||||
return (
|
||||
normalizedFileType.endsWith(`/${extension}`) ||
|
||||
normalizedFileType.includes(`${extension}`)
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
const availableWorkspaceFiles = workspaceFiles.filter((workspaceFile) => {
|
||||
const existingFiles = Array.isArray(value) ? value : value ? [value] : []
|
||||
return !existingFiles.some(
|
||||
|
||||
const isAlreadySelected = existingFiles.some(
|
||||
(existing) =>
|
||||
existing.name === workspaceFile.name ||
|
||||
existing.path?.includes(workspaceFile.key) ||
|
||||
existing.key === workspaceFile.key
|
||||
)
|
||||
|
||||
return !isAlreadySelected
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
@@ -421,23 +454,23 @@ export function FileUpload({
|
||||
return (
|
||||
<div
|
||||
key={fileKey}
|
||||
className='flex items-center justify-between rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[8px] py-[6px] hover:border-[var(--surface-7)] hover:bg-[var(--surface-5)] dark:bg-[var(--surface-5)] dark:hover:bg-[var(--border-1)]'
|
||||
className='relative rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[8px] py-[6px] hover:border-[var(--surface-7)] hover:bg-[var(--surface-5)] dark:bg-[var(--surface-5)] dark:hover:bg-[var(--border-1)]'
|
||||
>
|
||||
<div className='flex-1 truncate pr-2 text-sm' title={file.name}>
|
||||
<div className='truncate pr-[24px] text-sm' title={file.name}>
|
||||
<span className='text-[var(--text-primary)]'>{truncateMiddle(file.name)}</span>
|
||||
<span className='ml-2 text-[var(--text-muted)]'>({formatFileSize(file.size)})</span>
|
||||
</div>
|
||||
<Button
|
||||
type='button'
|
||||
variant='ghost'
|
||||
className='h-5 w-5 shrink-0 p-0'
|
||||
className='-translate-y-1/2 absolute top-1/2 right-[4px] h-6 w-6 p-0'
|
||||
onClick={(e) => handleRemoveFile(file, e)}
|
||||
disabled={isDeleting}
|
||||
>
|
||||
{isDeleting ? (
|
||||
<div className='h-3.5 w-3.5 animate-spin rounded-full border-[1.5px] border-current border-t-transparent' />
|
||||
<div className='h-4 w-4 animate-spin rounded-full border-[1.5px] border-current border-t-transparent' />
|
||||
) : (
|
||||
<X className='h-3.5 w-3.5' />
|
||||
<X className='h-4 w-4 opacity-50' />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -468,19 +501,30 @@ export function FileUpload({
|
||||
const comboboxOptions = useMemo(
|
||||
() => [
|
||||
{ label: 'Upload New File', value: '__upload_new__' },
|
||||
...availableWorkspaceFiles.map((file) => ({
|
||||
label: file.name,
|
||||
value: file.id,
|
||||
})),
|
||||
...availableWorkspaceFiles.map((file) => {
|
||||
const isAccepted =
|
||||
!acceptedTypes || acceptedTypes === '*' || isFileTypeAccepted(file.type, acceptedTypes)
|
||||
return {
|
||||
label: file.name,
|
||||
value: file.id,
|
||||
disabled: !isAccepted,
|
||||
}
|
||||
}),
|
||||
],
|
||||
[availableWorkspaceFiles]
|
||||
[availableWorkspaceFiles, acceptedTypes]
|
||||
)
|
||||
|
||||
const handleComboboxChange = (value: string) => {
|
||||
setInputValue(value)
|
||||
|
||||
const isValidOption =
|
||||
value === '__upload_new__' || availableWorkspaceFiles.some((file) => file.id === value)
|
||||
const selectedFile = availableWorkspaceFiles.find((file) => file.id === value)
|
||||
const isAcceptedType =
|
||||
selectedFile &&
|
||||
(!acceptedTypes ||
|
||||
acceptedTypes === '*' ||
|
||||
isFileTypeAccepted(selectedFile.type, acceptedTypes))
|
||||
|
||||
const isValidOption = value === '__upload_new__' || isAcceptedType
|
||||
|
||||
if (!isValidOption) {
|
||||
return
|
||||
|
||||
@@ -241,11 +241,9 @@ const getOutputTypeForPath = (
|
||||
const blockState = useWorkflowStore.getState().blocks[blockId]
|
||||
const subBlocks = mergedSubBlocksOverride ?? (blockState?.subBlocks || {})
|
||||
return getBlockOutputType(block.type, outputPath, subBlocks)
|
||||
} else {
|
||||
} else if (blockConfig) {
|
||||
const operationValue = getSubBlockValue(blockId, 'operation')
|
||||
if (blockConfig && operationValue) {
|
||||
return getToolOutputType(blockConfig, operationValue, outputPath)
|
||||
}
|
||||
return getToolOutputType(blockConfig, operationValue || '', outputPath)
|
||||
}
|
||||
return 'any'
|
||||
}
|
||||
@@ -1213,9 +1211,11 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
} else {
|
||||
const operationValue =
|
||||
mergedSubBlocks?.operation?.value ?? getSubBlockValue(activeSourceBlockId, 'operation')
|
||||
const toolOutputPaths = operationValue
|
||||
? getToolOutputPaths(blockConfig, operationValue, mergedSubBlocks)
|
||||
: []
|
||||
const toolOutputPaths = getToolOutputPaths(
|
||||
blockConfig,
|
||||
operationValue || '',
|
||||
mergedSubBlocks
|
||||
)
|
||||
|
||||
if (toolOutputPaths.length > 0) {
|
||||
blockTags = toolOutputPaths.map((path) => `${normalizedBlockName}.${path}`)
|
||||
@@ -1545,9 +1545,11 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
|
||||
} else {
|
||||
const operationValue =
|
||||
mergedSubBlocks?.operation?.value ?? getSubBlockValue(accessibleBlockId, 'operation')
|
||||
const toolOutputPaths = operationValue
|
||||
? getToolOutputPaths(blockConfig, operationValue, mergedSubBlocks)
|
||||
: []
|
||||
const toolOutputPaths = getToolOutputPaths(
|
||||
blockConfig,
|
||||
operationValue || '',
|
||||
mergedSubBlocks
|
||||
)
|
||||
|
||||
if (toolOutputPaths.length > 0) {
|
||||
blockTags = toolOutputPaths.map((path) => `${normalizedBlockName}.${path}`)
|
||||
|
||||
@@ -129,7 +129,6 @@ export function Editor() {
|
||||
blockSubBlockValues,
|
||||
canonicalIndex
|
||||
)
|
||||
// When user can edit, respect their toggle; otherwise show if values present
|
||||
const displayAdvancedOptions = userPermissions.canEdit
|
||||
? advancedMode
|
||||
: advancedMode || advancedValuesPresent
|
||||
|
||||
@@ -107,14 +107,26 @@ export const A2ABlock: BlockConfig<A2AResponse> = {
|
||||
condition: { field: 'operation', value: 'a2a_send_message' },
|
||||
},
|
||||
{
|
||||
id: 'files',
|
||||
id: 'fileUpload',
|
||||
title: 'Files',
|
||||
type: 'file-upload',
|
||||
canonicalParamId: 'files',
|
||||
placeholder: 'Upload files to send',
|
||||
description: 'Files to include with the message (FilePart)',
|
||||
condition: { field: 'operation', value: 'a2a_send_message' },
|
||||
mode: 'basic',
|
||||
multiple: true,
|
||||
},
|
||||
{
|
||||
id: 'fileReference',
|
||||
title: 'Files',
|
||||
type: 'short-input',
|
||||
canonicalParamId: 'files',
|
||||
placeholder: 'Reference files from previous blocks',
|
||||
description: 'Files to include with the message (FilePart)',
|
||||
condition: { field: 'operation', value: 'a2a_send_message' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'taskId',
|
||||
title: 'Task ID',
|
||||
@@ -233,6 +245,14 @@ export const A2ABlock: BlockConfig<A2AResponse> = {
|
||||
type: 'array',
|
||||
description: 'Files to include with the message',
|
||||
},
|
||||
fileUpload: {
|
||||
type: 'array',
|
||||
description: 'Uploaded files (basic mode)',
|
||||
},
|
||||
fileReference: {
|
||||
type: 'json',
|
||||
description: 'File reference from previous blocks (advanced mode)',
|
||||
},
|
||||
historyLength: {
|
||||
type: 'number',
|
||||
description: 'Number of history messages to include',
|
||||
|
||||
@@ -5,8 +5,9 @@ import type { ConfluenceResponse } from '@/tools/confluence/types'
|
||||
|
||||
export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
|
||||
type: 'confluence',
|
||||
name: 'Confluence',
|
||||
name: 'Confluence (Legacy)',
|
||||
description: 'Interact with Confluence',
|
||||
hideFromToolbar: true,
|
||||
authMode: AuthMode.OAuth,
|
||||
longDescription:
|
||||
'Integrate Confluence into the workflow. Can read, create, update, delete pages, manage comments, attachments, labels, and search content.',
|
||||
@@ -357,3 +358,342 @@ export const ConfluenceBlock: BlockConfig<ConfluenceResponse> = {
|
||||
status: { type: 'string', description: 'Space status' },
|
||||
},
|
||||
}
|
||||
|
||||
export const ConfluenceV2Block: BlockConfig<ConfluenceResponse> = {
|
||||
...ConfluenceBlock,
|
||||
type: 'confluence_v2',
|
||||
name: 'Confluence',
|
||||
hideFromToolbar: false,
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Read Page', id: 'read' },
|
||||
{ label: 'Create Page', id: 'create' },
|
||||
{ label: 'Update Page', id: 'update' },
|
||||
{ label: 'Delete Page', id: 'delete' },
|
||||
{ label: 'Search Content', id: 'search' },
|
||||
{ label: 'Create Comment', id: 'create_comment' },
|
||||
{ label: 'List Comments', id: 'list_comments' },
|
||||
{ label: 'Update Comment', id: 'update_comment' },
|
||||
{ label: 'Delete Comment', id: 'delete_comment' },
|
||||
{ label: 'Upload Attachment', id: 'upload_attachment' },
|
||||
{ label: 'List Attachments', id: 'list_attachments' },
|
||||
{ label: 'Delete Attachment', id: 'delete_attachment' },
|
||||
{ label: 'List Labels', id: 'list_labels' },
|
||||
{ label: 'Get Space', id: 'get_space' },
|
||||
{ label: 'List Spaces', id: 'list_spaces' },
|
||||
],
|
||||
value: () => 'read',
|
||||
},
|
||||
{
|
||||
id: 'domain',
|
||||
title: 'Domain',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter Confluence domain (e.g., simstudio.atlassian.net)',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'credential',
|
||||
title: 'Confluence Account',
|
||||
type: 'oauth-input',
|
||||
serviceId: 'confluence',
|
||||
requiredScopes: [
|
||||
'read:confluence-content.all',
|
||||
'read:confluence-space.summary',
|
||||
'read:space:confluence',
|
||||
'read:space-details:confluence',
|
||||
'write:confluence-content',
|
||||
'write:confluence-space',
|
||||
'write:confluence-file',
|
||||
'read:content:confluence',
|
||||
'read:page:confluence',
|
||||
'write:page:confluence',
|
||||
'read:comment:confluence',
|
||||
'write:comment:confluence',
|
||||
'delete:comment:confluence',
|
||||
'read:attachment:confluence',
|
||||
'write:attachment:confluence',
|
||||
'delete:attachment:confluence',
|
||||
'delete:page:confluence',
|
||||
'read:label:confluence',
|
||||
'write:label:confluence',
|
||||
'search:confluence',
|
||||
'read:me',
|
||||
'offline_access',
|
||||
],
|
||||
placeholder: 'Select Confluence account',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'pageId',
|
||||
title: 'Select Page',
|
||||
type: 'file-selector',
|
||||
canonicalParamId: 'pageId',
|
||||
serviceId: 'confluence',
|
||||
placeholder: 'Select Confluence page',
|
||||
dependsOn: ['credential', 'domain'],
|
||||
mode: 'basic',
|
||||
},
|
||||
{
|
||||
id: 'manualPageId',
|
||||
title: 'Page ID',
|
||||
type: 'short-input',
|
||||
canonicalParamId: 'pageId',
|
||||
placeholder: 'Enter Confluence page ID',
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'spaceId',
|
||||
title: 'Space ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter Confluence space ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: ['create', 'get_space'] },
|
||||
},
|
||||
{
|
||||
id: 'title',
|
||||
title: 'Title',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter title for the page',
|
||||
condition: { field: 'operation', value: ['create', 'update'] },
|
||||
},
|
||||
{
|
||||
id: 'content',
|
||||
title: 'Content',
|
||||
type: 'long-input',
|
||||
placeholder: 'Enter content for the page',
|
||||
condition: { field: 'operation', value: ['create', 'update'] },
|
||||
},
|
||||
{
|
||||
id: 'parentId',
|
||||
title: 'Parent Page ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter parent page ID (optional)',
|
||||
condition: { field: 'operation', value: 'create' },
|
||||
},
|
||||
{
|
||||
id: 'query',
|
||||
title: 'Search Query',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter search query',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'search' },
|
||||
},
|
||||
{
|
||||
id: 'comment',
|
||||
title: 'Comment Text',
|
||||
type: 'long-input',
|
||||
placeholder: 'Enter comment text',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: ['create_comment', 'update_comment'] },
|
||||
},
|
||||
{
|
||||
id: 'commentId',
|
||||
title: 'Comment ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter comment ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: ['update_comment', 'delete_comment'] },
|
||||
},
|
||||
{
|
||||
id: 'attachmentId',
|
||||
title: 'Attachment ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter attachment ID',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: 'delete_attachment' },
|
||||
},
|
||||
{
|
||||
id: 'attachmentFileUpload',
|
||||
title: 'File',
|
||||
type: 'file-upload',
|
||||
canonicalParamId: 'attachmentFile',
|
||||
placeholder: 'Select file to upload',
|
||||
condition: { field: 'operation', value: 'upload_attachment' },
|
||||
mode: 'basic',
|
||||
},
|
||||
{
|
||||
id: 'attachmentFileReference',
|
||||
title: 'File',
|
||||
type: 'short-input',
|
||||
canonicalParamId: 'attachmentFile',
|
||||
placeholder: 'Reference file from previous blocks',
|
||||
condition: { field: 'operation', value: 'upload_attachment' },
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'attachmentFileName',
|
||||
title: 'File Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'Optional custom file name',
|
||||
condition: { field: 'operation', value: 'upload_attachment' },
|
||||
},
|
||||
{
|
||||
id: 'attachmentComment',
|
||||
title: 'Comment',
|
||||
type: 'short-input',
|
||||
placeholder: 'Optional comment for the attachment',
|
||||
condition: { field: 'operation', value: 'upload_attachment' },
|
||||
},
|
||||
{
|
||||
id: 'labelName',
|
||||
title: 'Label Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter label name',
|
||||
required: true,
|
||||
condition: { field: 'operation', value: ['add_label', 'remove_label'] },
|
||||
},
|
||||
{
|
||||
id: 'limit',
|
||||
title: 'Limit',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter maximum number of results (default: 25)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['search', 'list_comments', 'list_attachments', 'list_spaces'],
|
||||
},
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: [
|
||||
'confluence_retrieve',
|
||||
'confluence_update',
|
||||
'confluence_create_page',
|
||||
'confluence_delete_page',
|
||||
'confluence_search',
|
||||
'confluence_create_comment',
|
||||
'confluence_list_comments',
|
||||
'confluence_update_comment',
|
||||
'confluence_delete_comment',
|
||||
'confluence_upload_attachment',
|
||||
'confluence_list_attachments',
|
||||
'confluence_delete_attachment',
|
||||
'confluence_list_labels',
|
||||
'confluence_get_space',
|
||||
'confluence_list_spaces',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'read':
|
||||
return 'confluence_retrieve'
|
||||
case 'create':
|
||||
return 'confluence_create_page'
|
||||
case 'update':
|
||||
return 'confluence_update'
|
||||
case 'delete':
|
||||
return 'confluence_delete_page'
|
||||
case 'search':
|
||||
return 'confluence_search'
|
||||
case 'create_comment':
|
||||
return 'confluence_create_comment'
|
||||
case 'list_comments':
|
||||
return 'confluence_list_comments'
|
||||
case 'update_comment':
|
||||
return 'confluence_update_comment'
|
||||
case 'delete_comment':
|
||||
return 'confluence_delete_comment'
|
||||
case 'upload_attachment':
|
||||
return 'confluence_upload_attachment'
|
||||
case 'list_attachments':
|
||||
return 'confluence_list_attachments'
|
||||
case 'delete_attachment':
|
||||
return 'confluence_delete_attachment'
|
||||
case 'list_labels':
|
||||
return 'confluence_list_labels'
|
||||
case 'get_space':
|
||||
return 'confluence_get_space'
|
||||
case 'list_spaces':
|
||||
return 'confluence_list_spaces'
|
||||
default:
|
||||
return 'confluence_retrieve'
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const {
|
||||
credential,
|
||||
pageId,
|
||||
manualPageId,
|
||||
operation,
|
||||
attachmentFileUpload,
|
||||
attachmentFileReference,
|
||||
attachmentFile,
|
||||
attachmentFileName,
|
||||
attachmentComment,
|
||||
...rest
|
||||
} = params
|
||||
|
||||
const effectivePageId = (pageId || manualPageId || '').trim()
|
||||
|
||||
const requiresPageId = [
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'create_comment',
|
||||
'list_comments',
|
||||
'list_attachments',
|
||||
'list_labels',
|
||||
'upload_attachment',
|
||||
]
|
||||
|
||||
const requiresSpaceId = ['create', 'get_space']
|
||||
|
||||
if (requiresPageId.includes(operation) && !effectivePageId) {
|
||||
throw new Error('Page ID is required. Please select a page or enter a page ID manually.')
|
||||
}
|
||||
|
||||
if (requiresSpaceId.includes(operation) && !rest.spaceId) {
|
||||
throw new Error('Space ID is required for this operation.')
|
||||
}
|
||||
|
||||
if (operation === 'upload_attachment') {
|
||||
const fileInput = attachmentFileUpload || attachmentFileReference || attachmentFile
|
||||
if (!fileInput) {
|
||||
throw new Error('File is required for upload attachment operation.')
|
||||
}
|
||||
return {
|
||||
credential,
|
||||
pageId: effectivePageId,
|
||||
operation,
|
||||
file: fileInput,
|
||||
fileName: attachmentFileName,
|
||||
comment: attachmentComment,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
credential,
|
||||
pageId: effectivePageId || undefined,
|
||||
operation,
|
||||
...rest,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
domain: { type: 'string', description: 'Confluence domain' },
|
||||
credential: { type: 'string', description: 'Confluence access token' },
|
||||
pageId: { type: 'string', description: 'Page identifier' },
|
||||
manualPageId: { type: 'string', description: 'Manual page identifier' },
|
||||
spaceId: { type: 'string', description: 'Space identifier' },
|
||||
title: { type: 'string', description: 'Page title' },
|
||||
content: { type: 'string', description: 'Page content' },
|
||||
parentId: { type: 'string', description: 'Parent page identifier' },
|
||||
query: { type: 'string', description: 'Search query' },
|
||||
comment: { type: 'string', description: 'Comment text' },
|
||||
commentId: { type: 'string', description: 'Comment identifier' },
|
||||
attachmentId: { type: 'string', description: 'Attachment identifier' },
|
||||
attachmentFile: { type: 'json', description: 'File to upload as attachment' },
|
||||
attachmentFileUpload: { type: 'json', description: 'Uploaded file (basic mode)' },
|
||||
attachmentFileReference: { type: 'json', description: 'File reference (advanced mode)' },
|
||||
attachmentFileName: { type: 'string', description: 'Custom file name for attachment' },
|
||||
attachmentComment: { type: 'string', description: 'Comment for the attachment' },
|
||||
labelName: { type: 'string', description: 'Label name' },
|
||||
limit: { type: 'number', description: 'Maximum number of results' },
|
||||
},
|
||||
}
|
||||
|
||||
@@ -173,9 +173,9 @@ export const MistralParseV2Block: BlockConfig<MistralParserOutput> = {
|
||||
title: 'Output Format',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ id: 'markdown', label: 'Markdown (Formatted)' },
|
||||
{ id: 'markdown', label: 'Markdown' },
|
||||
{ id: 'text', label: 'Plain Text' },
|
||||
{ id: 'json', label: 'JSON (Raw)' },
|
||||
{ id: 'json', label: 'JSON' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -262,7 +262,9 @@ export const MistralParseV2Block: BlockConfig<MistralParserOutput> = {
|
||||
pages: { type: 'string', description: 'Page selection' },
|
||||
},
|
||||
outputs: {
|
||||
content: { type: 'string', description: 'Extracted content' },
|
||||
metadata: { type: 'json', description: 'Processing metadata' },
|
||||
pages: { type: 'array', description: 'Array of page objects from Mistral OCR' },
|
||||
model: { type: 'string', description: 'Mistral OCR model identifier' },
|
||||
usage_info: { type: 'json', description: 'Usage statistics from the API' },
|
||||
document_annotation: { type: 'string', description: 'Structured annotation data' },
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ import type { VideoBlockResponse } from '@/tools/video/types'
|
||||
|
||||
export const VideoGeneratorBlock: BlockConfig<VideoBlockResponse> = {
|
||||
type: 'video_generator',
|
||||
name: 'Video Generator',
|
||||
name: 'Video Generator (Legacy)',
|
||||
description: 'Generate videos from text using AI',
|
||||
hideFromToolbar: true,
|
||||
authMode: AuthMode.ApiKey,
|
||||
longDescription:
|
||||
'Generate high-quality videos from text prompts using leading AI providers. Supports multiple models, aspect ratios, resolutions, and provider-specific features like world consistency, camera controls, and audio generation.',
|
||||
@@ -427,3 +428,378 @@ export const VideoGeneratorBlock: BlockConfig<VideoBlockResponse> = {
|
||||
model: { type: 'string', description: 'Model used' },
|
||||
},
|
||||
}
|
||||
|
||||
export const VideoGeneratorV2Block: BlockConfig<VideoBlockResponse> = {
|
||||
...VideoGeneratorBlock,
|
||||
type: 'video_generator_v2',
|
||||
name: 'Video Generator',
|
||||
hideFromToolbar: false,
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'provider',
|
||||
title: 'Provider',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Runway Gen-4', id: 'runway' },
|
||||
{ label: 'Google Veo 3', id: 'veo' },
|
||||
{ label: 'Luma Dream Machine', id: 'luma' },
|
||||
{ label: 'MiniMax Hailuo', id: 'minimax' },
|
||||
{ label: 'Fal.ai (Multi-Model)', id: 'falai' },
|
||||
],
|
||||
value: () => 'runway',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'model',
|
||||
title: 'Model',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'veo' },
|
||||
options: [
|
||||
{ label: 'Veo 3', id: 'veo-3' },
|
||||
{ label: 'Veo 3 Fast', id: 'veo-3-fast' },
|
||||
{ label: 'Veo 3.1', id: 'veo-3.1' },
|
||||
],
|
||||
value: () => 'veo-3',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'model',
|
||||
title: 'Model',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'luma' },
|
||||
options: [{ label: 'Ray 2', id: 'ray-2' }],
|
||||
value: () => 'ray-2',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'model',
|
||||
title: 'Model',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'minimax' },
|
||||
options: [{ label: 'Hailuo 2.3', id: 'hailuo-02' }],
|
||||
value: () => 'hailuo-02',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'endpoint',
|
||||
title: 'Quality Endpoint',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'minimax' },
|
||||
options: [
|
||||
{ label: 'Pro', id: 'pro' },
|
||||
{ label: 'Standard', id: 'standard' },
|
||||
],
|
||||
value: () => 'standard',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'model',
|
||||
title: 'Model',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'falai' },
|
||||
options: [
|
||||
{ label: 'Google Veo 3.1', id: 'veo-3.1' },
|
||||
{ label: 'OpenAI Sora 2', id: 'sora-2' },
|
||||
{ label: 'Kling 2.5 Turbo Pro', id: 'kling-2.5-turbo-pro' },
|
||||
{ label: 'Kling 2.1 Pro', id: 'kling-2.1-pro' },
|
||||
{ label: 'MiniMax Hailuo 2.3 Pro', id: 'minimax-hailuo-2.3-pro' },
|
||||
{ label: 'MiniMax Hailuo 2.3 Standard', id: 'minimax-hailuo-2.3-standard' },
|
||||
{ label: 'WAN 2.1', id: 'wan-2.1' },
|
||||
{ label: 'LTXV 0.9.8', id: 'ltxv-0.9.8' },
|
||||
],
|
||||
value: () => 'veo-3.1',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'prompt',
|
||||
title: 'Prompt',
|
||||
type: 'long-input',
|
||||
placeholder: 'Describe the video you want to generate...',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'duration',
|
||||
title: 'Duration (seconds)',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'runway' },
|
||||
options: [
|
||||
{ label: '5', id: '5' },
|
||||
{ label: '10', id: '10' },
|
||||
],
|
||||
value: () => '5',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'duration',
|
||||
title: 'Duration (seconds)',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'veo' },
|
||||
options: [
|
||||
{ label: '4', id: '4' },
|
||||
{ label: '6', id: '6' },
|
||||
{ label: '8', id: '8' },
|
||||
],
|
||||
value: () => '8',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'duration',
|
||||
title: 'Duration (seconds)',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'luma' },
|
||||
options: [
|
||||
{ label: '5', id: '5' },
|
||||
{ label: '9', id: '9' },
|
||||
],
|
||||
value: () => '5',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'duration',
|
||||
title: 'Duration (seconds)',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'minimax' },
|
||||
options: [
|
||||
{ label: '6', id: '6' },
|
||||
{ label: '10', id: '10' },
|
||||
],
|
||||
value: () => '6',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'duration',
|
||||
title: 'Duration (seconds)',
|
||||
type: 'dropdown',
|
||||
condition: {
|
||||
field: 'model',
|
||||
value: [
|
||||
'kling-2.5-turbo-pro',
|
||||
'kling-2.1-pro',
|
||||
'minimax-hailuo-2.3-pro',
|
||||
'minimax-hailuo-2.3-standard',
|
||||
],
|
||||
},
|
||||
options: [
|
||||
{ label: '5', id: '5' },
|
||||
{ label: '8', id: '8' },
|
||||
{ label: '10', id: '10' },
|
||||
],
|
||||
value: () => '5',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'aspectRatio',
|
||||
title: 'Aspect Ratio',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'veo' },
|
||||
options: [
|
||||
{ label: '16:9', id: '16:9' },
|
||||
{ label: '9:16', id: '9:16' },
|
||||
],
|
||||
value: () => '16:9',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'aspectRatio',
|
||||
title: 'Aspect Ratio',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'runway' },
|
||||
options: [
|
||||
{ label: '16:9', id: '16:9' },
|
||||
{ label: '9:16', id: '9:16' },
|
||||
{ label: '1:1', id: '1:1' },
|
||||
],
|
||||
value: () => '16:9',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'aspectRatio',
|
||||
title: 'Aspect Ratio',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'luma' },
|
||||
options: [
|
||||
{ label: '16:9', id: '16:9' },
|
||||
{ label: '9:16', id: '9:16' },
|
||||
{ label: '1:1', id: '1:1' },
|
||||
],
|
||||
value: () => '16:9',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'aspectRatio',
|
||||
title: 'Aspect Ratio',
|
||||
type: 'dropdown',
|
||||
condition: {
|
||||
field: 'model',
|
||||
value: [
|
||||
'kling-2.5-turbo-pro',
|
||||
'kling-2.1-pro',
|
||||
'minimax-hailuo-2.3-pro',
|
||||
'minimax-hailuo-2.3-standard',
|
||||
],
|
||||
},
|
||||
options: [
|
||||
{ label: '16:9', id: '16:9' },
|
||||
{ label: '9:16', id: '9:16' },
|
||||
],
|
||||
value: () => '16:9',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'resolution',
|
||||
title: 'Resolution',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'veo' },
|
||||
options: [
|
||||
{ label: '720p', id: '720p' },
|
||||
{ label: '1080p', id: '1080p' },
|
||||
],
|
||||
value: () => '1080p',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'resolution',
|
||||
title: 'Resolution',
|
||||
type: 'dropdown',
|
||||
condition: { field: 'provider', value: 'luma' },
|
||||
options: [
|
||||
{ label: '540p', id: '540p' },
|
||||
{ label: '720p', id: '720p' },
|
||||
{ label: '1080p', id: '1080p' },
|
||||
],
|
||||
value: () => '1080p',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'visualReferenceUpload',
|
||||
title: 'Reference Image',
|
||||
type: 'file-upload',
|
||||
canonicalParamId: 'visualReference',
|
||||
condition: { field: 'provider', value: 'runway' },
|
||||
placeholder: 'Upload reference image',
|
||||
mode: 'basic',
|
||||
multiple: false,
|
||||
required: true,
|
||||
acceptedTypes: '.jpg,.jpeg,.png,.webp',
|
||||
},
|
||||
{
|
||||
id: 'visualReferenceInput',
|
||||
title: 'Reference Image',
|
||||
type: 'short-input',
|
||||
canonicalParamId: 'visualReference',
|
||||
condition: { field: 'provider', value: 'runway' },
|
||||
placeholder: 'Reference image from previous blocks',
|
||||
mode: 'advanced',
|
||||
},
|
||||
{
|
||||
id: 'cameraControl',
|
||||
title: 'Camera Controls',
|
||||
type: 'long-input',
|
||||
condition: { field: 'provider', value: 'luma' },
|
||||
placeholder: 'JSON: [{ "key": "pan_right" }, { "key": "zoom_in" }]',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
id: 'promptOptimizer',
|
||||
title: 'Prompt Optimizer',
|
||||
type: 'switch',
|
||||
condition: { field: 'provider', value: 'minimax' },
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'API Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your provider API key',
|
||||
password: true,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['video_runway', 'video_veo', 'video_luma', 'video_minimax', 'video_falai'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.provider) {
|
||||
case 'runway':
|
||||
return 'video_runway'
|
||||
case 'veo':
|
||||
return 'video_veo'
|
||||
case 'luma':
|
||||
return 'video_luma'
|
||||
case 'minimax':
|
||||
return 'video_minimax'
|
||||
case 'falai':
|
||||
return 'video_falai'
|
||||
default:
|
||||
return 'video_runway'
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const visualRef =
|
||||
params.visualReferenceUpload || params.visualReferenceInput || params.visualReference
|
||||
return {
|
||||
provider: params.provider,
|
||||
apiKey: params.apiKey,
|
||||
model: params.model,
|
||||
endpoint: params.endpoint,
|
||||
prompt: params.prompt,
|
||||
duration: params.duration ? Number(params.duration) : undefined,
|
||||
aspectRatio: params.aspectRatio,
|
||||
resolution: params.resolution,
|
||||
visualReference: visualRef,
|
||||
consistencyMode: params.consistencyMode,
|
||||
stylePreset: params.stylePreset,
|
||||
promptOptimizer: params.promptOptimizer,
|
||||
cameraControl: params.cameraControl
|
||||
? typeof params.cameraControl === 'string'
|
||||
? JSON.parse(params.cameraControl)
|
||||
: params.cameraControl
|
||||
: undefined,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
provider: {
|
||||
type: 'string',
|
||||
description: 'Video generation provider (runway, veo, luma, minimax)',
|
||||
},
|
||||
apiKey: { type: 'string', description: 'Provider API key' },
|
||||
model: {
|
||||
type: 'string',
|
||||
description: 'Provider-specific model',
|
||||
},
|
||||
endpoint: {
|
||||
type: 'string',
|
||||
description: 'Quality endpoint for MiniMax (pro, standard)',
|
||||
},
|
||||
prompt: { type: 'string', description: 'Text prompt for video generation' },
|
||||
duration: { type: 'number', description: 'Video duration in seconds' },
|
||||
aspectRatio: {
|
||||
type: 'string',
|
||||
description: 'Aspect ratio (16:9, 9:16, 1:1) - not available for MiniMax',
|
||||
},
|
||||
resolution: {
|
||||
type: 'string',
|
||||
description: 'Video resolution - not available for MiniMax (fixed per endpoint)',
|
||||
},
|
||||
visualReference: { type: 'json', description: 'Reference image for Runway (UserFile)' },
|
||||
visualReferenceUpload: { type: 'json', description: 'Uploaded reference image (basic mode)' },
|
||||
visualReferenceInput: {
|
||||
type: 'json',
|
||||
description: 'Reference image from previous blocks (advanced mode)',
|
||||
},
|
||||
consistencyMode: {
|
||||
type: 'string',
|
||||
description: 'Consistency mode for Runway (character, object, style, location)',
|
||||
},
|
||||
stylePreset: { type: 'string', description: 'Style preset for Runway' },
|
||||
promptOptimizer: {
|
||||
type: 'boolean',
|
||||
description: 'Enable prompt optimization for MiniMax (default: true)',
|
||||
},
|
||||
cameraControl: {
|
||||
type: 'json',
|
||||
description: 'Camera controls for Luma (pan, zoom, tilt, truck, tracking)',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { ChatTriggerBlock } from '@/blocks/blocks/chat_trigger'
|
||||
import { CirclebackBlock } from '@/blocks/blocks/circleback'
|
||||
import { ClayBlock } from '@/blocks/blocks/clay'
|
||||
import { ConditionBlock } from '@/blocks/blocks/condition'
|
||||
import { ConfluenceBlock } from '@/blocks/blocks/confluence'
|
||||
import { ConfluenceBlock, ConfluenceV2Block } from '@/blocks/blocks/confluence'
|
||||
import { CursorBlock, CursorV2Block } from '@/blocks/blocks/cursor'
|
||||
import { DatadogBlock } from '@/blocks/blocks/datadog'
|
||||
import { DiscordBlock } from '@/blocks/blocks/discord'
|
||||
@@ -133,7 +133,7 @@ import { TwilioSMSBlock } from '@/blocks/blocks/twilio'
|
||||
import { TwilioVoiceBlock } from '@/blocks/blocks/twilio_voice'
|
||||
import { TypeformBlock } from '@/blocks/blocks/typeform'
|
||||
import { VariablesBlock } from '@/blocks/blocks/variables'
|
||||
import { VideoGeneratorBlock } from '@/blocks/blocks/video_generator'
|
||||
import { VideoGeneratorBlock, VideoGeneratorV2Block } from '@/blocks/blocks/video_generator'
|
||||
import { VisionBlock } from '@/blocks/blocks/vision'
|
||||
import { WaitBlock } from '@/blocks/blocks/wait'
|
||||
import { WealthboxBlock } from '@/blocks/blocks/wealthbox'
|
||||
@@ -170,6 +170,7 @@ export const registry: Record<string, BlockConfig> = {
|
||||
clay: ClayBlock,
|
||||
condition: ConditionBlock,
|
||||
confluence: ConfluenceBlock,
|
||||
confluence_v2: ConfluenceV2Block,
|
||||
cursor: CursorBlock,
|
||||
cursor_v2: CursorV2Block,
|
||||
datadog: DatadogBlock,
|
||||
@@ -300,6 +301,7 @@ export const registry: Record<string, BlockConfig> = {
|
||||
typeform: TypeformBlock,
|
||||
variables: VariablesBlock,
|
||||
video_generator: VideoGeneratorBlock,
|
||||
video_generator_v2: VideoGeneratorV2Block,
|
||||
vision: VisionBlock,
|
||||
wait: WaitBlock,
|
||||
wealthbox: WealthboxBlock,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import type { MistralParserInput, MistralParserOutput } from '@/tools/mistral/types'
|
||||
import type {
|
||||
MistralParserInput,
|
||||
MistralParserOutput,
|
||||
MistralParserV2Output,
|
||||
} from '@/tools/mistral/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('MistralParserTool')
|
||||
@@ -416,7 +420,7 @@ export const mistralParserTool: ToolConfig<MistralParserInput, MistralParserOutp
|
||||
},
|
||||
}
|
||||
|
||||
export const mistralParserV2Tool: ToolConfig<MistralParserInput, MistralParserOutput> = {
|
||||
export const mistralParserV2Tool: ToolConfig<MistralParserInput, MistralParserV2Output> = {
|
||||
id: 'mistral_parser_v2',
|
||||
name: 'Mistral PDF Parser',
|
||||
description: 'Parse PDF documents using Mistral OCR API',
|
||||
@@ -424,17 +428,129 @@ export const mistralParserV2Tool: ToolConfig<MistralParserInput, MistralParserOu
|
||||
|
||||
params: mistralParserTool.params,
|
||||
request: mistralParserTool.request,
|
||||
transformResponse: mistralParserTool.transformResponse,
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
let ocrResult
|
||||
try {
|
||||
ocrResult = await response.json()
|
||||
} catch (jsonError) {
|
||||
throw new Error(
|
||||
`Failed to parse Mistral OCR response: ${jsonError instanceof Error ? jsonError.message : String(jsonError)}`
|
||||
)
|
||||
}
|
||||
|
||||
if (!ocrResult || typeof ocrResult !== 'object') {
|
||||
throw new Error('Invalid response format from Mistral OCR API')
|
||||
}
|
||||
|
||||
// Extract the actual Mistral data (may be nested in output from our API route)
|
||||
const mistralData =
|
||||
ocrResult.output && typeof ocrResult.output === 'object' && !ocrResult.pages
|
||||
? ocrResult.output
|
||||
: ocrResult
|
||||
|
||||
// Return raw Mistral API structure - no transformation
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
pages: mistralData.pages ?? [],
|
||||
model: mistralData.model ?? 'mistral-ocr-latest',
|
||||
usage_info: mistralData.usage_info ?? { pages_processed: 0, doc_size_bytes: null },
|
||||
document_annotation: mistralData.document_annotation ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the PDF was parsed successfully' },
|
||||
content: {
|
||||
type: 'string',
|
||||
description: 'Extracted content in the requested format (markdown, text, or JSON)',
|
||||
pages: {
|
||||
type: 'array',
|
||||
description: 'Array of page objects from Mistral OCR',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
index: { type: 'number', description: 'Page index (zero-based)' },
|
||||
markdown: { type: 'string', description: 'Extracted markdown content' },
|
||||
images: {
|
||||
type: 'array',
|
||||
description: 'Images extracted from this page with bounding boxes',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Image identifier (e.g., img-0.jpeg)' },
|
||||
top_left_x: { type: 'number', description: 'Top-left X coordinate in pixels' },
|
||||
top_left_y: { type: 'number', description: 'Top-left Y coordinate in pixels' },
|
||||
bottom_right_x: {
|
||||
type: 'number',
|
||||
description: 'Bottom-right X coordinate in pixels',
|
||||
},
|
||||
bottom_right_y: {
|
||||
type: 'number',
|
||||
description: 'Bottom-right Y coordinate in pixels',
|
||||
},
|
||||
image_base64: {
|
||||
type: 'string',
|
||||
description: 'Base64-encoded image data (when include_image_base64=true)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dimensions: {
|
||||
type: 'object',
|
||||
description: 'Page dimensions',
|
||||
properties: {
|
||||
dpi: { type: 'number', description: 'Dots per inch' },
|
||||
height: { type: 'number', description: 'Page height in pixels' },
|
||||
width: { type: 'number', description: 'Page width in pixels' },
|
||||
},
|
||||
},
|
||||
tables: {
|
||||
type: 'array',
|
||||
description:
|
||||
'Extracted tables as HTML/markdown (when table_format is set). Referenced via placeholders like [tbl-0.html]',
|
||||
},
|
||||
hyperlinks: {
|
||||
type: 'array',
|
||||
description:
|
||||
'Array of URL strings detected in the page (e.g., ["https://...", "mailto:..."])',
|
||||
items: {
|
||||
type: 'string',
|
||||
description: 'URL or mailto link',
|
||||
},
|
||||
},
|
||||
header: {
|
||||
type: 'string',
|
||||
description: 'Page header content (when extract_header=true)',
|
||||
optional: true,
|
||||
},
|
||||
footer: {
|
||||
type: 'string',
|
||||
description: 'Page footer content (when extract_footer=true)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: {
|
||||
model: {
|
||||
type: 'string',
|
||||
description: 'Mistral OCR model identifier (e.g., mistral-ocr-latest)',
|
||||
},
|
||||
usage_info: {
|
||||
type: 'object',
|
||||
description: 'Processing metadata including jobId, fileType, pageCount, and usage info',
|
||||
description: 'Usage and processing statistics',
|
||||
properties: {
|
||||
pages_processed: { type: 'number', description: 'Total number of pages processed' },
|
||||
doc_size_bytes: {
|
||||
type: 'number',
|
||||
description: 'Document file size in bytes',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
document_annotation: {
|
||||
type: 'string',
|
||||
description: 'Structured annotation data as JSON string (when applicable)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -96,3 +96,81 @@ export interface MistralParserOutput extends ToolResponse {
|
||||
/** The output data containing content and metadata */
|
||||
output: MistralParserOutputData
|
||||
}
|
||||
|
||||
/**
|
||||
* Image bounding box and data from Mistral OCR API
|
||||
*/
|
||||
export interface MistralOcrImage {
|
||||
/** Image identifier */
|
||||
id: string
|
||||
/** Top-left X coordinate */
|
||||
top_left_x: number
|
||||
/** Top-left Y coordinate */
|
||||
top_left_y: number
|
||||
/** Bottom-right X coordinate */
|
||||
bottom_right_x: number
|
||||
/** Bottom-right Y coordinate */
|
||||
bottom_right_y: number
|
||||
/** Base64-encoded image data (if includeImageBase64 was true) */
|
||||
image_base64?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Page dimensions from Mistral OCR API
|
||||
*/
|
||||
export interface MistralOcrDimensions {
|
||||
/** DPI of the page */
|
||||
dpi: number
|
||||
/** Page height in pixels */
|
||||
height: number
|
||||
/** Page width in pixels */
|
||||
width: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Page data from Mistral OCR API
|
||||
*/
|
||||
export interface MistralOcrPage {
|
||||
/** Page index (zero-based) */
|
||||
index: number
|
||||
/** Markdown content extracted from this page */
|
||||
markdown: string
|
||||
/** Images extracted from this page */
|
||||
images: MistralOcrImage[]
|
||||
/** Page dimensions */
|
||||
dimensions: MistralOcrDimensions
|
||||
/** Tables extracted from this page */
|
||||
tables: unknown[]
|
||||
/** Hyperlinks found on this page */
|
||||
hyperlinks: unknown[]
|
||||
/** Header content if detected */
|
||||
header: string | null
|
||||
/** Footer content if detected */
|
||||
footer: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw usage info from Mistral OCR API
|
||||
*/
|
||||
export interface MistralOcrUsageInfoRaw {
|
||||
/** Number of pages processed */
|
||||
pages_processed: number
|
||||
/** Document size in bytes */
|
||||
doc_size_bytes: number | null
|
||||
}
|
||||
|
||||
/**
|
||||
* V2 Output - Returns raw Mistral API response structure
|
||||
*/
|
||||
export interface MistralParserV2Output extends ToolResponse {
|
||||
output: {
|
||||
/** Array of page objects with full OCR data */
|
||||
pages: MistralOcrPage[]
|
||||
/** Model used for OCR processing */
|
||||
model: string
|
||||
/** Usage statistics from the API */
|
||||
usage_info: MistralOcrUsageInfoRaw
|
||||
/** Structured annotation data as JSON string (when applicable) */
|
||||
document_annotation: string | null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user