mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
feat(execution-filesystem): system to pass files between blocks (#866)
* feat(files): pass files between blocks * presigned URL for downloads * Remove latest migration before merge * starter block file upload wasn't getting logged * checkpoint in human readable form * checkpoint files / file type outputs * file downloads working for block outputs * checkpoint file download * fix type issues * remove filereference interface with simpler user file interface * show files in the tag dropdown for start block * more migration to simple url object, reduce presigned time to 5 min * Remove migration 0065_parallel_nightmare and related files - Deleted apps/sim/db/migrations/0065_parallel_nightmare.sql - Deleted apps/sim/db/migrations/meta/0065_snapshot.json - Removed 0065 entry from apps/sim/db/migrations/meta/_journal.json Preparing for merge with origin/staging and migration regeneration * add migration files * fix tests * Update apps/sim/lib/uploads/setup.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update apps/sim/lib/workflows/execution-file-storage.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update apps/sim/lib/workflows/execution-file-storage.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * cleanup types * fix lint * fix logs typing for file refs * open download in new tab * fixed * Update apps/sim/tools/index.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * fix file block * cleanup unused code * fix bugs * remove hacky file id logic * fix drag and drop * fix tests --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
75963eb851
commit
de93e167af
@@ -87,6 +87,7 @@ export class Executor {
|
||||
edges?: Array<{ source: string; target: string }>
|
||||
onStream?: (streamingExecution: StreamingExecution) => Promise<void>
|
||||
executionId?: string
|
||||
workspaceId?: string
|
||||
}
|
||||
},
|
||||
private initialBlockStates: Record<string, BlockOutput> = {},
|
||||
@@ -675,6 +676,8 @@ export class Executor {
|
||||
): ExecutionContext {
|
||||
const context: ExecutionContext = {
|
||||
workflowId,
|
||||
workspaceId: this.contextExtensions.workspaceId,
|
||||
executionId: this.contextExtensions.executionId,
|
||||
blockStates: new Map(),
|
||||
blockLogs: [],
|
||||
metadata: {
|
||||
@@ -797,6 +800,11 @@ export class Executor {
|
||||
...finalInput, // Add input fields directly at top level
|
||||
}
|
||||
|
||||
// Add files if present (for all trigger types)
|
||||
if (this.workflowInput?.files && Array.isArray(this.workflowInput.files)) {
|
||||
blockOutput.files = this.workflowInput.files
|
||||
}
|
||||
|
||||
logger.info(`[Executor] Starting block output:`, JSON.stringify(blockOutput, null, 2))
|
||||
|
||||
context.blockStates.set(initBlock.id, {
|
||||
@@ -804,6 +812,10 @@ export class Executor {
|
||||
executed: true,
|
||||
executionTime: 0,
|
||||
})
|
||||
|
||||
// Create a block log for the starter block if it has files
|
||||
// This ensures files are captured in trace spans and execution logs
|
||||
this.createStartedBlockWithFilesLog(initBlock, blockOutput, context)
|
||||
} else {
|
||||
// Handle structured input (like API calls or chat messages)
|
||||
if (this.workflowInput && typeof this.workflowInput === 'object') {
|
||||
@@ -812,17 +824,26 @@ export class Executor {
|
||||
Object.hasOwn(this.workflowInput, 'input') &&
|
||||
Object.hasOwn(this.workflowInput, 'conversationId')
|
||||
) {
|
||||
// Chat workflow: extract input and conversationId to root level
|
||||
const starterOutput = {
|
||||
// Chat workflow: extract input, conversationId, and files to root level
|
||||
const starterOutput: any = {
|
||||
input: this.workflowInput.input,
|
||||
conversationId: this.workflowInput.conversationId,
|
||||
}
|
||||
|
||||
// Add files if present
|
||||
if (this.workflowInput.files && Array.isArray(this.workflowInput.files)) {
|
||||
starterOutput.files = this.workflowInput.files
|
||||
}
|
||||
|
||||
context.blockStates.set(initBlock.id, {
|
||||
output: starterOutput,
|
||||
executed: true,
|
||||
executionTime: 0,
|
||||
})
|
||||
|
||||
// Create a block log for the starter block if it has files
|
||||
// This ensures files are captured in trace spans and execution logs
|
||||
this.createStartedBlockWithFilesLog(initBlock, starterOutput, context)
|
||||
} else {
|
||||
// API workflow: spread the raw data directly (no wrapping)
|
||||
const starterOutput = { ...this.workflowInput }
|
||||
@@ -857,11 +878,16 @@ export class Executor {
|
||||
Object.hasOwn(this.workflowInput, 'input') &&
|
||||
Object.hasOwn(this.workflowInput, 'conversationId')
|
||||
) {
|
||||
// Chat workflow: extract input and conversationId to root level
|
||||
// Chat workflow: extract input, conversationId, and files to root level
|
||||
blockOutput = {
|
||||
input: this.workflowInput.input,
|
||||
conversationId: this.workflowInput.conversationId,
|
||||
}
|
||||
|
||||
// Add files if present
|
||||
if (this.workflowInput.files && Array.isArray(this.workflowInput.files)) {
|
||||
blockOutput.files = this.workflowInput.files
|
||||
}
|
||||
} else {
|
||||
// API workflow: spread the raw data directly (no wrapping)
|
||||
blockOutput = { ...this.workflowInput }
|
||||
@@ -883,6 +909,7 @@ export class Executor {
|
||||
executed: true,
|
||||
executionTime: 0,
|
||||
})
|
||||
this.createStartedBlockWithFilesLog(initBlock, blockOutput, context)
|
||||
}
|
||||
// Ensure the starting block is in the active execution path
|
||||
context.activeExecutionPath.add(initBlock.id)
|
||||
@@ -1806,4 +1833,29 @@ export class Executor {
|
||||
// Fallback to string conversion
|
||||
return String(error)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block log for the starter block if it contains files.
|
||||
* This ensures files are captured in trace spans and execution logs.
|
||||
*/
|
||||
private createStartedBlockWithFilesLog(
|
||||
initBlock: SerializedBlock,
|
||||
blockOutput: any,
|
||||
context: ExecutionContext
|
||||
): void {
|
||||
if (blockOutput.files && Array.isArray(blockOutput.files) && blockOutput.files.length > 0) {
|
||||
const starterBlockLog: BlockLog = {
|
||||
blockId: initBlock.id,
|
||||
blockName: initBlock.metadata?.name || 'Start',
|
||||
blockType: initBlock.metadata?.id || 'start',
|
||||
startedAt: new Date().toISOString(),
|
||||
endedAt: new Date().toISOString(),
|
||||
success: true,
|
||||
input: this.workflowInput,
|
||||
output: blockOutput,
|
||||
durationMs: 0,
|
||||
}
|
||||
context.blockLogs.push(starterBlockLog)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user