@tanstack/openai-base 0.10.2 → 0.10.5

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.
@@ -134,7 +134,8 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
134
134
  * Stream structured output via the Responses API: single request with
135
135
  * `text.format: json_schema` + `stream: true`. Consumes Responses-API
136
136
  * events (`response.output_text.delta`, `response.reasoning_text.delta`,
137
- * `response.reasoning_summary_text.delta`, `response.refusal.delta`,
137
+ * `response.reasoning_summary_text.delta`, the legacy
138
+ * `response.reasoning.delta`, `response.refusal.delta`,
138
139
  * `response.completed`, `response.failed`) and re-emits the standard AG-UI
139
140
  * lifecycle ending with `CUSTOM 'structured-output.complete'`.
140
141
  *
@@ -184,6 +185,9 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
184
185
  timestamp: Date.now(),
185
186
  content: accumulatedReasoning
186
187
  };
188
+ reasoningMessageId = void 0;
189
+ stepId = void 0;
190
+ hasClosedReasoning = false;
187
191
  }
188
192
  }.bind(this);
189
193
  const openReasoning = function* () {
@@ -265,7 +269,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
265
269
  };
266
270
  return;
267
271
  }
268
- if (chunk.type === "response.reasoning_text.delta" || chunk.type === "response.reasoning_summary_text.delta") {
272
+ if (chunk.type === "response.reasoning_text.delta" || chunk.type === "response.reasoning_summary_text.delta" || chunk.type === "response.reasoning.delta") {
269
273
  const raw = chunk.delta;
270
274
  const reasoningDelta = Array.isArray(raw) ? raw.join("") : typeof raw === "string" ? raw : "";
271
275
  if (!reasoningDelta) continue;
@@ -504,6 +508,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
504
508
  * - response.created / response.incomplete / response.failed
505
509
  * - response.output_text.delta
506
510
  * - response.reasoning_text.delta
511
+ * - response.reasoning.delta (the legacy type used before response.reasoning_text.delta)
507
512
  * - response.reasoning_summary_text.delta
508
513
  * - response.content_part.added / response.content_part.done
509
514
  * - response.output_item.added
@@ -520,8 +525,83 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
520
525
  let model = options.model;
521
526
  let stepId = null;
522
527
  let hasEmittedTextMessageStart = false;
523
- let hasEmittedStepStarted = false;
528
+ let reasoningMessageId;
529
+ let hasClosedReasoning = false;
524
530
  let runFinishedEmitted = false;
531
+ const adapterName = this.name;
532
+ const emitModel = () => model || options.model;
533
+ const openReasoning = function* () {
534
+ if (reasoningMessageId) return;
535
+ reasoningMessageId = generateId(adapterName);
536
+ stepId = generateId(adapterName);
537
+ const timestamp = Date.now();
538
+ const currentModel = emitModel();
539
+ yield {
540
+ type: EventType.REASONING_START,
541
+ messageId: reasoningMessageId,
542
+ model: currentModel,
543
+ timestamp
544
+ };
545
+ yield {
546
+ type: EventType.REASONING_MESSAGE_START,
547
+ messageId: reasoningMessageId,
548
+ role: "reasoning",
549
+ model: currentModel,
550
+ timestamp
551
+ };
552
+ yield {
553
+ type: EventType.STEP_STARTED,
554
+ stepName: stepId,
555
+ stepId,
556
+ model: currentModel,
557
+ timestamp,
558
+ stepType: "thinking"
559
+ };
560
+ };
561
+ const closeReasoning = function* () {
562
+ if (!reasoningMessageId || hasClosedReasoning) return;
563
+ hasClosedReasoning = true;
564
+ const timestamp = Date.now();
565
+ const currentModel = emitModel();
566
+ yield {
567
+ type: EventType.REASONING_MESSAGE_END,
568
+ messageId: reasoningMessageId,
569
+ model: currentModel,
570
+ timestamp
571
+ };
572
+ yield {
573
+ type: EventType.REASONING_END,
574
+ messageId: reasoningMessageId,
575
+ model: currentModel,
576
+ timestamp
577
+ };
578
+ if (stepId) yield {
579
+ type: EventType.STEP_FINISHED,
580
+ stepName: stepId,
581
+ stepId,
582
+ model: currentModel,
583
+ timestamp,
584
+ content: accumulatedReasoning
585
+ };
586
+ reasoningMessageId = void 0;
587
+ stepId = null;
588
+ hasClosedReasoning = false;
589
+ accumulatedReasoning = "";
590
+ };
591
+ const emitReasoningDelta = function* (text) {
592
+ if (!text) return;
593
+ yield* openReasoning();
594
+ if (!reasoningMessageId) return;
595
+ accumulatedReasoning += text;
596
+ hasStreamedReasoningDeltas = true;
597
+ yield {
598
+ type: EventType.REASONING_MESSAGE_CONTENT,
599
+ messageId: reasoningMessageId,
600
+ delta: text,
601
+ model: emitModel(),
602
+ timestamp: Date.now()
603
+ };
604
+ };
525
605
  try {
526
606
  for await (const chunk of stream) {
527
607
  options.logger.provider(`provider=${this.name} type=${chunk.type}`, {
@@ -551,19 +631,6 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
551
631
  content: accumulatedContent
552
632
  };
553
633
  }
554
- if (contentPart.type === "reasoning_text") {
555
- accumulatedReasoning += contentPart.text || "";
556
- if (!stepId) stepId = generateId(this.name);
557
- return {
558
- type: EventType.STEP_FINISHED,
559
- stepName: stepId,
560
- stepId,
561
- model: model || options.model,
562
- timestamp: Date.now(),
563
- delta: contentPart.text || "",
564
- content: accumulatedReasoning
565
- };
566
- }
567
634
  const isRefusal = contentPart.type === "refusal";
568
635
  const message = isRefusal ? contentPart.refusal || "Refused without explanation" : `Unsupported response content_part type: ${contentPart.type}`;
569
636
  const code = isRefusal ? "refusal" : contentPart.type;
@@ -584,11 +651,14 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
584
651
  hasStreamedContentDeltas = false;
585
652
  hasStreamedReasoningDeltas = false;
586
653
  hasEmittedTextMessageStart = false;
587
- hasEmittedStepStarted = false;
654
+ reasoningMessageId = void 0;
655
+ hasClosedReasoning = false;
656
+ stepId = null;
588
657
  accumulatedContent = "";
589
658
  accumulatedReasoning = "";
590
659
  }
591
660
  if (chunk.type === "response.failed" || chunk.type === "response.incomplete") {
661
+ yield* closeReasoning();
592
662
  if (hasEmittedTextMessageStart) {
593
663
  yield {
594
664
  type: EventType.TEXT_MESSAGE_END,
@@ -617,6 +687,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
617
687
  if (chunk.type === "response.output_text.delta" && chunk.delta) {
618
688
  const textDelta = Array.isArray(chunk.delta) ? chunk.delta.join("") : typeof chunk.delta === "string" ? chunk.delta : "";
619
689
  if (textDelta) {
690
+ yield* closeReasoning();
620
691
  if (!hasEmittedTextMessageStart) {
621
692
  hasEmittedTextMessageStart = true;
622
693
  yield {
@@ -639,68 +710,17 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
639
710
  };
640
711
  }
641
712
  }
642
- if (chunk.type === "response.reasoning_text.delta" && chunk.delta) {
643
- const reasoningDelta = Array.isArray(chunk.delta) ? chunk.delta.join("") : typeof chunk.delta === "string" ? chunk.delta : "";
644
- if (reasoningDelta) {
645
- if (!hasEmittedStepStarted) {
646
- hasEmittedStepStarted = true;
647
- stepId = generateId(this.name);
648
- yield {
649
- type: EventType.STEP_STARTED,
650
- stepName: stepId,
651
- stepId,
652
- model: model || options.model,
653
- timestamp: Date.now(),
654
- stepType: "thinking"
655
- };
656
- }
657
- accumulatedReasoning += reasoningDelta;
658
- hasStreamedReasoningDeltas = true;
659
- const fallbackStepId = stepId || generateId(this.name);
660
- yield {
661
- type: EventType.STEP_FINISHED,
662
- stepName: fallbackStepId,
663
- stepId: fallbackStepId,
664
- model: model || options.model,
665
- timestamp: Date.now(),
666
- delta: reasoningDelta,
667
- content: accumulatedReasoning
668
- };
669
- }
670
- }
671
- if (chunk.type === "response.reasoning_summary_text.delta" && chunk.delta) {
672
- const summaryDelta = typeof chunk.delta === "string" ? chunk.delta : "";
673
- if (summaryDelta) {
674
- if (!hasEmittedStepStarted) {
675
- hasEmittedStepStarted = true;
676
- stepId = generateId(this.name);
677
- yield {
678
- type: EventType.STEP_STARTED,
679
- stepName: stepId,
680
- stepId,
681
- model: model || options.model,
682
- timestamp: Date.now(),
683
- stepType: "thinking"
684
- };
685
- }
686
- accumulatedReasoning += summaryDelta;
687
- hasStreamedReasoningDeltas = true;
688
- const fallbackStepId = stepId || generateId(this.name);
689
- yield {
690
- type: EventType.STEP_FINISHED,
691
- stepName: fallbackStepId,
692
- stepId: fallbackStepId,
693
- model: model || options.model,
694
- timestamp: Date.now(),
695
- delta: summaryDelta,
696
- content: accumulatedReasoning
697
- };
698
- }
699
- }
713
+ if ((chunk.type === "response.reasoning_text.delta" || chunk.type === "response.reasoning.delta") && chunk.delta) yield* emitReasoningDelta(Array.isArray(chunk.delta) ? chunk.delta.join("") : typeof chunk.delta === "string" ? chunk.delta : "");
714
+ if (chunk.type === "response.reasoning_summary_text.delta" && chunk.delta) yield* emitReasoningDelta(typeof chunk.delta === "string" ? chunk.delta : "");
700
715
  if (chunk.type === "response.content_part.added") {
701
716
  const contentPart = chunk.part;
702
717
  if ((contentPart.type === "output_text" || contentPart.type === "reasoning_text") && !contentPart.text) continue;
718
+ if (contentPart.type === "reasoning_text") {
719
+ yield* emitReasoningDelta(contentPart.text || "");
720
+ continue;
721
+ }
703
722
  if (contentPart.type === "output_text" && !hasEmittedTextMessageStart) {
723
+ yield* closeReasoning();
704
724
  hasEmittedTextMessageStart = true;
705
725
  yield {
706
726
  type: EventType.TEXT_MESSAGE_START,
@@ -710,20 +730,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
710
730
  role: "assistant"
711
731
  };
712
732
  }
713
- if (contentPart.type === "reasoning_text" && !hasEmittedStepStarted) {
714
- hasEmittedStepStarted = true;
715
- stepId = generateId(this.name);
716
- yield {
717
- type: EventType.STEP_STARTED,
718
- stepName: stepId,
719
- stepId,
720
- model: model || options.model,
721
- timestamp: Date.now(),
722
- stepType: "thinking"
723
- };
724
- }
725
733
  if (contentPart.type === "output_text") hasStreamedContentDeltas = true;
726
- else if (contentPart.type === "reasoning_text") hasStreamedReasoningDeltas = true;
727
734
  const partChunk = handleContentPart(contentPart);
728
735
  yield partChunk;
729
736
  if (partChunk.type === "RUN_ERROR") {
@@ -735,7 +742,12 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
735
742
  const contentPart = chunk.part;
736
743
  if (contentPart.type === "output_text" && hasStreamedContentDeltas) continue;
737
744
  if (contentPart.type === "reasoning_text" && hasStreamedReasoningDeltas) continue;
745
+ if (contentPart.type === "reasoning_text") {
746
+ yield* emitReasoningDelta(contentPart.text || "");
747
+ continue;
748
+ }
738
749
  if (contentPart.type === "output_text" && !hasEmittedTextMessageStart) {
750
+ yield* closeReasoning();
739
751
  hasEmittedTextMessageStart = true;
740
752
  yield {
741
753
  type: EventType.TEXT_MESSAGE_START,
@@ -744,17 +756,6 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
744
756
  timestamp: Date.now(),
745
757
  role: "assistant"
746
758
  };
747
- } else if (contentPart.type === "reasoning_text" && !hasEmittedStepStarted) {
748
- hasEmittedStepStarted = true;
749
- stepId = generateId(this.name);
750
- yield {
751
- type: EventType.STEP_STARTED,
752
- stepName: stepId,
753
- stepId,
754
- model: model || options.model,
755
- timestamp: Date.now(),
756
- stepType: "thinking"
757
- };
758
759
  }
759
760
  const doneChunk = handleContentPart(contentPart);
760
761
  yield doneChunk;
@@ -996,6 +997,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
996
997
  metadata.pendingArguments = void 0;
997
998
  }
998
999
  }
1000
+ yield* closeReasoning();
999
1001
  if (hasEmittedTextMessageStart) {
1000
1002
  yield {
1001
1003
  type: EventType.TEXT_MESSAGE_END,
@@ -1037,6 +1039,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
1037
1039
  }
1038
1040
  }
1039
1041
  if (!runFinishedEmitted && aguiState.hasEmittedRunStarted) {
1042
+ yield* closeReasoning();
1040
1043
  if (hasEmittedTextMessageStart) yield {
1041
1044
  type: EventType.TEXT_MESSAGE_END,
1042
1045
  messageId: aguiState.messageId,
@@ -1235,7 +1238,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
1235
1238
  * Handles backward compatibility with string content.
1236
1239
  */
1237
1240
  normalizeContent(content) {
1238
- if (content === null) return [];
1241
+ if (content === null || content === void 0) return [];
1239
1242
  if (typeof content === "string") return [{
1240
1243
  type: "text",
1241
1244
  content
@@ -1246,7 +1249,7 @@ var OpenAIBaseResponsesTextAdapter = class extends BaseTextAdapter {
1246
1249
  * Extracts text content from a content value that may be string, null, or ContentPart array.
1247
1250
  */
1248
1251
  extractTextContent(content) {
1249
- if (content === null) return "";
1252
+ if (content === null || content === void 0) return "";
1250
1253
  if (typeof content === "string") return content;
1251
1254
  return content.filter((p) => p.type === "text").map((p) => p.content).join("");
1252
1255
  }