@@ -21,9 +21,10 @@ import { resolve } from 'node:path';
2121import React from 'react' ;
2222import { Box , Text , useInput } from 'ink' ;
2323import TextInput from 'ink-text-input' ;
24- import { Connection , SfError , Lifecycle } from '@salesforce/core' ;
24+ import { Connection , SfError , Lifecycle , Logger } from '@salesforce/core' ;
2525import { AgentPreviewBase , AgentPreviewSendResponse , writeDebugLog } from '@salesforce/agents' ;
2626import { sleep , env } from '@salesforce/kit' ;
27+ import { PlannerResponse } from '@salesforce/agents/lib/types.js' ;
2728
2829// Component to show a simple typing animation
2930function Typing ( ) : React . ReactNode {
@@ -52,7 +53,8 @@ function Typing(): React.ReactNode {
5253export const saveTranscriptsToFile = (
5354 outputDir : string ,
5455 messages : Array < { timestamp : Date ; role : string ; content : string } > ,
55- responses : AgentPreviewSendResponse [ ]
56+ responses : AgentPreviewSendResponse [ ] ,
57+ traces ?: PlannerResponse [ ]
5658) : void => {
5759 if ( ! outputDir ) return ;
5860 fs . mkdirSync ( outputDir , { recursive : true } ) ;
@@ -62,6 +64,27 @@ export const saveTranscriptsToFile = (
6264
6365 const responsesPath = path . join ( outputDir , 'responses.json' ) ;
6466 fs . writeFileSync ( responsesPath , JSON . stringify ( responses , null , 2 ) ) ;
67+
68+ if ( traces ) {
69+ const tracesPath = path . join ( outputDir , 'traces.json' ) ;
70+ fs . writeFileSync ( tracesPath , JSON . stringify ( traces , null , 2 ) ) ;
71+ }
72+ } ;
73+
74+ const getTraces = async (
75+ agent : AgentPreviewBase ,
76+ sessionId : string ,
77+ messageIds : string [ ] ,
78+ logger : Logger
79+ ) : Promise < PlannerResponse [ ] > => {
80+ try {
81+ const traces = await agent . traces ( sessionId , messageIds ) ;
82+ return traces ;
83+ } catch ( e ) {
84+ const sfError = SfError . wrap ( e ) ;
85+ logger . info ( `Error obtaining traces: ${ sfError . name } - ${ sfError . message } ` , { sessionId, messageIds } ) ;
86+ return [ ] ;
87+ }
6588} ;
6689
6790/**
@@ -78,6 +101,7 @@ export function AgentPreviewReact(props: {
78101 readonly outputDir : string | undefined ;
79102 readonly isLocalAgent : boolean ;
80103 readonly apexDebug : boolean | undefined ;
104+ readonly logger : Logger ;
81105} ) : React . ReactNode {
82106 const [ messages , setMessages ] = React . useState < Array < { timestamp : Date ; role : string ; content : string } > > ( [ ] ) ;
83107 const [ header , setHeader ] = React . useState ( 'Starting session...' ) ;
@@ -96,8 +120,9 @@ export function AgentPreviewReact(props: {
96120 const [ tempDir , setTempDir ] = React . useState ( '' ) ;
97121 const [ responses , setResponses ] = React . useState < AgentPreviewSendResponse [ ] > ( [ ] ) ;
98122 const [ apexDebugLogs , setApexDebugLogs ] = React . useState < string [ ] > ( [ ] ) ;
123+ const [ messageIds , setMessageIds ] = React . useState < string [ ] > ( [ ] ) ;
99124
100- const { connection, agent, name, outputDir, isLocalAgent, apexDebug } = props ;
125+ const { connection, agent, name, outputDir, isLocalAgent, apexDebug, logger } = props ;
101126
102127 useInput ( ( input , key ) => {
103128 // If user is in directory input and presses ESC, cancel and exit without saving
@@ -222,7 +247,9 @@ export function AgentPreviewReact(props: {
222247 const sessionDir = path . join ( finalDir , `${ dateForDir } --${ sessionId || 'session' } ` ) ;
223248 fs . mkdirSync ( sessionDir , { recursive : true } ) ;
224249
225- saveTranscriptsToFile ( sessionDir , messages , responses ) ;
250+ const traces = await getTraces ( agent , sessionId , messageIds , logger ) ;
251+
252+ saveTranscriptsToFile ( sessionDir , messages , responses , traces ) ;
226253
227254 // Write apex debug logs if any
228255 if ( apexDebug ) {
@@ -246,7 +273,7 @@ export function AgentPreviewReact(props: {
246273 }
247274 } ;
248275 void saveAndExit ( ) ;
249- } , [ saveConfirmed , saveDir , messages , responses , sessionId , apexDebug , connection ] ) ;
276+ } , [ saveConfirmed , saveDir , messages , responses , sessionId , apexDebug , connection , agent , messageIds , logger ] ) ;
250277
251278 return (
252279 < Box flexDirection = "column" >
@@ -395,6 +422,7 @@ export function AgentPreviewReact(props: {
395422
396423 // Add the agent's response to the chat
397424 setMessages ( ( prev ) => [ ...prev , { role : name , content : message , timestamp : new Date ( ) } ] ) ;
425+ setMessageIds ( ( prev ) => [ ...prev , response . messages [ 0 ] . planId ] ) ;
398426
399427 // Apex debug logs will be saved when user exits and chooses to save
400428 } catch ( e ) {
@@ -422,6 +450,7 @@ export function AgentPreviewReact(props: {
422450 < Text bold > Session Ended</ Text >
423451 { tempDir ? < Text > Conversation log: { tempDir } /transcript.json</ Text > : null }
424452 { tempDir ? < Text > API transactions: { tempDir } /responses.json</ Text > : null }
453+ { tempDir ? < Text > Traces: { tempDir } /traces.json</ Text > : null }
425454 { apexDebugLogs . length > 0 && tempDir && < Text > Apex Debug Logs saved to: { tempDir } </ Text > }
426455 </ Box >
427456 ) : null }
0 commit comments