@@ -54,15 +54,38 @@ export class PipelineExecutor {
5454 if ( ! agent ) {
5555 throw new Error ( `Agent not found: ${ agentName } ` ) ;
5656 }
57-
58- // Note: Agent start/complete events are emitted at step level via store()
57+ const phase = String ( this . execution . get ( 'phase' , 'current' ) || 'setup' ) ;
58+ const step = 'try' ;
59+ this . execution . store ( 'agent' , 'name' , agentName ) ;
60+ this . execution . store ( 'step' , 'name' , step ) ;
61+ this . execution . store ( `agent:${ agentName } ` , 'start' , {
62+ phase,
63+ currentPhase : phase ,
64+ agent : agentName ,
65+ currentAgent : agentName ,
66+ step,
67+ currentStep : step ,
68+ status : 'running' ,
69+ input : summarizeValue ( input ) ,
70+ startedAt : new Date ( ) . toISOString ( ) ,
71+ } as any ) ;
5972
6073 // Execute agent with error envelope
6174 let output : any ;
6275 try {
6376 output = await agent ( input , this . execution ) ;
6477 } catch ( error ) {
65- // Non-fatal: streaming for errors handled elsewhere via status/error writes
78+ this . execution . store ( `agent:${ agentName } ` , 'complete' , {
79+ phase,
80+ currentPhase : phase ,
81+ agent : agentName ,
82+ currentAgent : agentName ,
83+ step,
84+ currentStep : step ,
85+ status : 'failed' ,
86+ error : summarizeError ( error ) ,
87+ completedAt : new Date ( ) . toISOString ( ) ,
88+ } as any ) ;
6689 throw error ;
6790 }
6891
@@ -72,14 +95,34 @@ export class PipelineExecutor {
7295 this . execution . store ( 'pipeline/short-circuit' , 'signal' , output . signal as any ) ;
7396 this . execution . store ( 'pipeline/short-circuit' , 'agent' , agentName ) ;
7497 this . execution . store ( 'pipeline/short-circuit' , 'timestamp' , Date . now ( ) ) ;
75- // Step-level store emits handle agent-complete with step context
98+ this . execution . store ( `agent:${ agentName } ` , 'complete' , {
99+ phase,
100+ currentPhase : phase ,
101+ agent : agentName ,
102+ currentAgent : agentName ,
103+ step,
104+ currentStep : step ,
105+ status : 'completed' ,
106+ shortCircuited : true ,
107+ output : summarizeValue ( output ) ,
108+ completedAt : new Date ( ) . toISOString ( ) ,
109+ } as any ) ;
76110
77111 // Throw short-circuit error for phase runner to catch
78112 throw new ShortCircuitError ( output . signal ! ) ;
79113 }
80114
81- // Emit end
82- // Step-level store emits handle agent-complete with step context
115+ this . execution . store ( `agent:${ agentName } ` , 'complete' , {
116+ phase,
117+ currentPhase : phase ,
118+ agent : agentName ,
119+ currentAgent : agentName ,
120+ step,
121+ currentStep : step ,
122+ status : 'completed' ,
123+ output : summarizeValue ( output ) ,
124+ completedAt : new Date ( ) . toISOString ( ) ,
125+ } as any ) ;
83126
84127 // Return normal result
85128 return output . result || output ;
@@ -183,3 +226,36 @@ export function createPhaseRunner(config: PhaseConfig): Executor<any, PhaseResul
183226 return await executor . executePhase ( config ) ;
184227 } ;
185228}
229+
230+ function summarizeError ( error : unknown ) : Record < string , unknown > {
231+ if ( error instanceof Error ) {
232+ return {
233+ name : error . name ,
234+ message : error . message ,
235+ stack : error . stack ? error . stack . split ( '\n' ) . slice ( 0 , 6 ) . join ( '\n' ) : undefined ,
236+ } ;
237+ }
238+ return { message : String ( error ) } ;
239+ }
240+
241+ function summarizeValue ( value : unknown ) : unknown {
242+ try {
243+ if ( value == null ) return value ;
244+ if ( typeof value === 'string' ) {
245+ return value . length > 500 ? `${ value . slice ( 0 , 500 ) } ... [truncated]` : value ;
246+ }
247+ if ( Array . isArray ( value ) ) {
248+ return { type : 'array' , length : value . length , sample : summarizeValue ( value [ 0 ] ) } ;
249+ }
250+ if ( typeof value === 'object' ) {
251+ const objectValue = value as Record < string , unknown > ;
252+ const keys = Object . keys ( objectValue ) ;
253+ const sample : Record < string , unknown > = { } ;
254+ for ( const key of keys . slice ( 0 , 8 ) ) sample [ key ] = summarizeValue ( objectValue [ key ] ) ;
255+ return { type : 'object' , keys : keys . slice ( 0 , 20 ) , sample } ;
256+ }
257+ return value ;
258+ } catch {
259+ return '[unserializable]' ;
260+ }
261+ }
0 commit comments