@@ -563,7 +563,13 @@ export class AIAgentBubble extends ServiceBubble<
563563 this . beforeToolCallHook = params . beforeToolCall ;
564564 this . afterToolCallHook = params . afterToolCall ;
565565 this . afterLLMCallHook = params . afterLLMCall ;
566- this . streamingCallback = params . streamingCallback ;
566+ // Use explicit param if provided (Salad /ai route), otherwise check
567+ // execution metadata (Pearl flow execution injects it there).
568+ this . streamingCallback =
569+ params . streamingCallback ??
570+ ( context ?. executionMeta ?. _agentStreamCallback as
571+ | StreamingCallback
572+ | undefined ) ;
567573 this . factory = new BubbleFactory ( ) ;
568574 }
569575
@@ -2285,6 +2291,7 @@ export class AIAgentBubble extends ServiceBubble<
22852291 input : toolCall . args ,
22862292 callId : toolCall . id ! ,
22872293 variableId : this . context ?. variableId ,
2294+ agentName : this . params . name ,
22882295 } ,
22892296 } ) ;
22902297
@@ -2304,6 +2311,7 @@ export class AIAgentBubble extends ServiceBubble<
23042311 output : { error : errorContent } ,
23052312 duration : Date . now ( ) - startTime ,
23062313 variableId : this . context ?. variableId ,
2314+ agentName : this . params . name ,
23072315 } ,
23082316 } ) ;
23092317
@@ -2361,6 +2369,7 @@ export class AIAgentBubble extends ServiceBubble<
23612369 input : toolCall . args ,
23622370 callId : toolCall . id ! ,
23632371 variableId : this . context ?. variableId ,
2372+ agentName : this . params . name ,
23642373 } ,
23652374 } ) ;
23662375
@@ -2482,6 +2491,7 @@ export class AIAgentBubble extends ServiceBubble<
24822491 output : toolOutput ,
24832492 duration : toolDurationMs ,
24842493 variableId : this . context ?. variableId ,
2494+ agentName : this . params . name ,
24852495 } ,
24862496 } ) ;
24872497 } catch ( error ) {
@@ -2513,6 +2523,7 @@ export class AIAgentBubble extends ServiceBubble<
25132523 output : { error : errorContent } ,
25142524 duration : Date . now ( ) - startTime ,
25152525 variableId : this . context ?. variableId ,
2526+ agentName : this . params . name ,
25162527 } ,
25172528 } ) ;
25182529
@@ -2670,6 +2681,11 @@ export class AIAgentBubble extends ServiceBubble<
26702681 callbacks : [
26712682 {
26722683 handleLLMStart : async ( ) : Promise < void > => {
2684+ // Only for master — subagent llm_start events would flush
2685+ // the frontend's active tools group erroneously.
2686+ if ( this . params . name ?. startsWith ( 'Capability Agent:' ) ) {
2687+ return ;
2688+ }
26732689 await this . streamingCallback ?.( {
26742690 type : 'llm_start' ,
26752691 data : {
@@ -2678,9 +2694,26 @@ export class AIAgentBubble extends ServiceBubble<
26782694 } ,
26792695 } ) ;
26802696 } ,
2697+ handleLLMNewToken : async ( token : string ) : Promise < void > => {
2698+ if (
2699+ token &&
2700+ this . streamingCallback &&
2701+ ! this . params . name ?. startsWith ( 'Capability Agent:' )
2702+ ) {
2703+ await this . streamingCallback ( {
2704+ type : 'token' ,
2705+ data : { content : token , messageId } ,
2706+ } ) ;
2707+ }
2708+ } ,
26812709 handleLLMEnd : async ( output ) : Promise < void > => {
26822710 extractedThinking = extractThinking ( output ) ;
2683- if ( extractedThinking ) {
2711+ // Only emit think/llm_complete for the master agent — subagent
2712+ // events would confuse the frontend timeline (they're internal
2713+ // to the capability's execution).
2714+ const isMaster =
2715+ ! this . params . name ?. startsWith ( 'Capability Agent:' ) ;
2716+ if ( extractedThinking && isMaster ) {
26842717 await this . streamingCallback ?.( {
26852718 type : 'think' ,
26862719 data : {
@@ -2689,19 +2722,21 @@ export class AIAgentBubble extends ServiceBubble<
26892722 } ,
26902723 } ) ;
26912724 }
2692- const content = formatFinalResponse (
2693- generationsToMessageContent ( output . generations . flat ( ) ) ,
2694- this . params . model . model
2695- ) . response ;
2696- await this . streamingCallback ?.( {
2697- type : 'llm_complete' ,
2698- data : {
2699- messageId,
2700- content : content ,
2701- totalTokens :
2702- output . llmOutput ?. usage_metadata ?. total_tokens ,
2703- } ,
2704- } ) ;
2725+ if ( isMaster ) {
2726+ const content = formatFinalResponse (
2727+ generationsToMessageContent ( output . generations . flat ( ) ) ,
2728+ this . params . model . model
2729+ ) . response ;
2730+ await this . streamingCallback ?.( {
2731+ type : 'llm_complete' ,
2732+ data : {
2733+ messageId,
2734+ content : content ,
2735+ totalTokens :
2736+ output . llmOutput ?. usage_metadata ?. total_tokens ,
2737+ } ,
2738+ } ) ;
2739+ }
27052740 } ,
27062741 } ,
27072742 ] ,
0 commit comments