diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx
index d9ef4fa7dc..ab93278422 100644
--- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/console/components/console-entry/console-entry.tsx
@@ -417,6 +417,14 @@ export function ConsoleEntry({ entry, consoleWidth }: ConsoleEntryProps) {
{entry.startedAt ? format(new Date(entry.startedAt), 'HH:mm:ss') : 'N/A'}
+ {/* Iteration tag - only show if iteration context exists */}
+ {entry.iterationCurrent !== undefined && entry.iterationTotal !== undefined && (
+
+
+ {entry.iterationCurrent}/{entry.iterationTotal}
+
+
+ )}
{/* Input/Output tags - only show if input data exists */}
{hasInputData && (
<>
diff --git a/apps/sim/executor/index.ts b/apps/sim/executor/index.ts
index 09410595fb..f5ee9d63f3 100644
--- a/apps/sim/executor/index.ts
+++ b/apps/sim/executor/index.ts
@@ -1508,6 +1508,43 @@ export class Executor {
// Skip console logging for infrastructure blocks like loops and parallels
// For streaming blocks, we'll add the console entry after stream processing
if (block.metadata?.id !== BlockType.LOOP && block.metadata?.id !== BlockType.PARALLEL) {
+ // Determine iteration context for this block
+ let iterationCurrent: number | undefined
+ let iterationTotal: number | undefined
+ let iterationType: 'loop' | 'parallel' | undefined
+ const blockName = block.metadata?.name || 'Unnamed Block'
+
+ if (parallelInfo) {
+ // This is a parallel iteration
+ const parallelState = context.parallelExecutions?.get(parallelInfo.parallelId)
+ iterationCurrent = parallelInfo.iterationIndex + 1
+ iterationTotal = parallelState?.parallelCount
+ iterationType = 'parallel'
+ } else {
+ // Check if this block is inside a loop
+ const containingLoopId = this.resolver.loopsByBlockId?.get(block.id)
+ if (containingLoopId) {
+ const currentIteration = context.loopIterations.get(containingLoopId)
+ const loop = context.workflow?.loops?.[containingLoopId]
+ if (currentIteration !== undefined && loop) {
+ iterationCurrent = currentIteration
+ if (loop.loopType === 'forEach') {
+ // For forEach loops, get the total from the items
+ const forEachItems = context.loopItems.get(`${containingLoopId}_items`)
+ if (forEachItems) {
+ iterationTotal = Array.isArray(forEachItems)
+ ? forEachItems.length
+ : Object.keys(forEachItems).length
+ }
+ } else {
+ // For regular loops, use the iterations count
+ iterationTotal = loop.iterations || 5
+ }
+ iterationType = 'loop'
+ }
+ }
+ }
+
addConsole({
input: blockLog.input,
output: blockLog.output,
@@ -1518,12 +1555,11 @@ export class Executor {
workflowId: context.workflowId,
blockId: parallelInfo ? blockId : block.id,
executionId: this.contextExtensions.executionId,
- blockName: parallelInfo
- ? `${block.metadata?.name || 'Unnamed Block'} (iteration ${
- parallelInfo.iterationIndex + 1
- })`
- : block.metadata?.name || 'Unnamed Block',
+ blockName,
blockType: block.metadata?.id || 'unknown',
+ iterationCurrent,
+ iterationTotal,
+ iterationType,
})
}
@@ -1578,6 +1614,43 @@ export class Executor {
// Skip console logging for infrastructure blocks like loops and parallels
if (block.metadata?.id !== BlockType.LOOP && block.metadata?.id !== BlockType.PARALLEL) {
+ // Determine iteration context for this block
+ let iterationCurrent: number | undefined
+ let iterationTotal: number | undefined
+ let iterationType: 'loop' | 'parallel' | undefined
+ const blockName = block.metadata?.name || 'Unnamed Block'
+
+ if (parallelInfo) {
+ // This is a parallel iteration
+ const parallelState = context.parallelExecutions?.get(parallelInfo.parallelId)
+ iterationCurrent = parallelInfo.iterationIndex + 1
+ iterationTotal = parallelState?.parallelCount
+ iterationType = 'parallel'
+ } else {
+ // Check if this block is inside a loop
+ const containingLoopId = this.resolver.getContainingLoopId(block.id)
+ if (containingLoopId) {
+ const currentIteration = context.loopIterations.get(containingLoopId)
+ const loop = context.workflow?.loops?.[containingLoopId]
+ if (currentIteration !== undefined && loop) {
+ iterationCurrent = currentIteration
+ if (loop.loopType === 'forEach') {
+ // For forEach loops, get the total from the items
+ const forEachItems = context.loopItems.get(`${containingLoopId}_items`)
+ if (forEachItems) {
+ iterationTotal = Array.isArray(forEachItems)
+ ? forEachItems.length
+ : Object.keys(forEachItems).length
+ }
+ } else {
+ // For regular loops, use the iterations count
+ iterationTotal = loop.iterations || 5
+ }
+ iterationType = 'loop'
+ }
+ }
+ }
+
addConsole({
input: blockLog.input,
output: blockLog.output,
@@ -1588,12 +1661,11 @@ export class Executor {
workflowId: context.workflowId,
blockId: parallelInfo ? blockId : block.id,
executionId: this.contextExtensions.executionId,
- blockName: parallelInfo
- ? `${block.metadata?.name || 'Unnamed Block'} (iteration ${
- parallelInfo.iterationIndex + 1
- })`
- : block.metadata?.name || 'Unnamed Block',
+ blockName,
blockType: block.metadata?.id || 'unknown',
+ iterationCurrent,
+ iterationTotal,
+ iterationType,
})
}
@@ -1649,6 +1721,43 @@ export class Executor {
// Skip console logging for infrastructure blocks like loops and parallels
if (block.metadata?.id !== BlockType.LOOP && block.metadata?.id !== BlockType.PARALLEL) {
+ // Determine iteration context for this block
+ let iterationCurrent: number | undefined
+ let iterationTotal: number | undefined
+ let iterationType: 'loop' | 'parallel' | undefined
+ const blockName = block.metadata?.name || 'Unnamed Block'
+
+ if (parallelInfo) {
+ // This is a parallel iteration
+ const parallelState = context.parallelExecutions?.get(parallelInfo.parallelId)
+ iterationCurrent = parallelInfo.iterationIndex + 1
+ iterationTotal = parallelState?.parallelCount
+ iterationType = 'parallel'
+ } else {
+ // Check if this block is inside a loop
+ const containingLoopId = this.resolver.getContainingLoopId(block.id)
+ if (containingLoopId) {
+ const currentIteration = context.loopIterations.get(containingLoopId)
+ const loop = context.workflow?.loops?.[containingLoopId]
+ if (currentIteration !== undefined && loop) {
+ iterationCurrent = currentIteration
+ if (loop.loopType === 'forEach') {
+ // For forEach loops, get the total from the items
+ const forEachItems = context.loopItems.get(`${containingLoopId}_items`)
+ if (forEachItems) {
+ iterationTotal = Array.isArray(forEachItems)
+ ? forEachItems.length
+ : Object.keys(forEachItems).length
+ }
+ } else {
+ // For regular loops, use the iterations count
+ iterationTotal = loop.iterations || 5
+ }
+ iterationType = 'loop'
+ }
+ }
+ }
+
addConsole({
input: blockLog.input,
output: {},
@@ -1662,10 +1771,11 @@ export class Executor {
workflowId: context.workflowId,
blockId: parallelInfo ? blockId : block.id,
executionId: this.contextExtensions.executionId,
- blockName: parallelInfo
- ? `${block.metadata?.name || 'Unnamed Block'} (iteration ${parallelInfo.iterationIndex + 1})`
- : block.metadata?.name || 'Unnamed Block',
+ blockName,
blockType: block.metadata?.id || 'unknown',
+ iterationCurrent,
+ iterationTotal,
+ iterationType,
})
}
diff --git a/apps/sim/executor/resolver/resolver.ts b/apps/sim/executor/resolver/resolver.ts
index 6c82957b3d..7d7ced33c1 100644
--- a/apps/sim/executor/resolver/resolver.ts
+++ b/apps/sim/executor/resolver/resolver.ts
@@ -1845,4 +1845,13 @@ export class InputResolver {
return value
}
+
+ /**
+ * Get the containing loop ID for a block
+ * @param blockId - The ID of the block
+ * @returns The containing loop ID or undefined if not in a loop
+ */
+ getContainingLoopId(blockId: string): string | undefined {
+ return this.loopsByBlockId.get(blockId)
+ }
}
diff --git a/apps/sim/stores/panel/console/types.ts b/apps/sim/stores/panel/console/types.ts
index 4d1c0f693e..9059af82a2 100644
--- a/apps/sim/stores/panel/console/types.ts
+++ b/apps/sim/stores/panel/console/types.ts
@@ -16,6 +16,10 @@ export interface ConsoleEntry {
input?: any
error?: string
warning?: string
+ // Iteration context for loops and parallels
+ iterationCurrent?: number
+ iterationTotal?: number
+ iterationType?: 'loop' | 'parallel'
}
export interface ConsoleUpdate {