@reverbia/sdk 1.0.0-next.20260110221448 → 1.0.0-next.20260111110909

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.
@@ -105,14 +105,128 @@ function validateToken(token) {
105
105
  }
106
106
  return { valid: true };
107
107
  }
108
- function createStreamAccumulator() {
108
+ function parseReasoningTags(content, previousPartialTag = "") {
109
+ const OPENING_TAG = "<think>";
110
+ const CLOSING_TAG = "</think>";
111
+ const OPENING_TAG_LEN = OPENING_TAG.length;
112
+ const CLOSING_TAG_LEN = CLOSING_TAG.length;
113
+ const fullContent = previousPartialTag + content;
114
+ let messageContent = "";
115
+ let reasoningContent = "";
116
+ let partialTag = "";
117
+ let i = 0;
118
+ let insideReasoning = false;
119
+ if (previousPartialTag) {
120
+ if (previousPartialTag === OPENING_TAG) {
121
+ insideReasoning = true;
122
+ i = OPENING_TAG_LEN;
123
+ } else if (OPENING_TAG.startsWith(previousPartialTag)) {
124
+ if (fullContent.startsWith(OPENING_TAG)) {
125
+ insideReasoning = true;
126
+ i = OPENING_TAG_LEN;
127
+ } else if (OPENING_TAG.startsWith(fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length)))) {
128
+ return {
129
+ messageContent: "",
130
+ reasoningContent: "",
131
+ partialTag: fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length))
132
+ };
133
+ } else {
134
+ messageContent = previousPartialTag;
135
+ i = previousPartialTag.length;
136
+ }
137
+ } else if (CLOSING_TAG.startsWith(previousPartialTag)) {
138
+ if (fullContent.startsWith(CLOSING_TAG)) {
139
+ i = CLOSING_TAG_LEN;
140
+ insideReasoning = false;
141
+ } else if (CLOSING_TAG.startsWith(fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length)))) {
142
+ return {
143
+ messageContent: "",
144
+ reasoningContent: "",
145
+ partialTag: fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length))
146
+ };
147
+ } else {
148
+ reasoningContent = previousPartialTag;
149
+ i = previousPartialTag.length;
150
+ insideReasoning = true;
151
+ }
152
+ } else {
153
+ if (insideReasoning) {
154
+ reasoningContent = previousPartialTag;
155
+ } else {
156
+ messageContent = previousPartialTag;
157
+ }
158
+ i = previousPartialTag.length;
159
+ }
160
+ }
161
+ while (i < fullContent.length) {
162
+ if (insideReasoning) {
163
+ const closeIndex = fullContent.indexOf(CLOSING_TAG, i);
164
+ if (closeIndex === -1) {
165
+ const remaining = fullContent.slice(i);
166
+ if (remaining.length < CLOSING_TAG_LEN) {
167
+ const potentialClose = remaining;
168
+ if (CLOSING_TAG.startsWith(potentialClose)) {
169
+ partialTag = potentialClose;
170
+ } else {
171
+ reasoningContent += remaining;
172
+ }
173
+ } else {
174
+ reasoningContent += remaining;
175
+ }
176
+ break;
177
+ }
178
+ const contentBeforeClose = fullContent.slice(i, closeIndex);
179
+ if (contentBeforeClose) {
180
+ reasoningContent += contentBeforeClose;
181
+ }
182
+ i = closeIndex + CLOSING_TAG_LEN;
183
+ insideReasoning = false;
184
+ } else {
185
+ const openIndex = fullContent.indexOf(OPENING_TAG, i);
186
+ if (openIndex === -1) {
187
+ const remaining = fullContent.slice(i);
188
+ if (remaining.length < OPENING_TAG_LEN) {
189
+ const potentialOpen = remaining;
190
+ if (OPENING_TAG.startsWith(potentialOpen)) {
191
+ partialTag = potentialOpen;
192
+ } else {
193
+ messageContent += remaining;
194
+ }
195
+ } else {
196
+ messageContent += remaining;
197
+ }
198
+ break;
199
+ }
200
+ messageContent += fullContent.slice(i, openIndex);
201
+ i = openIndex + OPENING_TAG_LEN;
202
+ insideReasoning = true;
203
+ }
204
+ }
205
+ if (messageContent.includes(OPENING_TAG) || messageContent.includes(CLOSING_TAG)) {
206
+ console.warn("[parseReasoningTags] Warning: Tag found in messageContent, removing");
207
+ messageContent = messageContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
208
+ messageContent = messageContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
209
+ }
210
+ if (reasoningContent.includes(OPENING_TAG) || reasoningContent.includes(CLOSING_TAG)) {
211
+ console.warn("[parseReasoningTags] Warning: Tag found in reasoningContent, removing");
212
+ reasoningContent = reasoningContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
213
+ reasoningContent = reasoningContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
214
+ }
215
+ return {
216
+ messageContent,
217
+ reasoningContent,
218
+ partialTag
219
+ };
220
+ }
221
+ function createStreamAccumulator(initialModel) {
109
222
  return {
110
223
  content: "",
111
224
  thinking: "",
112
225
  responseId: "",
113
- responseModel: "",
226
+ responseModel: initialModel || "",
114
227
  usage: {},
115
- toolCalls: /* @__PURE__ */ new Map()
228
+ toolCalls: /* @__PURE__ */ new Map(),
229
+ partialReasoningTag: ""
116
230
  };
117
231
  }
118
232
  function processStreamingChunk(chunk, accumulator) {
@@ -427,7 +541,7 @@ var ResponsesStrategy = class {
427
541
  const delta = typedChunk.delta;
428
542
  if (delta) {
429
543
  const deltaText = typeof delta === "string" ? delta : delta.OfString;
430
- if (deltaText) {
544
+ if (deltaText && deltaText.trim().length > 0) {
431
545
  accumulator.content += deltaText;
432
546
  result.content = deltaText;
433
547
  }
@@ -554,8 +668,21 @@ var CompletionsStrategy = class {
554
668
  const choice = typedChunk.choices[0];
555
669
  if (choice.delta) {
556
670
  if (choice.delta.content) {
557
- accumulator.content += choice.delta.content;
558
- result.content = choice.delta.content;
671
+ const parseResult = parseReasoningTags(
672
+ choice.delta.content,
673
+ accumulator.partialReasoningTag || ""
674
+ );
675
+ accumulator.content += parseResult.messageContent;
676
+ accumulator.thinking += parseResult.reasoningContent;
677
+ accumulator.partialReasoningTag = parseResult.partialTag;
678
+ const willEmitMessage = parseResult.messageContent && parseResult.messageContent.trim().length > 0;
679
+ const willEmitReasoning = parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0;
680
+ if (willEmitMessage) {
681
+ result.content = parseResult.messageContent;
682
+ }
683
+ if (willEmitReasoning) {
684
+ result.thinking = parseResult.reasoningContent;
685
+ }
559
686
  }
560
687
  if (choice.delta.tool_calls) {
561
688
  for (const toolCallDelta of choice.delta.tool_calls) {
@@ -584,8 +711,19 @@ var CompletionsStrategy = class {
584
711
  }
585
712
  if (choice.message) {
586
713
  if (choice.message.content) {
587
- accumulator.content = choice.message.content;
588
- result.content = choice.message.content;
714
+ const parseResult = parseReasoningTags(
715
+ choice.message.content,
716
+ accumulator.partialReasoningTag || ""
717
+ );
718
+ accumulator.content = parseResult.messageContent;
719
+ accumulator.thinking += parseResult.reasoningContent;
720
+ accumulator.partialReasoningTag = parseResult.partialTag;
721
+ if (parseResult.messageContent && parseResult.messageContent.trim().length > 0) {
722
+ result.content = parseResult.messageContent;
723
+ }
724
+ if (parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0) {
725
+ result.thinking = parseResult.reasoningContent;
726
+ }
589
727
  }
590
728
  if (choice.message.tool_calls) {
591
729
  for (let i = 0; i < choice.message.tool_calls.length; i++) {
@@ -613,6 +751,23 @@ var CompletionsStrategy = class {
613
751
  }
614
752
  buildFinalResponse(accumulator) {
615
753
  const output = [];
754
+ let finalContent = accumulator.content;
755
+ let finalThinking = accumulator.thinking;
756
+ if (accumulator.partialReasoningTag) {
757
+ const finalParse = parseReasoningTags("", accumulator.partialReasoningTag);
758
+ finalContent += finalParse.messageContent;
759
+ if (finalParse.reasoningContent) {
760
+ finalThinking += finalParse.reasoningContent;
761
+ }
762
+ }
763
+ if (finalThinking) {
764
+ output.push({
765
+ type: "reasoning",
766
+ role: "assistant",
767
+ content: [{ type: "output_text", text: finalThinking }],
768
+ status: "completed"
769
+ });
770
+ }
616
771
  if (accumulator.toolCalls.size > 0) {
617
772
  for (const toolCall of accumulator.toolCalls.values()) {
618
773
  output.push({
@@ -627,7 +782,7 @@ var CompletionsStrategy = class {
627
782
  output.push({
628
783
  type: "message",
629
784
  role: "assistant",
630
- content: [{ type: "output_text", text: accumulator.content }],
785
+ content: [{ type: "output_text", text: finalContent }],
631
786
  status: "completed"
632
787
  });
633
788
  return {
@@ -763,7 +918,7 @@ function useChat(options) {
763
918
  const result = await new Promise((resolve) => {
764
919
  const xhr = new XMLHttpRequest();
765
920
  const url = `${baseUrl}/api/v1/responses`;
766
- const accumulator = createStreamAccumulator();
921
+ const accumulator = createStreamAccumulator(model || void 0);
767
922
  let lastProcessedIndex = 0;
768
923
  let incompleteLineBuffer = "";
769
924
  const abortHandler = () => {
@@ -910,7 +1065,7 @@ function useChat(options) {
910
1065
  const continuationResult = await new Promise(
911
1066
  (continueResolve) => {
912
1067
  const continuationXhr = new XMLHttpRequest();
913
- const continuationAccumulator = createStreamAccumulator();
1068
+ const continuationAccumulator = createStreamAccumulator(model || void 0);
914
1069
  let contLastProcessedIndex = 0;
915
1070
  let contIncompleteLineBuffer = "";
916
1071
  const contAbortHandler = () => {
@@ -1509,7 +1664,7 @@ function storedToLlmapiMessage(stored) {
1509
1664
  const content = [
1510
1665
  { type: "text", text: stored.content }
1511
1666
  ];
1512
- if (stored.files?.length) {
1667
+ if (stored.role !== "assistant" && stored.files?.length) {
1513
1668
  for (const file of stored.files) {
1514
1669
  if (file.url) {
1515
1670
  content.push({
@@ -66,14 +66,128 @@ function validateToken(token) {
66
66
  }
67
67
  return { valid: true };
68
68
  }
69
- function createStreamAccumulator() {
69
+ function parseReasoningTags(content, previousPartialTag = "") {
70
+ const OPENING_TAG = "<think>";
71
+ const CLOSING_TAG = "</think>";
72
+ const OPENING_TAG_LEN = OPENING_TAG.length;
73
+ const CLOSING_TAG_LEN = CLOSING_TAG.length;
74
+ const fullContent = previousPartialTag + content;
75
+ let messageContent = "";
76
+ let reasoningContent = "";
77
+ let partialTag = "";
78
+ let i = 0;
79
+ let insideReasoning = false;
80
+ if (previousPartialTag) {
81
+ if (previousPartialTag === OPENING_TAG) {
82
+ insideReasoning = true;
83
+ i = OPENING_TAG_LEN;
84
+ } else if (OPENING_TAG.startsWith(previousPartialTag)) {
85
+ if (fullContent.startsWith(OPENING_TAG)) {
86
+ insideReasoning = true;
87
+ i = OPENING_TAG_LEN;
88
+ } else if (OPENING_TAG.startsWith(fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length)))) {
89
+ return {
90
+ messageContent: "",
91
+ reasoningContent: "",
92
+ partialTag: fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length))
93
+ };
94
+ } else {
95
+ messageContent = previousPartialTag;
96
+ i = previousPartialTag.length;
97
+ }
98
+ } else if (CLOSING_TAG.startsWith(previousPartialTag)) {
99
+ if (fullContent.startsWith(CLOSING_TAG)) {
100
+ i = CLOSING_TAG_LEN;
101
+ insideReasoning = false;
102
+ } else if (CLOSING_TAG.startsWith(fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length)))) {
103
+ return {
104
+ messageContent: "",
105
+ reasoningContent: "",
106
+ partialTag: fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length))
107
+ };
108
+ } else {
109
+ reasoningContent = previousPartialTag;
110
+ i = previousPartialTag.length;
111
+ insideReasoning = true;
112
+ }
113
+ } else {
114
+ if (insideReasoning) {
115
+ reasoningContent = previousPartialTag;
116
+ } else {
117
+ messageContent = previousPartialTag;
118
+ }
119
+ i = previousPartialTag.length;
120
+ }
121
+ }
122
+ while (i < fullContent.length) {
123
+ if (insideReasoning) {
124
+ const closeIndex = fullContent.indexOf(CLOSING_TAG, i);
125
+ if (closeIndex === -1) {
126
+ const remaining = fullContent.slice(i);
127
+ if (remaining.length < CLOSING_TAG_LEN) {
128
+ const potentialClose = remaining;
129
+ if (CLOSING_TAG.startsWith(potentialClose)) {
130
+ partialTag = potentialClose;
131
+ } else {
132
+ reasoningContent += remaining;
133
+ }
134
+ } else {
135
+ reasoningContent += remaining;
136
+ }
137
+ break;
138
+ }
139
+ const contentBeforeClose = fullContent.slice(i, closeIndex);
140
+ if (contentBeforeClose) {
141
+ reasoningContent += contentBeforeClose;
142
+ }
143
+ i = closeIndex + CLOSING_TAG_LEN;
144
+ insideReasoning = false;
145
+ } else {
146
+ const openIndex = fullContent.indexOf(OPENING_TAG, i);
147
+ if (openIndex === -1) {
148
+ const remaining = fullContent.slice(i);
149
+ if (remaining.length < OPENING_TAG_LEN) {
150
+ const potentialOpen = remaining;
151
+ if (OPENING_TAG.startsWith(potentialOpen)) {
152
+ partialTag = potentialOpen;
153
+ } else {
154
+ messageContent += remaining;
155
+ }
156
+ } else {
157
+ messageContent += remaining;
158
+ }
159
+ break;
160
+ }
161
+ messageContent += fullContent.slice(i, openIndex);
162
+ i = openIndex + OPENING_TAG_LEN;
163
+ insideReasoning = true;
164
+ }
165
+ }
166
+ if (messageContent.includes(OPENING_TAG) || messageContent.includes(CLOSING_TAG)) {
167
+ console.warn("[parseReasoningTags] Warning: Tag found in messageContent, removing");
168
+ messageContent = messageContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
169
+ messageContent = messageContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
170
+ }
171
+ if (reasoningContent.includes(OPENING_TAG) || reasoningContent.includes(CLOSING_TAG)) {
172
+ console.warn("[parseReasoningTags] Warning: Tag found in reasoningContent, removing");
173
+ reasoningContent = reasoningContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
174
+ reasoningContent = reasoningContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
175
+ }
176
+ return {
177
+ messageContent,
178
+ reasoningContent,
179
+ partialTag
180
+ };
181
+ }
182
+ function createStreamAccumulator(initialModel) {
70
183
  return {
71
184
  content: "",
72
185
  thinking: "",
73
186
  responseId: "",
74
- responseModel: "",
187
+ responseModel: initialModel || "",
75
188
  usage: {},
76
- toolCalls: /* @__PURE__ */ new Map()
189
+ toolCalls: /* @__PURE__ */ new Map(),
190
+ partialReasoningTag: ""
77
191
  };
78
192
  }
79
193
  function processStreamingChunk(chunk, accumulator) {
@@ -388,7 +502,7 @@ var ResponsesStrategy = class {
388
502
  const delta = typedChunk.delta;
389
503
  if (delta) {
390
504
  const deltaText = typeof delta === "string" ? delta : delta.OfString;
391
- if (deltaText) {
505
+ if (deltaText && deltaText.trim().length > 0) {
392
506
  accumulator.content += deltaText;
393
507
  result.content = deltaText;
394
508
  }
@@ -515,8 +629,21 @@ var CompletionsStrategy = class {
515
629
  const choice = typedChunk.choices[0];
516
630
  if (choice.delta) {
517
631
  if (choice.delta.content) {
518
- accumulator.content += choice.delta.content;
519
- result.content = choice.delta.content;
632
+ const parseResult = parseReasoningTags(
633
+ choice.delta.content,
634
+ accumulator.partialReasoningTag || ""
635
+ );
636
+ accumulator.content += parseResult.messageContent;
637
+ accumulator.thinking += parseResult.reasoningContent;
638
+ accumulator.partialReasoningTag = parseResult.partialTag;
639
+ const willEmitMessage = parseResult.messageContent && parseResult.messageContent.trim().length > 0;
640
+ const willEmitReasoning = parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0;
641
+ if (willEmitMessage) {
642
+ result.content = parseResult.messageContent;
643
+ }
644
+ if (willEmitReasoning) {
645
+ result.thinking = parseResult.reasoningContent;
646
+ }
520
647
  }
521
648
  if (choice.delta.tool_calls) {
522
649
  for (const toolCallDelta of choice.delta.tool_calls) {
@@ -545,8 +672,19 @@ var CompletionsStrategy = class {
545
672
  }
546
673
  if (choice.message) {
547
674
  if (choice.message.content) {
548
- accumulator.content = choice.message.content;
549
- result.content = choice.message.content;
675
+ const parseResult = parseReasoningTags(
676
+ choice.message.content,
677
+ accumulator.partialReasoningTag || ""
678
+ );
679
+ accumulator.content = parseResult.messageContent;
680
+ accumulator.thinking += parseResult.reasoningContent;
681
+ accumulator.partialReasoningTag = parseResult.partialTag;
682
+ if (parseResult.messageContent && parseResult.messageContent.trim().length > 0) {
683
+ result.content = parseResult.messageContent;
684
+ }
685
+ if (parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0) {
686
+ result.thinking = parseResult.reasoningContent;
687
+ }
550
688
  }
551
689
  if (choice.message.tool_calls) {
552
690
  for (let i = 0; i < choice.message.tool_calls.length; i++) {
@@ -574,6 +712,23 @@ var CompletionsStrategy = class {
574
712
  }
575
713
  buildFinalResponse(accumulator) {
576
714
  const output = [];
715
+ let finalContent = accumulator.content;
716
+ let finalThinking = accumulator.thinking;
717
+ if (accumulator.partialReasoningTag) {
718
+ const finalParse = parseReasoningTags("", accumulator.partialReasoningTag);
719
+ finalContent += finalParse.messageContent;
720
+ if (finalParse.reasoningContent) {
721
+ finalThinking += finalParse.reasoningContent;
722
+ }
723
+ }
724
+ if (finalThinking) {
725
+ output.push({
726
+ type: "reasoning",
727
+ role: "assistant",
728
+ content: [{ type: "output_text", text: finalThinking }],
729
+ status: "completed"
730
+ });
731
+ }
577
732
  if (accumulator.toolCalls.size > 0) {
578
733
  for (const toolCall of accumulator.toolCalls.values()) {
579
734
  output.push({
@@ -588,7 +743,7 @@ var CompletionsStrategy = class {
588
743
  output.push({
589
744
  type: "message",
590
745
  role: "assistant",
591
- content: [{ type: "output_text", text: accumulator.content }],
746
+ content: [{ type: "output_text", text: finalContent }],
592
747
  status: "completed"
593
748
  });
594
749
  return {
@@ -724,7 +879,7 @@ function useChat(options) {
724
879
  const result = await new Promise((resolve) => {
725
880
  const xhr = new XMLHttpRequest();
726
881
  const url = `${baseUrl}/api/v1/responses`;
727
- const accumulator = createStreamAccumulator();
882
+ const accumulator = createStreamAccumulator(model || void 0);
728
883
  let lastProcessedIndex = 0;
729
884
  let incompleteLineBuffer = "";
730
885
  const abortHandler = () => {
@@ -871,7 +1026,7 @@ function useChat(options) {
871
1026
  const continuationResult = await new Promise(
872
1027
  (continueResolve) => {
873
1028
  const continuationXhr = new XMLHttpRequest();
874
- const continuationAccumulator = createStreamAccumulator();
1029
+ const continuationAccumulator = createStreamAccumulator(model || void 0);
875
1030
  let contLastProcessedIndex = 0;
876
1031
  let contIncompleteLineBuffer = "";
877
1032
  const contAbortHandler = () => {
@@ -1473,7 +1628,7 @@ function storedToLlmapiMessage(stored) {
1473
1628
  const content = [
1474
1629
  { type: "text", text: stored.content }
1475
1630
  ];
1476
- if (stored.files?.length) {
1631
+ if (stored.role !== "assistant" && stored.files?.length) {
1477
1632
  for (const file of stored.files) {
1478
1633
  if (file.url) {
1479
1634
  content.push({