From 929549940586d207be2d8782bbc68944823bec10 Mon Sep 17 00:00:00 2001 From: Waleed Date: Thu, 12 Mar 2026 01:39:02 -0700 Subject: [PATCH] fix(traces): prevent condition blocks from rendering source agent's timeSegments (#3534) * fix(traces): prevent condition blocks from rendering source agent's timeSegments Condition blocks spread their source block's entire output into their own output. When the source is an agent, this leaked providerTiming/timeSegments into the condition's output, causing buildTraceSpans to create "Initial response" as a child of the condition span instead of the agent span. Two fixes: - Skip timeSegment child creation for condition block types in buildTraceSpans - Filter execution metadata (providerTiming, tokens, toolCalls, model, cost) from condition handler's filterSourceOutput Co-Authored-By: Claude Opus 4.6 * fix(traces): guard condition blocks from leaked metadata on old persisted logs Extend isConditionBlockType guards to also skip setting span.providerTiming, span.cost, span.tokens, and span.model for condition blocks. This ensures old persisted logs (recorded before the filterSourceOutput fix) don't display misleading execution metadata on condition spans. Co-Authored-By: Claude Opus 4.6 * fix(traces): guard toolCalls fallback path for condition blocks on old logs The else branch that extracts toolCalls from log.output also needs a condition block guard, otherwise old persisted logs with leaked toolCalls from the source agent would render on the condition span. Co-Authored-By: Claude Opus 4.6 * refactor(traces): extract isCondition to local variable for readability Cache isConditionBlockType(log.blockType) in a local const at the top of the forEach loop instead of calling it 6 times per iteration. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- .../handlers/condition/condition-handler.ts | 3 ++- .../logs/execution/trace-spans/trace-spans.ts | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/sim/executor/handlers/condition/condition-handler.ts b/apps/sim/executor/handlers/condition/condition-handler.ts index 87a1eac9d1..60ad9f9986 100644 --- a/apps/sim/executor/handlers/condition/condition-handler.ts +++ b/apps/sim/executor/handlers/condition/condition-handler.ts @@ -166,7 +166,8 @@ export class ConditionBlockHandler implements BlockHandler { if (!output || typeof output !== 'object') { return output } - const { _pauseMetadata, error, ...rest } = output + const { _pauseMetadata, error, providerTiming, tokens, toolCalls, model, cost, ...rest } = + output return rest } diff --git a/apps/sim/lib/logs/execution/trace-spans/trace-spans.ts b/apps/sim/lib/logs/execution/trace-spans/trace-spans.ts index 450dd2c6ec..1910f8c605 100644 --- a/apps/sim/lib/logs/execution/trace-spans/trace-spans.ts +++ b/apps/sim/lib/logs/execution/trace-spans/trace-spans.ts @@ -1,6 +1,10 @@ import { createLogger } from '@sim/logger' import type { ToolCall, TraceSpan } from '@/lib/logs/types' -import { isWorkflowBlockType, stripCustomToolPrefix } from '@/executor/constants' +import { + isConditionBlockType, + isWorkflowBlockType, + stripCustomToolPrefix, +} from '@/executor/constants' import type { ExecutionResult } from '@/executor/types' import { stripCloneSuffixes } from '@/executor/utils/subflow-utils' @@ -109,6 +113,7 @@ export function buildTraceSpans(result: ExecutionResult): { if (!log.blockId || !log.blockType) return const spanId = `${log.blockId}-${new Date(log.startedAt).getTime()}` + const isCondition = isConditionBlockType(log.blockType) const duration = log.durationMs || 0 @@ -164,7 +169,7 @@ export function buildTraceSpans(result: ExecutionResult): { ...(log.parentIterations?.length && { parentIterations: log.parentIterations }), } - if (log.output?.providerTiming) { + if (!isCondition && log.output?.providerTiming) { const providerTiming = log.output.providerTiming as { duration: number startTime: string @@ -186,7 +191,7 @@ export function buildTraceSpans(result: ExecutionResult): { } } - if (log.output?.cost) { + if (!isCondition && log.output?.cost) { span.cost = log.output.cost as { input?: number output?: number @@ -194,7 +199,7 @@ export function buildTraceSpans(result: ExecutionResult): { } } - if (log.output?.tokens) { + if (!isCondition && log.output?.tokens) { const t = log.output.tokens as | number | { @@ -224,12 +229,13 @@ export function buildTraceSpans(result: ExecutionResult): { } } - if (log.output?.model) { + if (!isCondition && log.output?.model) { span.model = log.output.model as string } if ( !isWorkflowBlockType(log.blockType) && + !isCondition && log.output?.providerTiming?.timeSegments && Array.isArray(log.output.providerTiming.timeSegments) ) { @@ -317,7 +323,7 @@ export function buildTraceSpans(result: ExecutionResult): { } } ) - } else { + } else if (!isCondition) { let toolCallsList = null try {