mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Removed extraneous semicolons
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
import { Edge } from 'reactflow';
|
||||
import { Serializer } from '../index';
|
||||
import { SerializedWorkflow } from '../types';
|
||||
import { BlockState } from '@/stores/workflow/types';
|
||||
import { OutputType } from '@/blocks/types';
|
||||
import { Edge } from 'reactflow'
|
||||
import { Serializer } from '../index'
|
||||
import { SerializedWorkflow } from '../types'
|
||||
import { BlockState } from '@/stores/workflow/types'
|
||||
import { OutputType } from '@/blocks/types'
|
||||
|
||||
// Mock icons
|
||||
jest.mock('@/components/icons', () => ({
|
||||
AgentIcon: () => 'AgentIcon',
|
||||
ApiIcon: () => 'ApiIcon',
|
||||
CodeIcon: () => 'CodeIcon',
|
||||
}));
|
||||
}))
|
||||
|
||||
// Mock blocks
|
||||
jest.mock('@/blocks', () => ({
|
||||
@@ -35,7 +35,7 @@ jest.mock('@/blocks', () => ({
|
||||
},
|
||||
subBlocks: []
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// Default agent block config
|
||||
return {
|
||||
@@ -60,24 +60,24 @@ jest.mock('@/blocks', () => ({
|
||||
},
|
||||
subBlocks: []
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
getBlockTypeForTool: (toolId: string) => {
|
||||
const toolToType: Record<string, string> = {
|
||||
'openai.chat': 'agent',
|
||||
'http.request': 'api',
|
||||
'function': 'function'
|
||||
};
|
||||
return toolToType[toolId];
|
||||
}
|
||||
return toolToType[toolId]
|
||||
}
|
||||
}));
|
||||
}))
|
||||
|
||||
describe('Serializer', () => {
|
||||
let serializer: Serializer;
|
||||
let serializer: Serializer
|
||||
|
||||
beforeEach(() => {
|
||||
serializer = new Serializer();
|
||||
});
|
||||
serializer = new Serializer()
|
||||
})
|
||||
|
||||
describe('serializeWorkflow', () => {
|
||||
it('should serialize a workflow with agent and http blocks', () => {
|
||||
@@ -125,7 +125,7 @@ describe('Serializer', () => {
|
||||
},
|
||||
outputType: 'json'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const connections: Edge[] = [
|
||||
{
|
||||
@@ -135,34 +135,34 @@ describe('Serializer', () => {
|
||||
sourceHandle: 'response',
|
||||
targetHandle: 'body'
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
const serialized = serializer.serializeWorkflow(blocks, connections);
|
||||
const serialized = serializer.serializeWorkflow(blocks, connections)
|
||||
|
||||
// Test workflow structure
|
||||
expect(serialized.version).toBe('1.0');
|
||||
expect(serialized.blocks).toHaveLength(2);
|
||||
expect(serialized.connections).toHaveLength(1);
|
||||
expect(serialized.version).toBe('1.0')
|
||||
expect(serialized.blocks).toHaveLength(2)
|
||||
expect(serialized.connections).toHaveLength(1)
|
||||
|
||||
// Test agent block serialization
|
||||
const agentBlock = serialized.blocks.find(b => b.id === 'agent-1');
|
||||
expect(agentBlock).toBeDefined();
|
||||
expect(agentBlock?.config.tool).toBe('openai.chat');
|
||||
const agentBlock = serialized.blocks.find(b => b.id === 'agent-1')
|
||||
expect(agentBlock).toBeDefined()
|
||||
expect(agentBlock?.config.tool).toBe('openai.chat')
|
||||
expect(agentBlock?.config.params).toEqual({
|
||||
model: 'gpt-4o',
|
||||
systemPrompt: 'You are helpful',
|
||||
temperature: 0.7
|
||||
});
|
||||
})
|
||||
|
||||
// Test http block serialization
|
||||
const httpBlock = serialized.blocks.find(b => b.id === 'http-1');
|
||||
expect(httpBlock).toBeDefined();
|
||||
expect(httpBlock?.config.tool).toBe('http.request');
|
||||
const httpBlock = serialized.blocks.find(b => b.id === 'http-1')
|
||||
expect(httpBlock).toBeDefined()
|
||||
expect(httpBlock?.config.tool).toBe('http.request')
|
||||
expect(httpBlock?.config.params).toEqual({
|
||||
url: 'https://api.example.com',
|
||||
method: 'GET'
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle blocks with minimal required configuration', () => {
|
||||
const blocks: Record<string, BlockState> = {
|
||||
@@ -180,15 +180,15 @@ describe('Serializer', () => {
|
||||
},
|
||||
outputType: 'string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const serialized = serializer.serializeWorkflow(blocks, []);
|
||||
const block = serialized.blocks[0];
|
||||
const serialized = serializer.serializeWorkflow(blocks, [])
|
||||
const block = serialized.blocks[0]
|
||||
|
||||
expect(block.id).toBe('minimal-1');
|
||||
expect(block.config.tool).toBe('openai.chat');
|
||||
expect(block.config.params).toEqual({ model: 'gpt-4o' });
|
||||
});
|
||||
expect(block.id).toBe('minimal-1')
|
||||
expect(block.config.tool).toBe('openai.chat')
|
||||
expect(block.config.params).toEqual({ model: 'gpt-4o' })
|
||||
})
|
||||
|
||||
it('should handle complex workflow with multiple interconnected blocks', () => {
|
||||
const blocks: Record<string, BlockState> = {
|
||||
@@ -249,7 +249,7 @@ describe('Serializer', () => {
|
||||
},
|
||||
outputType: 'json'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const connections: Edge[] = [
|
||||
{
|
||||
@@ -266,22 +266,22 @@ describe('Serializer', () => {
|
||||
sourceHandle: 'result',
|
||||
targetHandle: 'body'
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
const serialized = serializer.serializeWorkflow(blocks, connections);
|
||||
const serialized = serializer.serializeWorkflow(blocks, connections)
|
||||
|
||||
// Verify workflow structure
|
||||
expect(serialized.blocks).toHaveLength(3);
|
||||
expect(serialized.connections).toHaveLength(2);
|
||||
expect(serialized.blocks).toHaveLength(3)
|
||||
expect(serialized.connections).toHaveLength(2)
|
||||
|
||||
// Verify data flow chain
|
||||
const conn1 = serialized.connections[0];
|
||||
const conn2 = serialized.connections[1];
|
||||
expect(conn1.source).toBe('input-1');
|
||||
expect(conn1.target).toBe('process-1');
|
||||
expect(conn2.source).toBe('process-1');
|
||||
expect(conn2.target).toBe('output-1');
|
||||
});
|
||||
const conn1 = serialized.connections[0]
|
||||
const conn2 = serialized.connections[1]
|
||||
expect(conn1.source).toBe('input-1')
|
||||
expect(conn1.target).toBe('process-1')
|
||||
expect(conn2.source).toBe('process-1')
|
||||
expect(conn2.target).toBe('output-1')
|
||||
})
|
||||
|
||||
it('should preserve tool-specific parameters', () => {
|
||||
const blocks: Record<string, BlockState> = {
|
||||
@@ -309,19 +309,19 @@ describe('Serializer', () => {
|
||||
},
|
||||
outputType: 'string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const serialized = serializer.serializeWorkflow(blocks, []);
|
||||
const block = serialized.blocks[0];
|
||||
const serialized = serializer.serializeWorkflow(blocks, [])
|
||||
const block = serialized.blocks[0]
|
||||
|
||||
expect(block.config.tool).toBe('openai.chat');
|
||||
expect(block.config.tool).toBe('openai.chat')
|
||||
expect(block.config.params).toEqual({
|
||||
model: 'gpt-4o',
|
||||
temperature: 0.7,
|
||||
maxTokens: 1000
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('deserializeWorkflow', () => {
|
||||
it('should deserialize a workflow back to blocks and connections', () => {
|
||||
@@ -345,15 +345,15 @@ describe('Serializer', () => {
|
||||
}
|
||||
],
|
||||
connections: []
|
||||
};
|
||||
}
|
||||
|
||||
const { blocks } = serializer.deserializeWorkflow(workflow);
|
||||
const block = blocks['agent-1'];
|
||||
const { blocks } = serializer.deserializeWorkflow(workflow)
|
||||
const block = blocks['agent-1']
|
||||
|
||||
expect(block.type).toBe('agent');
|
||||
expect(block.subBlocks.model.value).toBe('gpt-4o');
|
||||
expect(block.subBlocks.systemPrompt.value).toBe('You are helpful');
|
||||
expect(block.outputType).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(block.type).toBe('agent')
|
||||
expect(block.subBlocks.model.value).toBe('gpt-4o')
|
||||
expect(block.subBlocks.systemPrompt.value).toBe('You are helpful')
|
||||
expect(block.outputType).toBe('string')
|
||||
})
|
||||
})
|
||||
})
|
||||
+32
-32
@@ -1,8 +1,8 @@
|
||||
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';
|
||||
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 {
|
||||
@@ -15,33 +15,33 @@ export class Serializer {
|
||||
sourceHandle: conn.sourceHandle || undefined,
|
||||
targetHandle: conn.targetHandle || undefined
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private serializeBlock(block: BlockState): SerializedBlock {
|
||||
const blockConfig = getBlock(block.type);
|
||||
const blockConfig = getBlock(block.type)
|
||||
if (!blockConfig) {
|
||||
throw new Error(`Block configuration not found for type: ${block.type}`);
|
||||
throw new Error(`Block configuration not found for type: ${block.type}`)
|
||||
}
|
||||
|
||||
// Get the tool ID from the block's configuration
|
||||
const tools = blockConfig.tools;
|
||||
const tools = blockConfig.tools
|
||||
if (!tools?.access || tools.access.length === 0) {
|
||||
throw new Error(`No tools specified for block type: ${block.type}`);
|
||||
throw new Error(`No tools specified for block type: ${block.type}`)
|
||||
}
|
||||
|
||||
// Get all values from subBlocks
|
||||
const params: Record<string, any> = {};
|
||||
const params: Record<string, any> = {}
|
||||
Object.entries(block.subBlocks || {}).forEach(([id, subBlock]) => {
|
||||
if (subBlock?.value !== undefined) {
|
||||
params[id] = subBlock.value;
|
||||
params[id] = subBlock.value
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Get the tool ID from the block's configuration
|
||||
const toolId = tools.config?.tool?.(params) || params.tool || tools.access[0];
|
||||
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}`);
|
||||
throw new Error(`Invalid or unauthorized tool: ${toolId}`)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -57,18 +57,18 @@ export class Serializer {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
deserializeWorkflow(serialized: SerializedWorkflow): {
|
||||
blocks: Record<string, BlockState>;
|
||||
connections: Edge[];
|
||||
blocks: Record<string, BlockState>
|
||||
connections: Edge[]
|
||||
} {
|
||||
const blocks: Record<string, BlockState> = {};
|
||||
const blocks: Record<string, BlockState> = {}
|
||||
serialized.blocks.forEach(block => {
|
||||
const deserialized = this.deserializeBlock(block);
|
||||
blocks[deserialized.id] = deserialized;
|
||||
});
|
||||
const deserialized = this.deserializeBlock(block)
|
||||
blocks[deserialized.id] = deserialized
|
||||
})
|
||||
|
||||
return {
|
||||
blocks,
|
||||
@@ -79,20 +79,20 @@ export class Serializer {
|
||||
sourceHandle: conn.sourceHandle || null,
|
||||
targetHandle: conn.targetHandle || null
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private deserializeBlock(serialized: SerializedBlock): BlockState {
|
||||
const toolId = serialized.config.tool;
|
||||
const blockType = getBlockTypeForTool(toolId);
|
||||
const toolId = serialized.config.tool
|
||||
const blockType = getBlockTypeForTool(toolId)
|
||||
|
||||
if (!blockType) {
|
||||
throw new Error(`Could not determine block type for tool: ${toolId}`);
|
||||
throw new Error(`Could not determine block type for tool: ${toolId}`)
|
||||
}
|
||||
|
||||
const blockConfig = getBlock(blockType);
|
||||
const blockConfig = getBlock(blockType)
|
||||
if (!blockConfig) {
|
||||
throw new Error(`Block configuration not found for type: ${blockType}`);
|
||||
throw new Error(`Block configuration not found for type: ${blockType}`)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -101,15 +101,15 @@ export class Serializer {
|
||||
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);
|
||||
const subBlock = blockConfig.workflow.subBlocks?.find(sb => sb.id === key)
|
||||
acc[key] = {
|
||||
id: key,
|
||||
type: subBlock?.type || 'short-input',
|
||||
value: value
|
||||
};
|
||||
return acc;
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, SubBlockState>),
|
||||
outputType: serialized.config.interface.outputs.output as OutputType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-23
@@ -1,39 +1,39 @@
|
||||
export interface SerializedWorkflow {
|
||||
version: string;
|
||||
blocks: SerializedBlock[];
|
||||
connections: SerializedConnection[];
|
||||
version: string
|
||||
blocks: SerializedBlock[]
|
||||
connections: SerializedConnection[]
|
||||
}
|
||||
|
||||
export interface SerializedConnection {
|
||||
source: string;
|
||||
target: string;
|
||||
sourceHandle?: string;
|
||||
targetHandle?: string;
|
||||
source: string
|
||||
target: string
|
||||
sourceHandle?: string
|
||||
targetHandle?: string
|
||||
}
|
||||
|
||||
export interface Position {
|
||||
x: number;
|
||||
y: number;
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface BlockConfig {
|
||||
tool: string;
|
||||
params: Record<string, any>;
|
||||
tool: string
|
||||
params: Record<string, any>
|
||||
interface: {
|
||||
inputs: Record<string, string>;
|
||||
outputs: Record<string, string>;
|
||||
};
|
||||
inputs: Record<string, string>
|
||||
outputs: Record<string, string>
|
||||
}
|
||||
}
|
||||
|
||||
export interface SerializedBlock {
|
||||
id: string;
|
||||
position: Position;
|
||||
config: BlockConfig;
|
||||
id: string
|
||||
position: Position
|
||||
config: BlockConfig
|
||||
metadata?: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
category?: string;
|
||||
icon?: string;
|
||||
color?: string;
|
||||
};
|
||||
title?: string
|
||||
description?: string
|
||||
category?: string
|
||||
icon?: string
|
||||
color?: string
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user