mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-24 11:36:37 +08:00
115 lines
3.6 KiB
TypeScript
115 lines
3.6 KiB
TypeScript
import { BlockState, SubBlockState } from '@/stores/workflow/types';
|
|
import { Edge } from 'reactflow';
|
|
import { SerializedBlock, SerializedConnection, SerializedWorkflow } from './types';
|
|
import { getBlock, getBlockTypeForTool } from '@/blocks';
|
|
import { OutputType, SubBlockType } from '@/blocks/types';
|
|
|
|
export class Serializer {
|
|
serializeWorkflow(blocks: Record<string, BlockState>, connections: Edge[]): SerializedWorkflow {
|
|
return {
|
|
version: '1.0',
|
|
blocks: Object.values(blocks).map(block => this.serializeBlock(block)),
|
|
connections: connections.map(conn => ({
|
|
source: conn.source,
|
|
target: conn.target,
|
|
sourceHandle: conn.sourceHandle || undefined,
|
|
targetHandle: conn.targetHandle || undefined
|
|
}))
|
|
};
|
|
}
|
|
|
|
private serializeBlock(block: BlockState): SerializedBlock {
|
|
const blockConfig = getBlock(block.type);
|
|
if (!blockConfig) {
|
|
throw new Error(`Block configuration not found for type: ${block.type}`);
|
|
}
|
|
|
|
// Get the tool ID from the block's configuration
|
|
const tools = blockConfig.tools;
|
|
if (!tools?.access || tools.access.length === 0) {
|
|
throw new Error(`No tools specified for block type: ${block.type}`);
|
|
}
|
|
|
|
// Get all values from subBlocks
|
|
const params: Record<string, any> = {};
|
|
Object.entries(block.subBlocks || {}).forEach(([id, subBlock]) => {
|
|
if (subBlock?.value !== undefined) {
|
|
params[id] = subBlock.value;
|
|
}
|
|
});
|
|
|
|
// Get the tool ID from the block's configuration
|
|
const toolId = tools.config?.tool?.(params) || params.tool || tools.access[0];
|
|
if (!toolId || !tools.access.includes(toolId)) {
|
|
throw new Error(`Invalid or unauthorized tool: ${toolId}`);
|
|
}
|
|
|
|
return {
|
|
id: block.id,
|
|
position: block.position,
|
|
config: {
|
|
tool: toolId,
|
|
params: params,
|
|
interface: {
|
|
inputs: blockConfig.workflow.inputs || {},
|
|
outputs: {
|
|
output: block.outputType
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
deserializeWorkflow(serialized: SerializedWorkflow): {
|
|
blocks: Record<string, BlockState>;
|
|
connections: Edge[];
|
|
} {
|
|
const blocks: Record<string, BlockState> = {};
|
|
serialized.blocks.forEach(block => {
|
|
const deserialized = this.deserializeBlock(block);
|
|
blocks[deserialized.id] = deserialized;
|
|
});
|
|
|
|
return {
|
|
blocks,
|
|
connections: serialized.connections.map(conn => ({
|
|
id: `${conn.source}-${conn.target}`,
|
|
source: conn.source,
|
|
target: conn.target,
|
|
sourceHandle: conn.sourceHandle || null,
|
|
targetHandle: conn.targetHandle || null
|
|
}))
|
|
};
|
|
}
|
|
|
|
private deserializeBlock(serialized: SerializedBlock): BlockState {
|
|
const toolId = serialized.config.tool;
|
|
const blockType = getBlockTypeForTool(toolId);
|
|
|
|
if (!blockType) {
|
|
throw new Error(`Could not determine block type for tool: ${toolId}`);
|
|
}
|
|
|
|
const blockConfig = getBlock(blockType);
|
|
if (!blockConfig) {
|
|
throw new Error(`Block configuration not found for type: ${blockType}`);
|
|
}
|
|
|
|
return {
|
|
id: serialized.id,
|
|
type: blockType,
|
|
name: `${blockType} Block`,
|
|
position: serialized.position,
|
|
subBlocks: Object.entries(serialized.config.params).reduce((acc, [key, value]) => {
|
|
const subBlock = blockConfig.workflow.subBlocks?.find(sb => sb.id === key);
|
|
acc[key] = {
|
|
id: key,
|
|
type: subBlock?.type || 'short-input',
|
|
value: value
|
|
};
|
|
return acc;
|
|
}, {} as Record<string, SubBlockState>),
|
|
outputType: serialized.config.interface.outputs.output as OutputType
|
|
};
|
|
}
|
|
} |