mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
Moved block log initilization earlier in executor, before inputs are resolved. Throw errors instead of warnings at runtime during execution
This commit is contained in:
+93
-95
@@ -117,13 +117,51 @@ export class Executor {
|
||||
throw new Error(`Missing block ${blockId}`)
|
||||
}
|
||||
|
||||
// Resolve template references in block config params
|
||||
const resolvedInputs = this.resolveInputs(block, context)
|
||||
// Skip disabled blocks
|
||||
if (block.enabled === false) {
|
||||
return { response: {} }
|
||||
}
|
||||
|
||||
// Execute the block, store the result
|
||||
const output = await this.executeBlock(block, resolvedInputs, context)
|
||||
context.blockStates.set(block.id, output)
|
||||
return output
|
||||
// Prepare a new blockLog entry
|
||||
const blockLog: Partial<BlockLog> = {
|
||||
blockId: block.id,
|
||||
blockTitle: block.metadata?.title,
|
||||
blockType: getBlockTypeForTool(block.config.tool || ''),
|
||||
startedAt: new Date().toISOString(),
|
||||
}
|
||||
|
||||
try {
|
||||
// Resolve template references in block config params
|
||||
const resolvedInputs = this.resolveInputs(block, context)
|
||||
|
||||
// Execute the block, store the result
|
||||
const output = await this.executeBlock(block, resolvedInputs, context)
|
||||
context.blockStates.set(block.id, output)
|
||||
|
||||
// Update block log with success
|
||||
blockLog.success = true
|
||||
blockLog.output = output.response
|
||||
return output
|
||||
} catch (error) {
|
||||
// Update block log with error
|
||||
blockLog.success = false
|
||||
blockLog.error = error instanceof Error ? error.message : 'Unknown error'
|
||||
throw error
|
||||
} finally {
|
||||
// Compute the end time and duration
|
||||
const end = new Date()
|
||||
blockLog.endedAt = end.toISOString()
|
||||
|
||||
if (blockLog.startedAt) {
|
||||
const started = new Date(blockLog.startedAt).getTime()
|
||||
blockLog.durationMs = end.getTime() - started
|
||||
} else {
|
||||
blockLog.durationMs = 0
|
||||
}
|
||||
|
||||
// Push the log entry
|
||||
context.blockLogs.push(blockLog as BlockLog)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
@@ -186,92 +224,57 @@ export class Executor {
|
||||
...inputs,
|
||||
})
|
||||
|
||||
// Get the block type from the tool ID using the helper function
|
||||
const blockType = getBlockTypeForTool(toolId)
|
||||
|
||||
// Prepare a new blockLog entry
|
||||
const blockLog: Partial<BlockLog> = {
|
||||
blockId: block.id,
|
||||
blockTitle: block.metadata?.title || 'Unnamed Block',
|
||||
blockType: blockType,
|
||||
startedAt: new Date().toISOString(),
|
||||
if (!tool.request) {
|
||||
throw new Error(`Tool "${toolId}" has no request config.`)
|
||||
}
|
||||
|
||||
try {
|
||||
if (!tool.request) {
|
||||
throw new Error(`Tool "${toolId}" has no request config.`)
|
||||
}
|
||||
const { url: urlOrFn, method: defaultMethod, headers: headersFn, body: bodyFn } =
|
||||
tool.request
|
||||
|
||||
const { url: urlOrFn, method: defaultMethod, headers: headersFn, body: bodyFn } =
|
||||
tool.request
|
||||
// Build the URL
|
||||
const url = typeof urlOrFn === 'function' ? urlOrFn(validatedParams) : urlOrFn
|
||||
// Determine HTTP method
|
||||
const methodFromParams =
|
||||
typeof validatedParams.method === 'object'
|
||||
? validatedParams.method.method
|
||||
: validatedParams.method
|
||||
const method = methodFromParams || defaultMethod || 'GET'
|
||||
|
||||
// Build the URL
|
||||
const url = typeof urlOrFn === 'function' ? urlOrFn(validatedParams) : urlOrFn
|
||||
// Determine HTTP method
|
||||
const methodFromParams =
|
||||
typeof validatedParams.method === 'object'
|
||||
? validatedParams.method.method
|
||||
: validatedParams.method
|
||||
const method = methodFromParams || defaultMethod || 'GET'
|
||||
// Safely compute headers
|
||||
const headers = headersFn?.(validatedParams) ?? {}
|
||||
|
||||
// Safely compute headers
|
||||
const headers = headersFn?.(validatedParams) ?? {}
|
||||
// Build body if needed
|
||||
const bodyNeeded = method !== 'GET' && method !== 'HEAD' && !!bodyFn
|
||||
const body = bodyNeeded
|
||||
? JSON.stringify(bodyFn!(validatedParams))
|
||||
: undefined
|
||||
|
||||
// Build body if needed
|
||||
const bodyNeeded = method !== 'GET' && method !== 'HEAD' && !!bodyFn
|
||||
const body = bodyNeeded
|
||||
? JSON.stringify(bodyFn!(validatedParams))
|
||||
: undefined
|
||||
|
||||
// Perform fetch()
|
||||
const response = await fetch(url || '', { method, headers, body })
|
||||
if (!response.ok) {
|
||||
// In case there is a custom transformError
|
||||
const transformError = tool.transformError ?? (() => 'Unknown error')
|
||||
const errorBody = await response.json().catch(() => ({
|
||||
message: response.statusText,
|
||||
}))
|
||||
throw new Error(transformError(errorBody))
|
||||
}
|
||||
|
||||
// Transform the response
|
||||
const transformResponse =
|
||||
tool.transformResponse ??
|
||||
(async (resp: Response) => ({
|
||||
success: true,
|
||||
output: await resp.json(),
|
||||
}))
|
||||
|
||||
const result = await transformResponse(response)
|
||||
if (!result.success) {
|
||||
const transformError = tool.transformError ?? (() => 'Tool returned an error object')
|
||||
throw new Error(transformError(result))
|
||||
}
|
||||
|
||||
// Success: update the blockLog with success & output
|
||||
blockLog.success = true
|
||||
blockLog.output = result.output
|
||||
|
||||
return { response: result.output }
|
||||
} catch (e) {
|
||||
blockLog.success = false
|
||||
blockLog.error = e instanceof Error ? e.message : 'Unknown error'
|
||||
throw e
|
||||
} finally {
|
||||
// Compute the end time and duration
|
||||
const end = new Date()
|
||||
blockLog.endedAt = end.toISOString()
|
||||
|
||||
if (blockLog.startedAt) {
|
||||
const started = new Date(blockLog.startedAt).getTime()
|
||||
blockLog.durationMs = end.getTime() - started
|
||||
} else {
|
||||
blockLog.durationMs = 0
|
||||
}
|
||||
|
||||
// Push the log entry
|
||||
context.blockLogs.push(blockLog as BlockLog)
|
||||
// Perform fetch()
|
||||
const response = await fetch(url || '', { method, headers, body })
|
||||
if (!response.ok) {
|
||||
// In case there is a custom transformError
|
||||
const transformError = tool.transformError ?? (() => 'Unknown error')
|
||||
const errorBody = await response.json().catch(() => ({
|
||||
message: response.statusText,
|
||||
}))
|
||||
throw new Error(transformError(errorBody))
|
||||
}
|
||||
|
||||
// Transform the response
|
||||
const transformResponse =
|
||||
tool.transformResponse ??
|
||||
(async (resp: Response) => ({
|
||||
success: true,
|
||||
output: await resp.json(),
|
||||
}))
|
||||
|
||||
const result = await transformResponse(response)
|
||||
if (!result.success) {
|
||||
const transformError = tool.transformError ?? (() => 'Tool returned an error object')
|
||||
throw new Error(transformError(result))
|
||||
}
|
||||
|
||||
return { response: result.output }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,29 +331,24 @@ export class Executor {
|
||||
}
|
||||
|
||||
if (!sourceBlock) {
|
||||
console.warn(`Block reference "${blockRef}" not found by ID or name.`)
|
||||
continue
|
||||
throw new Error(`Block reference "${blockRef}" was not found.`)
|
||||
}
|
||||
|
||||
// Check if the referenced block is disabled.
|
||||
if (sourceBlock.enabled === false) {
|
||||
console.warn(`Block "${sourceBlock.metadata?.title}" is disabled, and block "${block.metadata?.title}" depends on it.`)
|
||||
continue
|
||||
throw new Error(`Block "${sourceBlock.metadata?.title}" is disabled, and block "${block.metadata?.title}" depends on it.`)
|
||||
}
|
||||
|
||||
const sourceState = context.blockStates.get(sourceBlock.id)
|
||||
if (!sourceState) {
|
||||
console.warn(`No state found for block ID "${sourceBlock.id}".`)
|
||||
continue
|
||||
throw new Error(`No state found for block "${sourceBlock.metadata?.title}" (ID: ${sourceBlock.id}).`)
|
||||
}
|
||||
|
||||
// Drill into the path
|
||||
let replacementValue: any = sourceState
|
||||
for (const part of pathParts) {
|
||||
if (!replacementValue || typeof replacementValue !== 'object') {
|
||||
console.warn(`Invalid path part "${part}" in "${path}".`)
|
||||
replacementValue = undefined
|
||||
break
|
||||
throw new Error(`Invalid path part "${part}" in "${path}" for block "${block.metadata?.title}".`)
|
||||
}
|
||||
replacementValue = replacementValue[part]
|
||||
}
|
||||
@@ -365,7 +363,7 @@ export class Executor {
|
||||
: String(replacementValue)
|
||||
)
|
||||
} else {
|
||||
console.warn(`No value found at path "${path}".`)
|
||||
throw new Error(`No value found at path "${path}" in block "${sourceBlock.metadata?.title}".`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user