Skip to content

Commit 4285b36

Browse files
Merge pull request #673 from simstudioai/fix/trace-spans-tool-calls
improvement(trace-span): make tool calls separately collect in the tracespan
2 parents 5b7c07c + 6967ac0 commit 4285b36

File tree

3 files changed

+784
-76
lines changed

3 files changed

+784
-76
lines changed

apps/sim/app/workspace/[workspaceId]/logs/components/trace-spans/trace-spans-display.tsx

Lines changed: 89 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,22 @@ function transformBlockData(data: any, blockType: string, isInput: boolean) {
2727
if (isInput) {
2828
const cleanInput = { ...data }
2929

30-
// Remove sensitive fields
30+
// Remove sensitive fields (common API keys and tokens)
3131
if (cleanInput.apiKey) {
3232
cleanInput.apiKey = '***'
3333
}
3434
if (cleanInput.azureApiKey) {
3535
cleanInput.azureApiKey = '***'
3636
}
37+
if (cleanInput.token) {
38+
cleanInput.token = '***'
39+
}
40+
if (cleanInput.accessToken) {
41+
cleanInput.accessToken = '***'
42+
}
43+
if (cleanInput.authorization) {
44+
cleanInput.authorization = '***'
45+
}
3746

3847
// Remove null/undefined values for cleaner display
3948
Object.keys(cleanInput).forEach((key) => {
@@ -73,6 +82,10 @@ function transformBlockData(data: any, blockType: string, isInput: boolean) {
7382
headers: response.headers,
7483
}
7584

85+
case 'tool':
86+
// For tool calls, show the result data directly
87+
return response
88+
7689
default:
7790
// For other block types, show the response content
7891
return response
@@ -82,6 +95,70 @@ function transformBlockData(data: any, blockType: string, isInput: boolean) {
8295
return data
8396
}
8497

98+
// Collapsible Input/Output component
99+
interface CollapsibleInputOutputProps {
100+
span: TraceSpan
101+
spanId: string
102+
}
103+
104+
function CollapsibleInputOutput({ span, spanId }: CollapsibleInputOutputProps) {
105+
const [inputExpanded, setInputExpanded] = useState(false)
106+
const [outputExpanded, setOutputExpanded] = useState(false)
107+
108+
return (
109+
<div className='mt-2 mr-4 mb-4 ml-8 space-y-3 overflow-hidden'>
110+
{/* Input Data - Collapsible */}
111+
{span.input && (
112+
<div>
113+
<button
114+
onClick={() => setInputExpanded(!inputExpanded)}
115+
className='flex items-center gap-2 mb-2 font-medium text-muted-foreground text-xs hover:text-foreground transition-colors'
116+
>
117+
{inputExpanded ? (
118+
<ChevronDown className='h-3 w-3' />
119+
) : (
120+
<ChevronRight className='h-3 w-3' />
121+
)}
122+
Input
123+
</button>
124+
{inputExpanded && (
125+
<div className='mb-2 overflow-hidden rounded-md bg-secondary/30 p-3'>
126+
<BlockDataDisplay data={span.input} blockType={span.type} isInput={true} />
127+
</div>
128+
)}
129+
</div>
130+
)}
131+
132+
{/* Output Data - Collapsible */}
133+
{span.output && (
134+
<div>
135+
<button
136+
onClick={() => setOutputExpanded(!outputExpanded)}
137+
className='flex items-center gap-2 mb-2 font-medium text-muted-foreground text-xs hover:text-foreground transition-colors'
138+
>
139+
{outputExpanded ? (
140+
<ChevronDown className='h-3 w-3' />
141+
) : (
142+
<ChevronRight className='h-3 w-3' />
143+
)}
144+
{span.status === 'error' ? 'Error Details' : 'Output'}
145+
</button>
146+
{outputExpanded && (
147+
<div className='mb-2 overflow-hidden rounded-md bg-secondary/30 p-3'>
148+
<BlockDataDisplay
149+
data={span.output}
150+
blockType={span.type}
151+
isInput={false}
152+
isError={span.status === 'error'}
153+
/>
154+
</div>
155+
)}
156+
</div>
157+
)}
158+
</div>
159+
)
160+
}
161+
85162
// Component to display block input/output data in a clean, readable format
86163
function BlockDataDisplay({
87164
data,
@@ -531,37 +608,8 @@ function TraceSpanItem({
531608
{/* Expanded content */}
532609
{expanded && (
533610
<div>
534-
{/* Block Input/Output Data */}
535-
{(span.input || span.output) && (
536-
<div className='mt-2 mr-4 mb-4 ml-8 space-y-3 overflow-hidden'>
537-
{/* Input Data */}
538-
{span.input && (
539-
<div>
540-
<h4 className='mb-2 font-medium text-muted-foreground text-xs'>Input</h4>
541-
<div className='mb-2 overflow-hidden rounded-md bg-secondary/30 p-3'>
542-
<BlockDataDisplay data={span.input} blockType={span.type} isInput={true} />
543-
</div>
544-
</div>
545-
)}
546-
547-
{/* Output Data */}
548-
{span.output && (
549-
<div>
550-
<h4 className='mb-2 font-medium text-muted-foreground text-xs'>
551-
{span.status === 'error' ? 'Error Details' : 'Output'}
552-
</h4>
553-
<div className='mb-2 overflow-hidden rounded-md bg-secondary/30 p-3'>
554-
<BlockDataDisplay
555-
data={span.output}
556-
blockType={span.type}
557-
isInput={false}
558-
isError={span.status === 'error'}
559-
/>
560-
</div>
561-
</div>
562-
)}
563-
</div>
564-
)}
611+
{/* Block Input/Output Data - Collapsible */}
612+
{(span.input || span.output) && <CollapsibleInputOutput span={span} spanId={spanId} />}
565613

566614
{/* Children and tool calls */}
567615
{/* Render child spans */}
@@ -613,9 +661,16 @@ function TraceSpanItem({
613661
startTime: new Date(toolStartTime).toISOString(),
614662
endTime: new Date(toolEndTime).toISOString(),
615663
status: toolCall.error ? 'error' : 'success',
664+
// Include tool call arguments as input and result as output
665+
input: toolCall.input,
666+
output: toolCall.error
667+
? { error: toolCall.error, ...(toolCall.output || {}) }
668+
: toolCall.output,
616669
}
617670

618-
// Tool calls typically don't have sub-items
671+
// Tool calls now have input/output data to display
672+
const hasToolCallData = Boolean(toolCall.input || toolCall.output || toolCall.error)
673+
619674
return (
620675
<TraceSpanItem
621676
key={`tool-${index}`}
@@ -627,7 +682,7 @@ function TraceSpanItem({
627682
workflowStartTime={workflowStartTime}
628683
onToggle={onToggle}
629684
expandedSpans={expandedSpans}
630-
hasSubItems={false}
685+
hasSubItems={hasToolCallData}
631686
/>
632687
)
633688
})}

0 commit comments

Comments
 (0)