Standardized output format for blocks/tools. Updated executor so we can now resolve sub-json values for tagged inputs. Updated serializer to match new block output format.

This commit is contained in:
Waleed Latif
2025-01-30 13:50:38 -08:00
parent 15b42c7d19
commit 3850c112ca
31 changed files with 798 additions and 775 deletions
+11 -3
View File
@@ -52,12 +52,20 @@ export const AgentBlock: BlockConfig = {
},
outputs: {
response: {
type: 'string',
type: {
text: 'string',
model: 'string',
tokens: 'number'
},
dependsOn: {
subBlockId: 'responseFormat',
condition: {
whenEmpty: 'string',
whenFilled: 'json'
whenEmpty: {
response: { type: 'string' }
},
whenFilled: {
response: { type: 'json' }
}
}
}
}
+7 -1
View File
@@ -21,7 +21,13 @@ export const ApiBlock: BlockConfig = {
body: { type: 'json', required: false }
},
outputs: {
response: 'any'
response: {
type: {
body: 'any',
status: 'number',
headers: 'json'
}
}
},
subBlocks: [
{
+15 -9
View File
@@ -21,17 +21,15 @@ export const CrewAIVisionBlock: BlockConfig = {
prompt: { type: 'string', required: false }
},
outputs: {
response: 'any'
response: {
type: {
text: 'string',
model: 'string',
tokens: 'number'
}
}
},
subBlocks: [
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
layout: 'full',
placeholder: 'Enter your API key',
password: true
},
{
id: 'imageUrl',
title: 'Image URL',
@@ -50,6 +48,14 @@ export const CrewAIVisionBlock: BlockConfig = {
'claude-3-sonnet-20240229'
]
},
{
id: 'apiKey',
title: 'API Key',
type: 'short-input',
layout: 'full',
placeholder: 'Enter your API key',
password: true
},
{
id: 'prompt',
title: 'Custom Prompt',
+7 -1
View File
@@ -20,7 +20,13 @@ export const FirecrawlScrapeBlock: BlockConfig = {
scrapeOptions: { type: 'json', required: false }
},
outputs: {
response: 'any'
response: {
type: {
markdown: 'string',
html: 'string',
metadata: 'json'
}
}
},
subBlocks: [
{
+6 -1
View File
@@ -21,7 +21,12 @@ export const FunctionBlock: BlockConfig = {
code: { type: 'string', required: true }
},
outputs: {
result: 'any'
response: {
type: {
value: 'any',
stdout: 'string'
}
}
},
subBlocks: [
{
+13 -6
View File
@@ -3,19 +3,26 @@ import type { JSX } from 'react'
export type BlockIcon = (props: SVGProps<SVGSVGElement>) => JSX.Element
export type BlockCategory = 'basic' | 'advanced'
export type OutputType = 'string' | 'number' | 'json' | 'boolean' | 'any'
export type PrimitiveValueType = 'string' | 'number' | 'json' | 'boolean' | 'any'
export type ValueType = PrimitiveValueType | Record<string, PrimitiveValueType>
export interface BlockOutput {
response: ValueType
}
export type ParamType = 'string' | 'number' | 'boolean' | 'json'
export type SubBlockType = 'short-input' | 'long-input' | 'dropdown' | 'slider' | 'table' | 'code' | 'switch'
export type SubBlockLayout = 'full' | 'half'
export type OutputConfig = OutputType | {
type: OutputType
dependsOn: {
export interface OutputConfig {
type: ValueType
dependsOn?: {
subBlockId: string
condition: {
whenEmpty: OutputType
whenFilled: OutputType
whenEmpty: BlockOutput
whenFilled: BlockOutput
}
}
}
+9 -11
View File
@@ -1,5 +1,5 @@
import { BlockState, SubBlockState } from '@/stores/workflow/types'
import { OutputType, OutputConfig } from '@/blocks/types'
import { BlockOutput, OutputConfig } from '@/blocks/types'
interface CodeLine {
id: string
@@ -28,23 +28,21 @@ function isCodeEditorValue(value: any[]): value is CodeLine[] {
export function resolveOutputType(
outputs: Record<string, OutputConfig>,
subBlocks: Record<string, SubBlockState>
): Record<string, OutputType> {
const resolvedOutputs: Record<string, OutputType> = {}
): Record<string, BlockOutput> {
const resolvedOutputs: Record<string, BlockOutput> = {}
for (const [key, outputConfig] of Object.entries(outputs)) {
// If outputType is a string, use it directly
if (typeof outputConfig === 'string') {
resolvedOutputs[key] = outputConfig
// If no dependencies, use the type directly
if (!outputConfig.dependsOn) {
resolvedOutputs[key] = { response: outputConfig.type }
continue
}
// Handle dependent output types
const { dependsOn } = outputConfig
const subBlock = subBlocks[dependsOn.subBlockId]
const subBlock = subBlocks[outputConfig.dependsOn.subBlockId]
resolvedOutputs[key] = isEmptyValue(subBlock?.value)
? dependsOn.condition.whenEmpty
: dependsOn.condition.whenFilled
? outputConfig.dependsOn.condition.whenEmpty
: outputConfig.dependsOn.condition.whenFilled
}
return resolvedOutputs