mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
improvement(executor): redesign executor + add start block (#1790)
* fix(billing): should allow restoring subscription (#1728) * fix(already-cancelled-sub): UI should allow restoring subscription * restore functionality fixed * fix * improvement(start): revert to start block * make it work with start block * fix start block persistence * cleanup triggers * debounce status checks * update docs * improvement(start): revert to start block * make it work with start block * fix start block persistence * cleanup triggers * debounce status checks * update docs * SSE v0.1 * v0.2 * v0.3 * v0.4 * v0.5 * v0.6 * broken checkpoint * Executor progress - everything preliminarily tested except while loops and triggers * Executor fixes * Fix var typing * Implement while loop execution * Loop and parallel result agg * Refactor v1 - loops work * Fix var resolution in for each loop * Fix while loop condition and variable resolution * Fix loop iteration counts * Fix loop badges * Clean logs * Fix variable references from start block * Fix condition block * Fix conditional convergence * Dont execute orphaned nodse * Code cleanup 1 and error surfacing * compile time try catch * Some fixes * Fix error throwing * Sentinels v1 * Fix multiple start and end nodes in loop * Edge restoration * Fix reachable nodes execution * Parallel subflows * Fix loop/parallel sentinel convergence * Loops and parallels orchestrator * Split executor * Variable resolution split * Dag phase * Refactor * Refactor * Refactor 3 * Lint + refactor * Lint + cleanup + refactor * Readability * Initial logs * Fix trace spans * Console pills for iters * Add input/output pills * Checkpoint * remove unused code * THIS IS THE COMMIT THAT CAN BREAK A LOT OF THINGS * ANOTHER BIG REFACTOR * Lint + fix tests * Fix webhook * Remove comment * Merge stash * Fix triggers? * Stuff * Fix error port * Lint * Consolidate state * Clean up some var resolution * Remove some var resolution logs * Fix chat * Fix chat triggers * Fix chat trigger fully * Snapshot refactor * Fix mcp and custom tools * Lint * Fix parallel default count and trace span overlay * Agent purple * Fix test * Fix test --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
This commit is contained in:
committed by
GitHub
parent
7d67ae397d
commit
3bf00cbd2a
@@ -1,39 +1,335 @@
|
||||
/**
|
||||
* Enum defining all supported block types in the executor.
|
||||
* This centralizes block type definitions and eliminates magic strings.
|
||||
* Central constants and types for the executor
|
||||
*
|
||||
* Consolidates all magic strings, block types, edge handles, and type definitions
|
||||
* used throughout the executor to eliminate duplication and improve type safety.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Block types
|
||||
*/
|
||||
export enum BlockType {
|
||||
// Control flow
|
||||
PARALLEL = 'parallel',
|
||||
LOOP = 'loop',
|
||||
ROUTER = 'router',
|
||||
CONDITION = 'condition',
|
||||
|
||||
// Triggers
|
||||
START_TRIGGER = 'start_trigger',
|
||||
STARTER = 'starter',
|
||||
TRIGGER = 'trigger',
|
||||
|
||||
// Data processing
|
||||
FUNCTION = 'function',
|
||||
AGENT = 'agent',
|
||||
API = 'api',
|
||||
EVALUATOR = 'evaluator',
|
||||
RESPONSE = 'response',
|
||||
WORKFLOW = 'workflow', // Deprecated - kept for backwards compatibility
|
||||
WORKFLOW_INPUT = 'workflow_input', // Current workflow block type
|
||||
STARTER = 'starter',
|
||||
VARIABLES = 'variables',
|
||||
|
||||
// I/O
|
||||
RESPONSE = 'response',
|
||||
WORKFLOW = 'workflow',
|
||||
WORKFLOW_INPUT = 'workflow_input',
|
||||
|
||||
// Utilities
|
||||
WAIT = 'wait',
|
||||
|
||||
// Infrastructure (virtual blocks)
|
||||
SENTINEL_START = 'sentinel_start',
|
||||
SENTINEL_END = 'sentinel_end',
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of all block types for iteration and validation
|
||||
* Trigger block types (blocks that can start a workflow)
|
||||
*/
|
||||
export const ALL_BLOCK_TYPES = Object.values(BlockType) as string[]
|
||||
export const TRIGGER_BLOCK_TYPES = [
|
||||
BlockType.START_TRIGGER,
|
||||
BlockType.STARTER,
|
||||
BlockType.TRIGGER,
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Type guard to check if a string is a valid block type
|
||||
* Metadata-only block types (not executable, just configuration)
|
||||
*/
|
||||
export function isValidBlockType(type: string): type is BlockType {
|
||||
return ALL_BLOCK_TYPES.includes(type)
|
||||
export const METADATA_ONLY_BLOCK_TYPES = [BlockType.LOOP, BlockType.PARALLEL] as const
|
||||
|
||||
/**
|
||||
* Loop types
|
||||
*/
|
||||
export type LoopType = 'for' | 'forEach' | 'while' | 'doWhile'
|
||||
|
||||
/**
|
||||
* Sentinel types
|
||||
*/
|
||||
export type SentinelType = 'start' | 'end'
|
||||
|
||||
/**
|
||||
* Parallel types
|
||||
*/
|
||||
export type ParallelType = 'collection' | 'count'
|
||||
|
||||
export const EDGE = {
|
||||
CONDITION_PREFIX: 'condition-',
|
||||
CONDITION_TRUE: 'condition-true',
|
||||
CONDITION_FALSE: 'condition-false',
|
||||
ROUTER_PREFIX: 'router-',
|
||||
LOOP_CONTINUE: 'loop_continue',
|
||||
LOOP_CONTINUE_ALT: 'loop-continue-source',
|
||||
LOOP_EXIT: 'loop_exit',
|
||||
ERROR: 'error',
|
||||
SOURCE: 'source',
|
||||
DEFAULT: 'default',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Loop configuration
|
||||
*/
|
||||
export const LOOP = {
|
||||
// Loop types
|
||||
TYPE: {
|
||||
FOR: 'for' as LoopType,
|
||||
FOR_EACH: 'forEach' as LoopType,
|
||||
WHILE: 'while' as LoopType,
|
||||
DO_WHILE: 'doWhile',
|
||||
},
|
||||
|
||||
// Sentinel node naming
|
||||
SENTINEL: {
|
||||
PREFIX: 'loop-',
|
||||
START_SUFFIX: '-sentinel-start',
|
||||
END_SUFFIX: '-sentinel-end',
|
||||
START_TYPE: 'start' as SentinelType,
|
||||
END_TYPE: 'end' as SentinelType,
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Parallel configuration
|
||||
*/
|
||||
export const PARALLEL = {
|
||||
// Parallel types
|
||||
TYPE: {
|
||||
COLLECTION: 'collection' as ParallelType,
|
||||
COUNT: 'count' as ParallelType,
|
||||
},
|
||||
|
||||
// Branch notation
|
||||
BRANCH: {
|
||||
PREFIX: '₍',
|
||||
SUFFIX: '₎',
|
||||
},
|
||||
|
||||
// Default values
|
||||
DEFAULT_COUNT: 1,
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Reference syntax for variable resolution
|
||||
*/
|
||||
export const REFERENCE = {
|
||||
START: '<',
|
||||
END: '>',
|
||||
PATH_DELIMITER: '.',
|
||||
ENV_VAR_START: '{{',
|
||||
ENV_VAR_END: '}}',
|
||||
PREFIX: {
|
||||
LOOP: 'loop',
|
||||
PARALLEL: 'parallel',
|
||||
VARIABLE: 'variable',
|
||||
},
|
||||
} as const
|
||||
|
||||
export const SPECIAL_REFERENCE_PREFIXES = [
|
||||
REFERENCE.PREFIX.LOOP,
|
||||
REFERENCE.PREFIX.PARALLEL,
|
||||
REFERENCE.PREFIX.VARIABLE,
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Loop reference fields
|
||||
*/
|
||||
export const LOOP_REFERENCE = {
|
||||
ITERATION: 'iteration',
|
||||
INDEX: 'index',
|
||||
ITEM: 'item',
|
||||
INDEX_PATH: 'loop.index',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Parallel reference fields
|
||||
*/
|
||||
export const PARALLEL_REFERENCE = {
|
||||
INDEX: 'index',
|
||||
CURRENT_ITEM: 'currentItem',
|
||||
ITEMS: 'items',
|
||||
} as const
|
||||
|
||||
export const DEFAULTS = {
|
||||
BLOCK_TYPE: 'unknown',
|
||||
BLOCK_TITLE: 'Untitled Block',
|
||||
WORKFLOW_NAME: 'Workflow',
|
||||
MAX_LOOP_ITERATIONS: 1000,
|
||||
MAX_WORKFLOW_DEPTH: 10,
|
||||
EXECUTION_TIME: 0,
|
||||
TOKENS: {
|
||||
PROMPT: 0,
|
||||
COMPLETION: 0,
|
||||
TOTAL: 0,
|
||||
},
|
||||
COST: {
|
||||
INPUT: 0,
|
||||
OUTPUT: 0,
|
||||
TOTAL: 0,
|
||||
},
|
||||
} as const
|
||||
|
||||
export const HTTP = {
|
||||
STATUS: {
|
||||
OK: 200,
|
||||
FORBIDDEN: 403,
|
||||
NOT_FOUND: 404,
|
||||
TOO_MANY_REQUESTS: 429,
|
||||
SERVER_ERROR: 500,
|
||||
},
|
||||
CONTENT_TYPE: {
|
||||
JSON: 'application/json',
|
||||
EVENT_STREAM: 'text/event-stream',
|
||||
},
|
||||
} as const
|
||||
|
||||
export const AGENT = {
|
||||
DEFAULT_MODEL: 'gpt-4o',
|
||||
DEFAULT_FUNCTION_TIMEOUT: 5000,
|
||||
REQUEST_TIMEOUT: 120000,
|
||||
CUSTOM_TOOL_PREFIX: 'custom_',
|
||||
} as const
|
||||
|
||||
export const ROUTER = {
|
||||
DEFAULT_MODEL: 'gpt-4o',
|
||||
DEFAULT_TEMPERATURE: 0,
|
||||
INFERENCE_TEMPERATURE: 0.1,
|
||||
} as const
|
||||
|
||||
export const EVALUATOR = {
|
||||
DEFAULT_MODEL: 'gpt-4o',
|
||||
DEFAULT_TEMPERATURE: 0.1,
|
||||
RESPONSE_SCHEMA_NAME: 'evaluation_response',
|
||||
JSON_INDENT: 2,
|
||||
} as const
|
||||
|
||||
export const CONDITION = {
|
||||
ELSE_LABEL: 'else',
|
||||
ELSE_TITLE: 'else',
|
||||
} as const
|
||||
|
||||
export const PARSING = {
|
||||
JSON_RADIX: 10,
|
||||
PREVIEW_LENGTH: 200,
|
||||
PREVIEW_SUFFIX: '...',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Condition configuration
|
||||
*/
|
||||
export interface ConditionConfig {
|
||||
id: string
|
||||
label?: string
|
||||
condition: string
|
||||
}
|
||||
|
||||
export function isTriggerBlockType(blockType: string | undefined): boolean {
|
||||
return TRIGGER_BLOCK_TYPES.includes(blockType as any)
|
||||
}
|
||||
|
||||
export function isMetadataOnlyBlockType(blockType: string | undefined): boolean {
|
||||
return METADATA_ONLY_BLOCK_TYPES.includes(blockType as any)
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to check if a block type is a workflow block (current or deprecated)
|
||||
*/
|
||||
export function isWorkflowBlockType(blockType: string | undefined): boolean {
|
||||
return blockType === BlockType.WORKFLOW || blockType === BlockType.WORKFLOW_INPUT
|
||||
}
|
||||
|
||||
export function isSentinelBlockType(blockType: string | undefined): boolean {
|
||||
return blockType === BlockType.SENTINEL_START || blockType === BlockType.SENTINEL_END
|
||||
}
|
||||
|
||||
export function isConditionBlockType(blockType: string | undefined): boolean {
|
||||
return blockType === BlockType.CONDITION
|
||||
}
|
||||
|
||||
export function isRouterBlockType(blockType: string | undefined): boolean {
|
||||
return blockType === BlockType.ROUTER
|
||||
}
|
||||
|
||||
export function isAgentBlockType(blockType: string | undefined): boolean {
|
||||
return blockType === BlockType.AGENT
|
||||
}
|
||||
|
||||
export function getDefaultTokens() {
|
||||
return {
|
||||
prompt: DEFAULTS.TOKENS.PROMPT,
|
||||
completion: DEFAULTS.TOKENS.COMPLETION,
|
||||
total: DEFAULTS.TOKENS.TOTAL,
|
||||
}
|
||||
}
|
||||
|
||||
export function getDefaultCost() {
|
||||
return {
|
||||
input: DEFAULTS.COST.INPUT,
|
||||
output: DEFAULTS.COST.OUTPUT,
|
||||
total: DEFAULTS.COST.TOTAL,
|
||||
}
|
||||
}
|
||||
|
||||
export function buildReference(path: string): string {
|
||||
return `${REFERENCE.START}${path}${REFERENCE.END}`
|
||||
}
|
||||
|
||||
export function buildLoopReference(property: string): string {
|
||||
return buildReference(`${REFERENCE.PREFIX.LOOP}${REFERENCE.PATH_DELIMITER}${property}`)
|
||||
}
|
||||
|
||||
export function buildParallelReference(property: string): string {
|
||||
return buildReference(`${REFERENCE.PREFIX.PARALLEL}${REFERENCE.PATH_DELIMITER}${property}`)
|
||||
}
|
||||
|
||||
export function buildVariableReference(variableName: string): string {
|
||||
return buildReference(`${REFERENCE.PREFIX.VARIABLE}${REFERENCE.PATH_DELIMITER}${variableName}`)
|
||||
}
|
||||
|
||||
export function buildBlockReference(blockId: string, path?: string): string {
|
||||
return buildReference(path ? `${blockId}${REFERENCE.PATH_DELIMITER}${path}` : blockId)
|
||||
}
|
||||
|
||||
export function buildLoopIndexCondition(maxIterations: number): string {
|
||||
return `${buildLoopReference(LOOP_REFERENCE.INDEX)} < ${maxIterations}`
|
||||
}
|
||||
|
||||
export function buildEnvVarReference(varName: string): string {
|
||||
return `${REFERENCE.ENV_VAR_START}${varName}${REFERENCE.ENV_VAR_END}`
|
||||
}
|
||||
|
||||
export function isReference(value: string): boolean {
|
||||
return value.startsWith(REFERENCE.START) && value.endsWith(REFERENCE.END)
|
||||
}
|
||||
|
||||
export function isEnvVarReference(value: string): boolean {
|
||||
return value.startsWith(REFERENCE.ENV_VAR_START) && value.endsWith(REFERENCE.ENV_VAR_END)
|
||||
}
|
||||
|
||||
export function extractEnvVarName(reference: string): string {
|
||||
return reference.substring(
|
||||
REFERENCE.ENV_VAR_START.length,
|
||||
reference.length - REFERENCE.ENV_VAR_END.length
|
||||
)
|
||||
}
|
||||
|
||||
export function extractReferenceContent(reference: string): string {
|
||||
return reference.substring(REFERENCE.START.length, reference.length - REFERENCE.END.length)
|
||||
}
|
||||
|
||||
export function parseReferencePath(reference: string): string[] {
|
||||
const content = extractReferenceContent(reference)
|
||||
return content.split(REFERENCE.PATH_DELIMITER)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user