@octavus/client-sdk 2.2.0 → 2.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.
package/dist/index.js CHANGED
@@ -161,7 +161,8 @@ function createEmptyStreamingState() {
161
161
  currentTextPartIndex: null,
162
162
  currentReasoningPartIndex: null,
163
163
  currentObjectPartIndex: null,
164
- accumulatedJson: ""
164
+ accumulatedJson: "",
165
+ activeWorkers: /* @__PURE__ */ new Map()
165
166
  };
166
167
  }
167
168
  function buildMessageFromState(state, status) {
@@ -173,6 +174,36 @@ function buildMessageFromState(state, status) {
173
174
  createdAt: /* @__PURE__ */ new Date()
174
175
  };
175
176
  }
177
+ function finalizeParts(parts, workerError) {
178
+ return parts.map((part) => {
179
+ if (part.type === "text" || part.type === "reasoning") {
180
+ if (part.status === "streaming") {
181
+ return { ...part, status: "done" };
182
+ }
183
+ }
184
+ if (part.type === "object" && part.status === "streaming") {
185
+ return { ...part, status: "done" };
186
+ }
187
+ if (part.type === "tool-call") {
188
+ if (part.status === "pending" || part.status === "running") {
189
+ return { ...part, status: "cancelled" };
190
+ }
191
+ }
192
+ if (part.type === "operation" && part.status === "running") {
193
+ return { ...part, status: "cancelled" };
194
+ }
195
+ if (part.type === "worker" && part.status === "running") {
196
+ return {
197
+ ...part,
198
+ status: "error",
199
+ error: workerError,
200
+ parts: finalizeParts(part.parts)
201
+ // Recursive for nested parts
202
+ };
203
+ }
204
+ return part;
205
+ });
206
+ }
176
207
  var OctavusChat = class {
177
208
  // Private state
178
209
  _messages;
@@ -373,25 +404,7 @@ var OctavusChat = class {
373
404
  const messages = [...this._messages];
374
405
  const lastMsg = messages[messages.length - 1];
375
406
  if (state.parts.length > 0) {
376
- const finalParts = state.parts.map((part) => {
377
- if (part.type === "text" || part.type === "reasoning") {
378
- if (part.status === "streaming") {
379
- return { ...part, status: "done" };
380
- }
381
- }
382
- if (part.type === "object" && part.status === "streaming") {
383
- return { ...part, status: "done" };
384
- }
385
- if (part.type === "tool-call") {
386
- if (part.status === "pending" || part.status === "running") {
387
- return { ...part, status: "cancelled" };
388
- }
389
- }
390
- if (part.type === "operation" && part.status === "running") {
391
- return { ...part, status: "cancelled" };
392
- }
393
- return part;
394
- });
407
+ const finalParts = finalizeParts(state.parts, "Stream error");
395
408
  const finalMessage = {
396
409
  id: state.messageId,
397
410
  role: "assistant",
@@ -468,7 +481,9 @@ var OctavusChat = class {
468
481
  result: error ? void 0 : result,
469
482
  error,
470
483
  outputVariable: pendingTool.outputVariable,
471
- blockIndex: pendingTool.blockIndex
484
+ blockIndex: pendingTool.blockIndex,
485
+ thread: pendingTool.thread,
486
+ workerId: pendingTool.workerId
472
487
  };
473
488
  this._completedToolResults.push(toolResult);
474
489
  if (error) {
@@ -499,33 +514,7 @@ var OctavusChat = class {
499
514
  this.transport.stop();
500
515
  const state = this.streamingState;
501
516
  if (state && state.parts.length > 0) {
502
- const finalParts = state.parts.map((part) => {
503
- if (part.type === "tool-call") {
504
- const toolPart = part;
505
- if (toolPart.status === "pending" || toolPart.status === "running") {
506
- return { ...toolPart, status: "cancelled" };
507
- }
508
- }
509
- if (part.type === "operation") {
510
- const opPart = part;
511
- if (opPart.status === "running") {
512
- return { ...opPart, status: "cancelled" };
513
- }
514
- }
515
- if (part.type === "text" || part.type === "reasoning") {
516
- const textPart = part;
517
- if (textPart.status === "streaming") {
518
- return { ...textPart, status: "done" };
519
- }
520
- }
521
- if (part.type === "object") {
522
- const objPart = part;
523
- if (objPart.status === "streaming") {
524
- return { ...objPart, status: "done" };
525
- }
526
- }
527
- return part;
528
- });
517
+ const finalParts = finalizeParts(state.parts, "Stopped by user");
529
518
  const finalMessage = {
530
519
  id: state.messageId,
531
520
  role: "assistant",
@@ -552,8 +541,13 @@ var OctavusChat = class {
552
541
  handleStreamEvent(event, state) {
553
542
  switch (event.type) {
554
543
  case "start":
544
+ if (event.executionId) {
545
+ this.options.onStart?.(event.executionId);
546
+ }
555
547
  break;
556
548
  case "block-start": {
549
+ const workerId = event.workerId;
550
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
557
551
  const block = {
558
552
  blockId: event.blockId,
559
553
  blockName: event.blockName,
@@ -580,7 +574,13 @@ var OctavusChat = class {
580
574
  status: "running",
581
575
  thread: threadForPart(thread)
582
576
  };
583
- state.parts.push(operationPart);
577
+ if (workerState) {
578
+ const workerPart = state.parts[workerState.partIndex];
579
+ workerPart.parts.push(operationPart);
580
+ state.parts[workerState.partIndex] = { ...workerPart };
581
+ } else {
582
+ state.parts.push(operationPart);
583
+ }
584
584
  }
585
585
  state.currentTextPartIndex = null;
586
586
  state.currentReasoningPartIndex = null;
@@ -588,12 +588,26 @@ var OctavusChat = class {
588
588
  break;
589
589
  }
590
590
  case "block-end": {
591
- const operationPartIndex = state.parts.findIndex(
592
- (p) => p.type === "operation" && p.operationId === event.blockId
593
- );
594
- if (operationPartIndex >= 0) {
595
- const part = state.parts[operationPartIndex];
596
- state.parts[operationPartIndex] = { ...part, status: "done" };
591
+ const workerId = event.workerId;
592
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
593
+ if (workerState) {
594
+ const workerPart = state.parts[workerState.partIndex];
595
+ const operationPartIndex = workerPart.parts.findIndex(
596
+ (p) => p.type === "operation" && p.operationId === event.blockId
597
+ );
598
+ if (operationPartIndex >= 0) {
599
+ const part = workerPart.parts[operationPartIndex];
600
+ workerPart.parts[operationPartIndex] = { ...part, status: "done" };
601
+ state.parts[workerState.partIndex] = { ...workerPart };
602
+ }
603
+ } else {
604
+ const operationPartIndex = state.parts.findIndex(
605
+ (p) => p.type === "operation" && p.operationId === event.blockId
606
+ );
607
+ if (operationPartIndex >= 0) {
608
+ const part = state.parts[operationPartIndex];
609
+ state.parts[operationPartIndex] = { ...part, status: "done" };
610
+ }
597
611
  }
598
612
  if (state.activeBlock?.blockId === event.blockId) {
599
613
  state.activeBlock = null;
@@ -602,31 +616,63 @@ var OctavusChat = class {
602
616
  break;
603
617
  }
604
618
  case "reasoning-start": {
619
+ const workerId = event.workerId;
620
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
605
621
  const reasoningPart = {
606
622
  type: "reasoning",
607
623
  text: "",
608
624
  status: "streaming",
609
625
  thread: threadForPart(state.activeBlock?.thread)
610
626
  };
611
- state.parts.push(reasoningPart);
612
- state.currentReasoningPartIndex = state.parts.length - 1;
627
+ if (workerState) {
628
+ const workerPart = state.parts[workerState.partIndex];
629
+ workerPart.parts.push(reasoningPart);
630
+ workerState.currentReasoningPartIndex = workerPart.parts.length - 1;
631
+ state.parts[workerState.partIndex] = { ...workerPart };
632
+ } else {
633
+ state.parts.push(reasoningPart);
634
+ state.currentReasoningPartIndex = state.parts.length - 1;
635
+ }
613
636
  this.updateStreamingMessage();
614
637
  break;
615
638
  }
616
639
  case "reasoning-delta": {
617
- if (state.currentReasoningPartIndex !== null) {
618
- const part = state.parts[state.currentReasoningPartIndex];
619
- part.text += event.delta;
620
- state.parts[state.currentReasoningPartIndex] = { ...part };
621
- }
622
- if (state.activeBlock) {
623
- state.activeBlock.reasoning += event.delta;
640
+ const workerId = event.workerId;
641
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
642
+ if (workerState) {
643
+ if (workerState.currentReasoningPartIndex !== null) {
644
+ const workerPart = state.parts[workerState.partIndex];
645
+ const part = workerPart.parts[workerState.currentReasoningPartIndex];
646
+ part.text += event.delta;
647
+ workerPart.parts[workerState.currentReasoningPartIndex] = { ...part };
648
+ state.parts[workerState.partIndex] = { ...workerPart };
649
+ }
650
+ } else {
651
+ if (state.currentReasoningPartIndex !== null) {
652
+ const part = state.parts[state.currentReasoningPartIndex];
653
+ part.text += event.delta;
654
+ state.parts[state.currentReasoningPartIndex] = { ...part };
655
+ }
656
+ if (state.activeBlock) {
657
+ state.activeBlock.reasoning += event.delta;
658
+ }
624
659
  }
625
660
  this.updateStreamingMessage();
626
661
  break;
627
662
  }
628
663
  case "reasoning-end": {
629
- if (state.currentReasoningPartIndex !== null) {
664
+ const workerId = event.workerId;
665
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
666
+ if (workerState) {
667
+ if (workerState.currentReasoningPartIndex !== null) {
668
+ const workerPart = state.parts[workerState.partIndex];
669
+ const part = workerPart.parts[workerState.currentReasoningPartIndex];
670
+ part.status = "done";
671
+ workerPart.parts[workerState.currentReasoningPartIndex] = { ...part };
672
+ state.parts[workerState.partIndex] = { ...workerPart };
673
+ workerState.currentReasoningPartIndex = null;
674
+ }
675
+ } else if (state.currentReasoningPartIndex !== null) {
630
676
  const part = state.parts[state.currentReasoningPartIndex];
631
677
  part.status = "done";
632
678
  state.parts[state.currentReasoningPartIndex] = { ...part };
@@ -636,9 +682,11 @@ var OctavusChat = class {
636
682
  break;
637
683
  }
638
684
  case "text-start": {
685
+ const workerId = event.workerId;
686
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
639
687
  const thread = threadForPart(state.activeBlock?.thread);
640
688
  const shouldAddPart = state.activeBlock?.outputToChat !== false || thread !== void 0;
641
- if (shouldAddPart) {
689
+ if (workerState || shouldAddPart) {
642
690
  if (event.responseType) {
643
691
  const objectPart = {
644
692
  type: "object",
@@ -649,10 +697,19 @@ var OctavusChat = class {
649
697
  status: "streaming",
650
698
  thread
651
699
  };
652
- state.parts.push(objectPart);
653
- state.currentObjectPartIndex = state.parts.length - 1;
654
- state.accumulatedJson = "";
655
- state.currentTextPartIndex = null;
700
+ if (workerState) {
701
+ const workerPart = state.parts[workerState.partIndex];
702
+ workerPart.parts.push(objectPart);
703
+ workerState.currentObjectPartIndex = workerPart.parts.length - 1;
704
+ workerState.accumulatedJson = "";
705
+ workerState.currentTextPartIndex = null;
706
+ state.parts[workerState.partIndex] = { ...workerPart };
707
+ } else {
708
+ state.parts.push(objectPart);
709
+ state.currentObjectPartIndex = state.parts.length - 1;
710
+ state.accumulatedJson = "";
711
+ state.currentTextPartIndex = null;
712
+ }
656
713
  } else {
657
714
  const textPart = {
658
715
  type: "text",
@@ -660,36 +717,89 @@ var OctavusChat = class {
660
717
  status: "streaming",
661
718
  thread
662
719
  };
663
- state.parts.push(textPart);
664
- state.currentTextPartIndex = state.parts.length - 1;
665
- state.currentObjectPartIndex = null;
720
+ if (workerState) {
721
+ const workerPart = state.parts[workerState.partIndex];
722
+ workerPart.parts.push(textPart);
723
+ workerState.currentTextPartIndex = workerPart.parts.length - 1;
724
+ workerState.currentObjectPartIndex = null;
725
+ state.parts[workerState.partIndex] = { ...workerPart };
726
+ } else {
727
+ state.parts.push(textPart);
728
+ state.currentTextPartIndex = state.parts.length - 1;
729
+ state.currentObjectPartIndex = null;
730
+ }
666
731
  }
667
732
  }
668
733
  this.updateStreamingMessage();
669
734
  break;
670
735
  }
671
736
  case "text-delta": {
672
- if (state.currentObjectPartIndex !== null) {
673
- state.accumulatedJson += event.delta;
674
- const part = state.parts[state.currentObjectPartIndex];
675
- const parsed = parsePartialJson(state.accumulatedJson);
676
- if (parsed !== void 0) {
677
- part.partial = parsed;
678
- state.parts[state.currentObjectPartIndex] = { ...part };
737
+ const workerId = event.workerId;
738
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
739
+ if (workerState) {
740
+ const workerPart = state.parts[workerState.partIndex];
741
+ if (workerState.currentObjectPartIndex !== null) {
742
+ workerState.accumulatedJson += event.delta;
743
+ const part = workerPart.parts[workerState.currentObjectPartIndex];
744
+ const parsed = parsePartialJson(workerState.accumulatedJson);
745
+ if (parsed !== void 0) {
746
+ part.partial = parsed;
747
+ workerPart.parts[workerState.currentObjectPartIndex] = { ...part };
748
+ }
749
+ } else if (workerState.currentTextPartIndex !== null) {
750
+ const part = workerPart.parts[workerState.currentTextPartIndex];
751
+ part.text += event.delta;
752
+ workerPart.parts[workerState.currentTextPartIndex] = { ...part };
753
+ }
754
+ state.parts[workerState.partIndex] = { ...workerPart };
755
+ } else {
756
+ if (state.currentObjectPartIndex !== null) {
757
+ state.accumulatedJson += event.delta;
758
+ const part = state.parts[state.currentObjectPartIndex];
759
+ const parsed = parsePartialJson(state.accumulatedJson);
760
+ if (parsed !== void 0) {
761
+ part.partial = parsed;
762
+ state.parts[state.currentObjectPartIndex] = { ...part };
763
+ }
764
+ } else if (state.currentTextPartIndex !== null) {
765
+ const part = state.parts[state.currentTextPartIndex];
766
+ part.text += event.delta;
767
+ state.parts[state.currentTextPartIndex] = { ...part };
768
+ }
769
+ if (state.activeBlock) {
770
+ state.activeBlock.text += event.delta;
679
771
  }
680
- } else if (state.currentTextPartIndex !== null) {
681
- const part = state.parts[state.currentTextPartIndex];
682
- part.text += event.delta;
683
- state.parts[state.currentTextPartIndex] = { ...part };
684
- }
685
- if (state.activeBlock) {
686
- state.activeBlock.text += event.delta;
687
772
  }
688
773
  this.updateStreamingMessage();
689
774
  break;
690
775
  }
691
776
  case "text-end": {
692
- if (state.currentObjectPartIndex !== null) {
777
+ const workerId = event.workerId;
778
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
779
+ if (workerState) {
780
+ const workerPart = state.parts[workerState.partIndex];
781
+ if (workerState.currentObjectPartIndex !== null) {
782
+ const part = workerPart.parts[workerState.currentObjectPartIndex];
783
+ try {
784
+ const finalObject = JSON.parse(workerState.accumulatedJson);
785
+ part.object = finalObject;
786
+ part.partial = finalObject;
787
+ part.status = "done";
788
+ } catch {
789
+ part.status = "error";
790
+ part.error = "Failed to parse response as JSON";
791
+ }
792
+ workerPart.parts[workerState.currentObjectPartIndex] = { ...part };
793
+ workerState.currentObjectPartIndex = null;
794
+ workerState.accumulatedJson = "";
795
+ } else if (workerState.currentTextPartIndex !== null) {
796
+ const part = workerPart.parts[workerState.currentTextPartIndex];
797
+ part.status = "done";
798
+ workerPart.parts[workerState.currentTextPartIndex] = { ...part };
799
+ workerState.currentTextPartIndex = null;
800
+ }
801
+ state.parts[workerState.partIndex] = { ...workerPart };
802
+ } else if (state.currentObjectPartIndex !== null) {
693
803
  const part = state.parts[state.currentObjectPartIndex];
694
804
  try {
695
805
  const finalObject = JSON.parse(state.accumulatedJson);
@@ -713,6 +823,8 @@ var OctavusChat = class {
713
823
  break;
714
824
  }
715
825
  case "tool-input-start": {
826
+ const workerId = event.workerId;
827
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
716
828
  const toolPart = {
717
829
  type: "tool-call",
718
830
  toolCallId: event.toolCallId,
@@ -722,24 +834,49 @@ var OctavusChat = class {
722
834
  status: "pending",
723
835
  thread: threadForPart(state.activeBlock?.thread)
724
836
  };
725
- state.parts.push(toolPart);
726
- if (state.activeBlock) {
727
- state.activeBlock.toolCalls.set(event.toolCallId, toolPart);
837
+ if (workerState) {
838
+ const workerPart = state.parts[workerState.partIndex];
839
+ workerPart.parts.push(toolPart);
840
+ state.parts[workerState.partIndex] = { ...workerPart };
841
+ } else {
842
+ state.parts.push(toolPart);
843
+ if (state.activeBlock) {
844
+ state.activeBlock.toolCalls.set(event.toolCallId, toolPart);
845
+ }
728
846
  }
729
847
  this.updateStreamingMessage();
730
848
  break;
731
849
  }
732
850
  case "tool-input-delta": {
733
- const toolPartIndex = state.parts.findIndex(
734
- (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
735
- );
736
- if (toolPartIndex >= 0) {
737
- try {
738
- const part = state.parts[toolPartIndex];
739
- part.args = JSON.parse(event.inputTextDelta);
740
- state.parts[toolPartIndex] = { ...part };
741
- this.updateStreamingMessage();
742
- } catch {
851
+ const workerId = event.workerId;
852
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
853
+ if (workerState) {
854
+ const workerPart = state.parts[workerState.partIndex];
855
+ const toolPartIndex = workerPart.parts.findIndex(
856
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
857
+ );
858
+ if (toolPartIndex >= 0) {
859
+ try {
860
+ const part = workerPart.parts[toolPartIndex];
861
+ part.args = JSON.parse(event.inputTextDelta);
862
+ workerPart.parts[toolPartIndex] = { ...part };
863
+ state.parts[workerState.partIndex] = { ...workerPart };
864
+ this.updateStreamingMessage();
865
+ } catch {
866
+ }
867
+ }
868
+ } else {
869
+ const toolPartIndex = state.parts.findIndex(
870
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
871
+ );
872
+ if (toolPartIndex >= 0) {
873
+ try {
874
+ const part = state.parts[toolPartIndex];
875
+ part.args = JSON.parse(event.inputTextDelta);
876
+ state.parts[toolPartIndex] = { ...part };
877
+ this.updateStreamingMessage();
878
+ } catch {
879
+ }
743
880
  }
744
881
  }
745
882
  break;
@@ -747,45 +884,98 @@ var OctavusChat = class {
747
884
  case "tool-input-end":
748
885
  break;
749
886
  case "tool-input-available": {
750
- const toolPartIndex = state.parts.findIndex(
751
- (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
752
- );
753
- if (toolPartIndex >= 0) {
754
- const part = state.parts[toolPartIndex];
755
- part.args = event.input;
756
- part.status = "running";
757
- state.parts[toolPartIndex] = { ...part };
758
- this.updateStreamingMessage();
887
+ const workerId = event.workerId;
888
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
889
+ if (workerState) {
890
+ const workerPart = state.parts[workerState.partIndex];
891
+ const toolPartIndex = workerPart.parts.findIndex(
892
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
893
+ );
894
+ if (toolPartIndex >= 0) {
895
+ const part = workerPart.parts[toolPartIndex];
896
+ part.args = event.input;
897
+ part.status = "running";
898
+ workerPart.parts[toolPartIndex] = { ...part };
899
+ state.parts[workerState.partIndex] = { ...workerPart };
900
+ this.updateStreamingMessage();
901
+ }
902
+ } else {
903
+ const toolPartIndex = state.parts.findIndex(
904
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
905
+ );
906
+ if (toolPartIndex >= 0) {
907
+ const part = state.parts[toolPartIndex];
908
+ part.args = event.input;
909
+ part.status = "running";
910
+ state.parts[toolPartIndex] = { ...part };
911
+ this.updateStreamingMessage();
912
+ }
759
913
  }
760
914
  break;
761
915
  }
762
916
  case "tool-output-available": {
763
- const toolPartIndex = state.parts.findIndex(
764
- (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
765
- );
766
- if (toolPartIndex >= 0) {
767
- const part = state.parts[toolPartIndex];
768
- part.result = event.output;
769
- part.status = "done";
770
- state.parts[toolPartIndex] = { ...part };
771
- this.updateStreamingMessage();
917
+ const workerId = event.workerId;
918
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
919
+ if (workerState) {
920
+ const workerPart = state.parts[workerState.partIndex];
921
+ const toolPartIndex = workerPart.parts.findIndex(
922
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
923
+ );
924
+ if (toolPartIndex >= 0) {
925
+ const part = workerPart.parts[toolPartIndex];
926
+ part.result = event.output;
927
+ part.status = "done";
928
+ workerPart.parts[toolPartIndex] = { ...part };
929
+ state.parts[workerState.partIndex] = { ...workerPart };
930
+ this.updateStreamingMessage();
931
+ }
932
+ } else {
933
+ const toolPartIndex = state.parts.findIndex(
934
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
935
+ );
936
+ if (toolPartIndex >= 0) {
937
+ const part = state.parts[toolPartIndex];
938
+ part.result = event.output;
939
+ part.status = "done";
940
+ state.parts[toolPartIndex] = { ...part };
941
+ this.updateStreamingMessage();
942
+ }
772
943
  }
773
944
  break;
774
945
  }
775
946
  case "tool-output-error": {
776
- const toolPartIndex = state.parts.findIndex(
777
- (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
778
- );
779
- if (toolPartIndex >= 0) {
780
- const part = state.parts[toolPartIndex];
781
- part.error = event.error;
782
- part.status = "error";
783
- state.parts[toolPartIndex] = { ...part };
784
- this.updateStreamingMessage();
947
+ const workerId = event.workerId;
948
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
949
+ if (workerState) {
950
+ const workerPart = state.parts[workerState.partIndex];
951
+ const toolPartIndex = workerPart.parts.findIndex(
952
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
953
+ );
954
+ if (toolPartIndex >= 0) {
955
+ const part = workerPart.parts[toolPartIndex];
956
+ part.error = event.error;
957
+ part.status = "error";
958
+ workerPart.parts[toolPartIndex] = { ...part };
959
+ state.parts[workerState.partIndex] = { ...workerPart };
960
+ this.updateStreamingMessage();
961
+ }
962
+ } else {
963
+ const toolPartIndex = state.parts.findIndex(
964
+ (p) => p.type === "tool-call" && p.toolCallId === event.toolCallId
965
+ );
966
+ if (toolPartIndex >= 0) {
967
+ const part = state.parts[toolPartIndex];
968
+ part.error = event.error;
969
+ part.status = "error";
970
+ state.parts[toolPartIndex] = { ...part };
971
+ this.updateStreamingMessage();
972
+ }
785
973
  }
786
974
  break;
787
975
  }
788
976
  case "source": {
977
+ const workerId = event.workerId;
978
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
789
979
  const thread = threadForPart(state.activeBlock?.thread);
790
980
  let sourcePart;
791
981
  if (event.sourceType === "url") {
@@ -808,11 +998,19 @@ var OctavusChat = class {
808
998
  thread
809
999
  };
810
1000
  }
811
- state.parts.push(sourcePart);
1001
+ if (workerState) {
1002
+ const workerPart = state.parts[workerState.partIndex];
1003
+ workerPart.parts.push(sourcePart);
1004
+ state.parts[workerState.partIndex] = { ...workerPart };
1005
+ } else {
1006
+ state.parts.push(sourcePart);
1007
+ }
812
1008
  this.updateStreamingMessage();
813
1009
  break;
814
1010
  }
815
1011
  case "file-available": {
1012
+ const workerId = event.workerId;
1013
+ const workerState = workerId ? state.activeWorkers.get(workerId) : void 0;
816
1014
  const filePart = {
817
1015
  type: "file",
818
1016
  id: event.id,
@@ -823,13 +1021,75 @@ var OctavusChat = class {
823
1021
  toolCallId: event.toolCallId,
824
1022
  thread: threadForPart(state.activeBlock?.thread)
825
1023
  };
826
- state.parts.push(filePart);
1024
+ if (workerState) {
1025
+ const workerPart = state.parts[workerState.partIndex];
1026
+ workerPart.parts.push(filePart);
1027
+ state.parts[workerState.partIndex] = { ...workerPart };
1028
+ } else {
1029
+ state.parts.push(filePart);
1030
+ }
827
1031
  this.updateStreamingMessage();
828
1032
  break;
829
1033
  }
830
1034
  case "resource-update":
831
1035
  this.options.onResourceUpdate?.(event.name, event.value);
832
1036
  break;
1037
+ case "worker-start": {
1038
+ const existingIndex = state.parts.findIndex(
1039
+ (p) => p.type === "worker" && p.workerId === event.workerId
1040
+ );
1041
+ let partIndex;
1042
+ if (existingIndex !== -1) {
1043
+ const existingPart = state.parts[existingIndex];
1044
+ existingPart.status = "running";
1045
+ partIndex = existingIndex;
1046
+ } else {
1047
+ const workerPart = {
1048
+ type: "worker",
1049
+ workerId: event.workerId,
1050
+ workerSlug: event.workerSlug,
1051
+ description: event.description,
1052
+ parts: [],
1053
+ status: "running"
1054
+ };
1055
+ state.parts.push(workerPart);
1056
+ partIndex = state.parts.length - 1;
1057
+ }
1058
+ const workerState = {
1059
+ partIndex,
1060
+ currentTextPartIndex: null,
1061
+ currentReasoningPartIndex: null,
1062
+ currentObjectPartIndex: null,
1063
+ accumulatedJson: ""
1064
+ };
1065
+ state.activeWorkers.set(event.workerId, workerState);
1066
+ this.updateStreamingMessage();
1067
+ break;
1068
+ }
1069
+ case "worker-result": {
1070
+ const workerState = state.activeWorkers.get(event.workerId);
1071
+ if (workerState !== void 0) {
1072
+ const part = state.parts[workerState.partIndex];
1073
+ part.output = event.output;
1074
+ part.error = event.error;
1075
+ part.status = event.error ? "error" : "done";
1076
+ part.parts = part.parts.map((p) => {
1077
+ if (p.type === "text" || p.type === "reasoning") {
1078
+ if (p.status === "streaming") {
1079
+ return { ...p, status: "done" };
1080
+ }
1081
+ }
1082
+ if (p.type === "object" && p.status === "streaming") {
1083
+ return { ...p, status: "done" };
1084
+ }
1085
+ return p;
1086
+ });
1087
+ state.parts[workerState.partIndex] = { ...part };
1088
+ state.activeWorkers.delete(event.workerId);
1089
+ }
1090
+ this.updateStreamingMessage();
1091
+ break;
1092
+ }
833
1093
  case "finish": {
834
1094
  if (event.finishReason === "client-tool-calls") {
835
1095
  this._finishEventReceived = true;
@@ -994,7 +1254,9 @@ var OctavusChat = class {
994
1254
  args: tc.args,
995
1255
  source: tc.source,
996
1256
  outputVariable: tc.outputVariable,
997
- blockIndex: tc.blockIndex
1257
+ blockIndex: tc.blockIndex,
1258
+ thread: tc.thread,
1259
+ workerId: tc.workerId
998
1260
  };
999
1261
  this._pendingToolsByCallId.set(tc.toolCallId, toolState);
1000
1262
  const existing = this._pendingToolsByName.get(tc.toolName) ?? [];
@@ -1026,7 +1288,9 @@ var OctavusChat = class {
1026
1288
  toolName: tc.toolName,
1027
1289
  result,
1028
1290
  outputVariable: tc.outputVariable,
1029
- blockIndex: tc.blockIndex
1291
+ blockIndex: tc.blockIndex,
1292
+ thread: tc.thread,
1293
+ workerId: tc.workerId
1030
1294
  });
1031
1295
  this.emitToolOutputAvailable(tc.toolCallId, result);
1032
1296
  } catch (err) {
@@ -1036,7 +1300,9 @@ var OctavusChat = class {
1036
1300
  toolName: tc.toolName,
1037
1301
  error: errorMessage,
1038
1302
  outputVariable: tc.outputVariable,
1039
- blockIndex: tc.blockIndex
1303
+ blockIndex: tc.blockIndex,
1304
+ thread: tc.thread,
1305
+ workerId: tc.workerId
1040
1306
  });
1041
1307
  this.emitToolOutputError(tc.toolCallId, errorMessage);
1042
1308
  }
@@ -1047,7 +1313,9 @@ var OctavusChat = class {
1047
1313
  toolName: tc.toolName,
1048
1314
  error: errorMessage,
1049
1315
  outputVariable: tc.outputVariable,
1050
- blockIndex: tc.blockIndex
1316
+ blockIndex: tc.blockIndex,
1317
+ thread: tc.thread,
1318
+ workerId: tc.workerId
1051
1319
  });
1052
1320
  this.emitToolOutputError(tc.toolCallId, errorMessage);
1053
1321
  }