@tanstack/ai 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +1 -0
  2. package/dist/esm/activities/chat/index.js +206 -172
  3. package/dist/esm/activities/chat/index.js.map +1 -1
  4. package/dist/esm/activities/chat/stream/index.d.ts +1 -1
  5. package/dist/esm/activities/chat/stream/processor.d.ts +22 -43
  6. package/dist/esm/activities/chat/stream/processor.js +90 -157
  7. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  8. package/dist/esm/activities/chat/tools/tool-calls.d.ts +22 -21
  9. package/dist/esm/activities/chat/tools/tool-calls.js +40 -27
  10. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  11. package/dist/esm/activities/generateImage/index.js +41 -1
  12. package/dist/esm/activities/generateImage/index.js.map +1 -1
  13. package/dist/esm/activities/generateSpeech/index.js +33 -1
  14. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  15. package/dist/esm/activities/generateTranscription/index.js +29 -1
  16. package/dist/esm/activities/generateTranscription/index.js.map +1 -1
  17. package/dist/esm/activities/generateVideo/index.js +50 -0
  18. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  19. package/dist/esm/activities/summarize/index.js +9 -8
  20. package/dist/esm/activities/summarize/index.js.map +1 -1
  21. package/dist/esm/event-client.d.ts +378 -254
  22. package/dist/esm/event-client.js.map +1 -1
  23. package/dist/esm/index.d.ts +2 -2
  24. package/dist/esm/stream-to-response.d.ts +1 -1
  25. package/dist/esm/stream-to-response.js +5 -3
  26. package/dist/esm/stream-to-response.js.map +1 -1
  27. package/dist/esm/types.d.ts +162 -46
  28. package/package.json +1 -1
  29. package/src/activities/chat/index.ts +267 -191
  30. package/src/activities/chat/stream/index.ts +1 -5
  31. package/src/activities/chat/stream/processor.ts +129 -270
  32. package/src/activities/chat/tools/tool-calls.ts +55 -49
  33. package/src/activities/generateImage/index.ts +47 -2
  34. package/src/activities/generateSpeech/index.ts +37 -1
  35. package/src/activities/generateTranscription/index.ts +33 -1
  36. package/src/activities/generateVideo/index.ts +54 -0
  37. package/src/activities/summarize/index.ts +10 -9
  38. package/src/event-client.ts +460 -256
  39. package/src/index.ts +2 -3
  40. package/src/stream-to-response.ts +8 -6
  41. package/src/types.ts +209 -65
@@ -6,11 +6,7 @@
6
6
 
7
7
  // Core processor
8
8
  export { StreamProcessor, createReplayStream } from './processor'
9
- export type {
10
- StreamProcessorEvents,
11
- StreamProcessorHandlers,
12
- StreamProcessorOptions,
13
- } from './processor'
9
+ export type { StreamProcessorEvents, StreamProcessorOptions } from './processor'
14
10
 
15
11
  // Strategies
16
12
  export {
@@ -78,67 +78,13 @@ export interface StreamProcessorEvents {
78
78
  onThinkingUpdate?: (messageId: string, content: string) => void
79
79
  }
80
80
 
81
- /**
82
- * Legacy handlers for backward compatibility
83
- * These are the old callback-style handlers
84
- */
85
- export interface StreamProcessorHandlers {
86
- onTextUpdate?: (content: string) => void
87
- onThinkingUpdate?: (content: string) => void
88
-
89
- // Tool call lifecycle handlers
90
- onToolCallStart?: (index: number, id: string, name: string) => void
91
- onToolCallDelta?: (index: number, args: string) => void
92
- onToolCallComplete?: (
93
- index: number,
94
- id: string,
95
- name: string,
96
- args: string,
97
- ) => void
98
- onToolCallStateChange?: (
99
- index: number,
100
- id: string,
101
- name: string,
102
- state: ToolCallState,
103
- args: string,
104
- parsedArgs?: any,
105
- ) => void
106
-
107
- // Tool result handlers
108
- onToolResultStateChange?: (
109
- toolCallId: string,
110
- content: string,
111
- state: ToolResultState,
112
- error?: string,
113
- ) => void
114
-
115
- // Approval/client tool handlers
116
- onApprovalRequested?: (
117
- toolCallId: string,
118
- toolName: string,
119
- input: any,
120
- approvalId: string,
121
- ) => void
122
- onToolInputAvailable?: (
123
- toolCallId: string,
124
- toolName: string,
125
- input: any,
126
- ) => void
127
-
128
- // Stream lifecycle
129
- onStreamEnd?: (content: string, toolCalls?: Array<ToolCall>) => void
130
- onError?: (error: { message: string; code?: string }) => void
131
- }
132
-
133
81
  /**
134
82
  * Options for StreamProcessor
135
83
  */
136
84
  export interface StreamProcessorOptions {
137
85
  chunkStrategy?: ChunkStrategy
138
- /** New event-driven handlers */
86
+ /** Event-driven handlers */
139
87
  events?: StreamProcessorEvents
140
- /** Legacy callback handlers (for backward compatibility) */
141
- handlers?: StreamProcessorHandlers
142
88
  jsonParser?: {
143
89
  parse: (jsonString: string) => any
144
90
  }
@@ -168,7 +114,6 @@ export interface StreamProcessorOptions {
168
114
  export class StreamProcessor {
169
115
  private chunkStrategy: ChunkStrategy
170
116
  private events: StreamProcessorEvents
171
- private handlers: StreamProcessorHandlers
172
117
  private jsonParser: { parse: (jsonString: string) => any }
173
118
  private recordingEnabled: boolean
174
119
 
@@ -197,7 +142,6 @@ export class StreamProcessor {
197
142
  constructor(options: StreamProcessorOptions = {}) {
198
143
  this.chunkStrategy = options.chunkStrategy || new ImmediateStrategy()
199
144
  this.events = options.events || {}
200
- this.handlers = options.handlers || {}
201
145
  this.jsonParser = options.jsonParser || defaultJSONParser
202
146
  this.recordingEnabled = options.recording ?? false
203
147
 
@@ -423,49 +367,51 @@ export class StreamProcessor {
423
367
  }
424
368
 
425
369
  switch (chunk.type) {
426
- case 'content':
427
- this.handleContentChunk(chunk)
370
+ // AG-UI Events
371
+ case 'TEXT_MESSAGE_CONTENT':
372
+ this.handleTextMessageContentEvent(chunk)
428
373
  break
429
374
 
430
- case 'tool_call':
431
- this.handleToolCallChunk(chunk)
375
+ case 'TOOL_CALL_START':
376
+ this.handleToolCallStartEvent(chunk)
432
377
  break
433
378
 
434
- case 'tool_result':
435
- this.handleToolResultChunk(chunk)
379
+ case 'TOOL_CALL_ARGS':
380
+ this.handleToolCallArgsEvent(chunk)
436
381
  break
437
382
 
438
- case 'done':
439
- this.handleDoneChunk(chunk)
383
+ case 'TOOL_CALL_END':
384
+ this.handleToolCallEndEvent(chunk)
440
385
  break
441
386
 
442
- case 'error':
443
- this.handleErrorChunk(chunk)
387
+ case 'RUN_FINISHED':
388
+ this.handleRunFinishedEvent(chunk)
444
389
  break
445
390
 
446
- case 'thinking':
447
- this.handleThinkingChunk(chunk)
391
+ case 'RUN_ERROR':
392
+ this.handleRunErrorEvent(chunk)
448
393
  break
449
394
 
450
- case 'approval-requested':
451
- this.handleApprovalRequestedChunk(chunk)
395
+ case 'STEP_FINISHED':
396
+ this.handleStepFinishedEvent(chunk)
452
397
  break
453
398
 
454
- case 'tool-input-available':
455
- this.handleToolInputAvailableChunk(chunk)
399
+ case 'CUSTOM':
400
+ this.handleCustomEvent(chunk)
456
401
  break
457
402
 
458
403
  default:
459
- // Unknown chunk type - ignore
404
+ // RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_END, STEP_STARTED,
405
+ // STATE_SNAPSHOT, STATE_DELTA - no special handling needed
460
406
  break
461
407
  }
462
408
  }
463
409
 
464
410
  /**
465
- * Handle a content chunk
411
+ * Handle TEXT_MESSAGE_CONTENT event
466
412
  */
467
- private handleContentChunk(
468
- chunk: Extract<StreamChunk, { type: 'content' }>,
413
+ private handleTextMessageContentEvent(
414
+ chunk: Extract<StreamChunk, { type: 'TEXT_MESSAGE_CONTENT' }>,
469
415
  ): void {
470
416
  // Content arriving means all current tool calls are complete
471
417
  this.completeAllToolCalls()
@@ -495,7 +441,7 @@ export class StreamProcessor {
495
441
  // Prefer delta over content - delta is the incremental change
496
442
  if (chunk.delta !== '') {
497
443
  nextText = currentText + chunk.delta
498
- } else if (chunk.content !== '') {
444
+ } else if (chunk.content && chunk.content !== '') {
499
445
  // Fallback: use content if delta is not provided
500
446
  if (chunk.content.startsWith(currentText)) {
501
447
  nextText = chunk.content
@@ -512,8 +458,7 @@ export class StreamProcessor {
512
458
  this.totalTextContent += textDelta
513
459
 
514
460
  // Use delta for chunk strategy if available
515
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
516
- const chunkPortion = chunk.delta ?? chunk.content ?? ''
461
+ const chunkPortion = chunk.delta || chunk.content || ''
517
462
  const shouldEmit = this.chunkStrategy.shouldEmit(
518
463
  chunkPortion,
519
464
  this.currentSegmentText,
@@ -524,100 +469,75 @@ export class StreamProcessor {
524
469
  }
525
470
 
526
471
  /**
527
- * Handle a tool call chunk
472
+ * Handle TOOL_CALL_START event
528
473
  */
529
- private handleToolCallChunk(
530
- chunk: Extract<StreamChunk, { type: 'tool_call' }>,
474
+ private handleToolCallStartEvent(
475
+ chunk: Extract<StreamChunk, { type: 'TOOL_CALL_START' }>,
531
476
  ): void {
532
477
  // Mark that we've seen tool calls since the last text segment
533
478
  this.hasToolCallsSinceTextStart = true
534
479
 
535
- const toolCallId = chunk.toolCall.id
480
+ const toolCallId = chunk.toolCallId
536
481
  const existingToolCall = this.toolCalls.get(toolCallId)
537
482
 
538
483
  if (!existingToolCall) {
539
484
  // New tool call starting
540
- const initialState: ToolCallState = chunk.toolCall.function.arguments
541
- ? 'input-streaming'
542
- : 'awaiting-input'
485
+ const initialState: ToolCallState = 'awaiting-input'
543
486
 
544
487
  const newToolCall: InternalToolCallState = {
545
- id: chunk.toolCall.id,
546
- name: chunk.toolCall.function.name,
547
- arguments: chunk.toolCall.function.arguments || '',
488
+ id: chunk.toolCallId,
489
+ name: chunk.toolName,
490
+ arguments: '',
548
491
  state: initialState,
549
492
  parsedArguments: undefined,
550
- index: chunk.index,
551
- }
552
-
553
- // Try to parse the arguments
554
- if (chunk.toolCall.function.arguments) {
555
- newToolCall.parsedArguments = this.jsonParser.parse(
556
- chunk.toolCall.function.arguments,
557
- )
493
+ index: chunk.index ?? this.toolCalls.size,
558
494
  }
559
495
 
560
496
  this.toolCalls.set(toolCallId, newToolCall)
561
497
  this.toolCallOrder.push(toolCallId)
562
498
 
563
- // Get actual index for this tool call (based on order)
564
- const actualIndex = this.toolCallOrder.indexOf(toolCallId)
565
-
566
- // Emit legacy lifecycle event
567
- this.handlers.onToolCallStart?.(
568
- actualIndex,
569
- chunk.toolCall.id,
570
- chunk.toolCall.function.name,
571
- )
572
-
573
- // Emit legacy state change event
574
- this.handlers.onToolCallStateChange?.(
575
- actualIndex,
576
- chunk.toolCall.id,
577
- chunk.toolCall.function.name,
578
- initialState,
579
- chunk.toolCall.function.arguments || '',
580
- newToolCall.parsedArguments,
581
- )
582
-
583
- // Emit initial delta
584
- if (chunk.toolCall.function.arguments) {
585
- this.handlers.onToolCallDelta?.(
586
- actualIndex,
587
- chunk.toolCall.function.arguments,
588
- )
589
- }
590
-
591
499
  // Update UIMessage
592
500
  if (this.currentAssistantMessageId) {
593
501
  this.messages = updateToolCallPart(
594
502
  this.messages,
595
503
  this.currentAssistantMessageId,
596
504
  {
597
- id: chunk.toolCall.id,
598
- name: chunk.toolCall.function.name,
599
- arguments: chunk.toolCall.function.arguments || '',
505
+ id: chunk.toolCallId,
506
+ name: chunk.toolName,
507
+ arguments: '',
600
508
  state: initialState,
601
509
  },
602
510
  )
603
511
  this.emitMessagesChange()
604
512
 
605
- // Emit new granular event
513
+ // Emit granular event
606
514
  this.events.onToolCallStateChange?.(
607
515
  this.currentAssistantMessageId,
608
- chunk.toolCall.id,
516
+ chunk.toolCallId,
609
517
  initialState,
610
- chunk.toolCall.function.arguments || '',
518
+ '',
611
519
  )
612
520
  }
613
- } else {
614
- // Continuing existing tool call
521
+ }
522
+ }
523
+
524
+ /**
525
+ * Handle TOOL_CALL_ARGS event
526
+ */
527
+ private handleToolCallArgsEvent(
528
+ chunk: Extract<StreamChunk, { type: 'TOOL_CALL_ARGS' }>,
529
+ ): void {
530
+ const toolCallId = chunk.toolCallId
531
+ const existingToolCall = this.toolCalls.get(toolCallId)
532
+
533
+ if (existingToolCall) {
615
534
  const wasAwaitingInput = existingToolCall.state === 'awaiting-input'
616
535
 
617
- existingToolCall.arguments += chunk.toolCall.function.arguments || ''
536
+ // Accumulate arguments from delta
537
+ existingToolCall.arguments += chunk.delta || ''
618
538
 
619
539
  // Update state
620
- if (wasAwaitingInput && chunk.toolCall.function.arguments) {
540
+ if (wasAwaitingInput && chunk.delta) {
621
541
  existingToolCall.state = 'input-streaming'
622
542
  }
623
543
 
@@ -626,27 +546,6 @@ export class StreamProcessor {
626
546
  existingToolCall.arguments,
627
547
  )
628
548
 
629
- // Get actual index for this tool call
630
- const actualIndex = this.toolCallOrder.indexOf(toolCallId)
631
-
632
- // Emit legacy state change event
633
- this.handlers.onToolCallStateChange?.(
634
- actualIndex,
635
- existingToolCall.id,
636
- existingToolCall.name,
637
- existingToolCall.state,
638
- existingToolCall.arguments,
639
- existingToolCall.parsedArguments,
640
- )
641
-
642
- // Emit delta
643
- if (chunk.toolCall.function.arguments) {
644
- this.handlers.onToolCallDelta?.(
645
- actualIndex,
646
- chunk.toolCall.function.arguments,
647
- )
648
- }
649
-
650
549
  // Update UIMessage
651
550
  if (this.currentAssistantMessageId) {
652
551
  this.messages = updateToolCallPart(
@@ -661,7 +560,7 @@ export class StreamProcessor {
661
560
  )
662
561
  this.emitMessagesChange()
663
562
 
664
- // Emit new granular event
563
+ // Emit granular event
665
564
  this.events.onToolCallStateChange?.(
666
565
  this.currentAssistantMessageId,
667
566
  existingToolCall.id,
@@ -673,27 +572,20 @@ export class StreamProcessor {
673
572
  }
674
573
 
675
574
  /**
676
- * Handle a tool result chunk
575
+ * Handle TOOL_CALL_END event
677
576
  */
678
- private handleToolResultChunk(
679
- chunk: Extract<StreamChunk, { type: 'tool_result' }>,
577
+ private handleToolCallEndEvent(
578
+ chunk: Extract<StreamChunk, { type: 'TOOL_CALL_END' }>,
680
579
  ): void {
681
580
  const state: ToolResultState = 'complete'
682
581
 
683
- // Emit legacy handler
684
- this.handlers.onToolResultStateChange?.(
685
- chunk.toolCallId,
686
- chunk.content,
687
- state,
688
- )
689
-
690
582
  // Update UIMessage if we have a current assistant message
691
- if (this.currentAssistantMessageId) {
583
+ if (this.currentAssistantMessageId && chunk.result) {
692
584
  this.messages = updateToolResultPart(
693
585
  this.messages,
694
586
  this.currentAssistantMessageId,
695
587
  chunk.toolCallId,
696
- chunk.content,
588
+ chunk.result,
697
589
  state,
698
590
  )
699
591
  this.emitMessagesChange()
@@ -701,40 +593,39 @@ export class StreamProcessor {
701
593
  }
702
594
 
703
595
  /**
704
- * Handle a done chunk
596
+ * Handle RUN_FINISHED event
705
597
  */
706
- private handleDoneChunk(chunk: Extract<StreamChunk, { type: 'done' }>): void {
598
+ private handleRunFinishedEvent(
599
+ chunk: Extract<StreamChunk, { type: 'RUN_FINISHED' }>,
600
+ ): void {
707
601
  this.finishReason = chunk.finishReason
708
602
  this.isDone = true
709
603
  this.completeAllToolCalls()
710
604
  }
711
605
 
712
606
  /**
713
- * Handle an error chunk
607
+ * Handle RUN_ERROR event
714
608
  */
715
- private handleErrorChunk(
716
- chunk: Extract<StreamChunk, { type: 'error' }>,
609
+ private handleRunErrorEvent(
610
+ chunk: Extract<StreamChunk, { type: 'RUN_ERROR' }>,
717
611
  ): void {
718
- // Emit legacy handler
719
- this.handlers.onError?.(chunk.error)
720
-
721
- // Emit new event
722
- this.events.onError?.(new Error(chunk.error.message))
612
+ // Emit error event
613
+ this.events.onError?.(new Error(chunk.error.message || 'An error occurred'))
723
614
  }
724
615
 
725
616
  /**
726
- * Handle a thinking chunk
617
+ * Handle STEP_FINISHED event (for thinking/reasoning content)
727
618
  */
728
- private handleThinkingChunk(
729
- chunk: Extract<StreamChunk, { type: 'thinking' }>,
619
+ private handleStepFinishedEvent(
620
+ chunk: Extract<StreamChunk, { type: 'STEP_FINISHED' }>,
730
621
  ): void {
731
622
  const previous = this.thinkingContent
732
623
  let nextThinking = previous
733
624
 
734
625
  // Prefer delta over content
735
- if (chunk.delta !== '') {
626
+ if (chunk.delta && chunk.delta !== '') {
736
627
  nextThinking = previous + chunk.delta
737
- } else if (chunk.content !== '') {
628
+ } else if (chunk.content && chunk.content !== '') {
738
629
  if (chunk.content.startsWith(previous)) {
739
630
  nextThinking = chunk.content
740
631
  } else if (previous.startsWith(chunk.content)) {
@@ -746,9 +637,6 @@ export class StreamProcessor {
746
637
 
747
638
  this.thinkingContent = nextThinking
748
639
 
749
- // Emit legacy handler
750
- this.handlers.onThinkingUpdate?.(this.thinkingContent)
751
-
752
640
  // Update UIMessage
753
641
  if (this.currentAssistantMessageId) {
754
642
  this.messages = updateThinkingPart(
@@ -758,7 +646,7 @@ export class StreamProcessor {
758
646
  )
759
647
  this.emitMessagesChange()
760
648
 
761
- // Emit new granular event
649
+ // Emit granular event
762
650
  this.events.onThinkingUpdate?.(
763
651
  this.currentAssistantMessageId,
764
652
  this.thinkingContent,
@@ -767,69 +655,68 @@ export class StreamProcessor {
767
655
  }
768
656
 
769
657
  /**
770
- * Handle an approval-requested chunk
658
+ * Handle CUSTOM event
659
+ * Handles special custom events like 'tool-input-available' for client-side tool execution
660
+ * and 'approval-requested' for tool approval flows
771
661
  */
772
- private handleApprovalRequestedChunk(
773
- chunk: Extract<StreamChunk, { type: 'approval-requested' }>,
662
+ private handleCustomEvent(
663
+ chunk: Extract<StreamChunk, { type: 'CUSTOM' }>,
774
664
  ): void {
775
- // Emit legacy handler
776
- this.handlers.onApprovalRequested?.(
777
- chunk.toolCallId,
778
- chunk.toolName,
779
- chunk.input,
780
- chunk.approval.id,
781
- )
665
+ // Handle client tool input availability - trigger client-side execution
666
+ if (chunk.name === 'tool-input-available' && chunk.data) {
667
+ const { toolCallId, toolName, input } = chunk.data as {
668
+ toolCallId: string
669
+ toolName: string
670
+ input: any
671
+ }
782
672
 
783
- // Update UIMessage with approval metadata
784
- if (this.currentAssistantMessageId) {
785
- this.messages = updateToolCallApproval(
786
- this.messages,
787
- this.currentAssistantMessageId,
788
- chunk.toolCallId,
789
- chunk.approval.id,
790
- )
791
- this.emitMessagesChange()
673
+ // Emit onToolCall event for the client to execute the tool
674
+ this.events.onToolCall?.({
675
+ toolCallId,
676
+ toolName,
677
+ input,
678
+ })
792
679
  }
793
680
 
794
- // Emit new event
795
- this.events.onApprovalRequest?.({
796
- toolCallId: chunk.toolCallId,
797
- toolName: chunk.toolName,
798
- input: chunk.input,
799
- approvalId: chunk.approval.id,
800
- })
801
- }
681
+ // Handle approval requests
682
+ if (chunk.name === 'approval-requested' && chunk.data) {
683
+ const { toolCallId, toolName, input, approval } = chunk.data as {
684
+ toolCallId: string
685
+ toolName: string
686
+ input: any
687
+ approval: { id: string; needsApproval: boolean }
688
+ }
802
689
 
803
- /**
804
- * Handle a tool-input-available chunk
805
- */
806
- private handleToolInputAvailableChunk(
807
- chunk: Extract<StreamChunk, { type: 'tool-input-available' }>,
808
- ): void {
809
- // Emit legacy handler
810
- this.handlers.onToolInputAvailable?.(
811
- chunk.toolCallId,
812
- chunk.toolName,
813
- chunk.input,
814
- )
690
+ // Update the tool call part with approval state
691
+ if (this.currentAssistantMessageId) {
692
+ this.messages = updateToolCallApproval(
693
+ this.messages,
694
+ this.currentAssistantMessageId,
695
+ toolCallId,
696
+ approval.id,
697
+ )
698
+ this.emitMessagesChange()
699
+ }
815
700
 
816
- // Emit new event
817
- this.events.onToolCall?.({
818
- toolCallId: chunk.toolCallId,
819
- toolName: chunk.toolName,
820
- input: chunk.input,
821
- })
701
+ // Emit approval request event
702
+ this.events.onApprovalRequest?.({
703
+ toolCallId,
704
+ toolName,
705
+ input,
706
+ approvalId: approval.id,
707
+ })
708
+ }
822
709
  }
823
710
 
824
711
  /**
825
712
  * Detect if an incoming content chunk represents a NEW text segment
826
713
  */
827
714
  private isNewTextSegment(
828
- chunk: Extract<StreamChunk, { type: 'content' }>,
715
+ chunk: Extract<StreamChunk, { type: 'TEXT_MESSAGE_CONTENT' }>,
829
716
  previous: string,
830
717
  ): boolean {
831
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
832
- if (chunk.delta !== undefined && chunk.content !== undefined) {
718
+ // Check if content is present (delta is always defined but may be empty string)
719
+ if (chunk.content !== undefined) {
833
720
  if (chunk.content.length < previous.length) {
834
721
  return true
835
722
  }
@@ -859,7 +746,7 @@ export class StreamProcessor {
859
746
  * Mark a tool call as complete and emit event
860
747
  */
861
748
  private completeToolCall(
862
- index: number,
749
+ _index: number,
863
750
  toolCall: InternalToolCallState,
864
751
  ): void {
865
752
  toolCall.state = 'input-complete'
@@ -867,24 +754,6 @@ export class StreamProcessor {
867
754
  // Try final parse
868
755
  toolCall.parsedArguments = this.jsonParser.parse(toolCall.arguments)
869
756
 
870
- // Emit legacy state change event
871
- this.handlers.onToolCallStateChange?.(
872
- index,
873
- toolCall.id,
874
- toolCall.name,
875
- 'input-complete',
876
- toolCall.arguments,
877
- toolCall.parsedArguments,
878
- )
879
-
880
- // Emit legacy complete event
881
- this.handlers.onToolCallComplete?.(
882
- index,
883
- toolCall.id,
884
- toolCall.name,
885
- toolCall.arguments,
886
- )
887
-
888
757
  // Update UIMessage
889
758
  if (this.currentAssistantMessageId) {
890
759
  this.messages = updateToolCallPart(
@@ -899,7 +768,7 @@ export class StreamProcessor {
899
768
  )
900
769
  this.emitMessagesChange()
901
770
 
902
- // Emit new granular event
771
+ // Emit granular event
903
772
  this.events.onToolCallStateChange?.(
904
773
  this.currentAssistantMessageId,
905
774
  toolCall.id,
@@ -915,9 +784,6 @@ export class StreamProcessor {
915
784
  private emitTextUpdate(): void {
916
785
  this.lastEmittedText = this.currentSegmentText
917
786
 
918
- // Emit legacy handler
919
- this.handlers.onTextUpdate?.(this.currentSegmentText)
920
-
921
787
  // Update UIMessage
922
788
  if (this.currentAssistantMessageId) {
923
789
  this.messages = updateTextPart(
@@ -927,7 +793,7 @@ export class StreamProcessor {
927
793
  )
928
794
  this.emitMessagesChange()
929
795
 
930
- // Emit new granular event
796
+ // Emit granular event
931
797
  this.events.onTextUpdate?.(
932
798
  this.currentAssistantMessageId,
933
799
  this.currentSegmentText,
@@ -954,14 +820,7 @@ export class StreamProcessor {
954
820
  this.emitTextUpdate()
955
821
  }
956
822
 
957
- // Emit legacy stream end with total accumulated content
958
- const toolCalls = this.getCompletedToolCalls()
959
- this.handlers.onStreamEnd?.(
960
- this.totalTextContent,
961
- toolCalls.length > 0 ? toolCalls : undefined,
962
- )
963
-
964
- // Emit new stream end event
823
+ // Emit stream end event
965
824
  if (this.currentAssistantMessageId) {
966
825
  const assistantMessage = this.messages.find(
967
826
  (m) => m.id === this.currentAssistantMessageId,
@@ -1002,7 +861,7 @@ export class StreamProcessor {
1002
861
  }
1003
862
 
1004
863
  /**
1005
- * Get current processor state (legacy)
864
+ * Get current processor state
1006
865
  */
1007
866
  getState(): ProcessorState {
1008
867
  return {