@librechat/agents 3.3.13 → 3.4.1

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 (192) hide show
  1. package/dist/cjs/graphs/Graph.cjs +121 -27
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hooks/HookRegistry.cjs +83 -0
  4. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  5. package/dist/cjs/hooks/executeHooks.cjs +60 -14
  6. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  7. package/dist/cjs/hooks/index.cjs.map +1 -1
  8. package/dist/cjs/hooks/types.cjs +2 -0
  9. package/dist/cjs/hooks/types.cjs.map +1 -1
  10. package/dist/cjs/llm/anthropic/index.cjs +35 -206
  11. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  12. package/dist/cjs/llm/bedrock/index.cjs +121 -241
  13. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  14. package/dist/cjs/llm/google/index.cjs +19 -12
  15. package/dist/cjs/llm/google/index.cjs.map +1 -1
  16. package/dist/cjs/llm/init.cjs +3 -3
  17. package/dist/cjs/llm/invoke.cjs +2 -2
  18. package/dist/cjs/llm/mistral/index.cjs +26 -0
  19. package/dist/cjs/llm/mistral/index.cjs.map +1 -0
  20. package/dist/cjs/llm/openai/index.cjs +82 -80
  21. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  22. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  23. package/dist/cjs/llm/providers.cjs +19 -19
  24. package/dist/cjs/llm/providers.cjs.map +1 -1
  25. package/dist/cjs/llm/stream/chunkAdapters.cjs +198 -0
  26. package/dist/cjs/llm/stream/chunkAdapters.cjs.map +1 -0
  27. package/dist/cjs/llm/stream/smoother.cjs +369 -0
  28. package/dist/cjs/llm/stream/smoother.cjs.map +1 -0
  29. package/dist/cjs/llm/vertexai/index.cjs +13 -1
  30. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  31. package/dist/cjs/main.cjs +25 -16
  32. package/dist/cjs/messages/format.cjs +40 -23
  33. package/dist/cjs/messages/format.cjs.map +1 -1
  34. package/dist/cjs/run.cjs +82 -15
  35. package/dist/cjs/run.cjs.map +1 -1
  36. package/dist/cjs/session/AgentSession.cjs +37 -2
  37. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  38. package/dist/cjs/stream.cjs +1 -1
  39. package/dist/cjs/summarization/node.cjs +6 -3
  40. package/dist/cjs/summarization/node.cjs.map +1 -1
  41. package/dist/cjs/tools/BashExecutor.cjs +1 -1
  42. package/dist/cjs/tools/CodeExecutor.cjs +1 -1
  43. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +1 -1
  44. package/dist/cjs/tools/ToolNode.cjs +316 -94
  45. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  46. package/dist/cjs/tools/ToolSearch.cjs +1 -1
  47. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +664 -80
  48. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  49. package/dist/cjs/tools/subagent/SubagentReplay.cjs +175 -0
  50. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -0
  51. package/dist/cjs/tools/toolOutputReferences.cjs +20 -0
  52. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  53. package/dist/cjs/utils/index.cjs +2 -2
  54. package/dist/cjs/utils/tokens.cjs +76 -29
  55. package/dist/cjs/utils/tokens.cjs.map +1 -1
  56. package/dist/esm/graphs/Graph.mjs +121 -27
  57. package/dist/esm/graphs/Graph.mjs.map +1 -1
  58. package/dist/esm/hooks/HookRegistry.mjs +83 -0
  59. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  60. package/dist/esm/hooks/executeHooks.mjs +60 -14
  61. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  62. package/dist/esm/hooks/index.mjs.map +1 -1
  63. package/dist/esm/hooks/types.mjs +2 -1
  64. package/dist/esm/hooks/types.mjs.map +1 -1
  65. package/dist/esm/llm/anthropic/index.mjs +34 -205
  66. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  67. package/dist/esm/llm/bedrock/index.mjs +120 -240
  68. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  69. package/dist/esm/llm/google/index.mjs +19 -12
  70. package/dist/esm/llm/google/index.mjs.map +1 -1
  71. package/dist/esm/llm/init.mjs +1 -1
  72. package/dist/esm/llm/invoke.mjs +2 -2
  73. package/dist/esm/llm/mistral/index.mjs +26 -0
  74. package/dist/esm/llm/mistral/index.mjs.map +1 -0
  75. package/dist/esm/llm/openai/index.mjs +82 -80
  76. package/dist/esm/llm/openai/index.mjs.map +1 -1
  77. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  78. package/dist/esm/llm/providers.mjs +3 -3
  79. package/dist/esm/llm/providers.mjs.map +1 -1
  80. package/dist/esm/llm/stream/chunkAdapters.mjs +195 -0
  81. package/dist/esm/llm/stream/chunkAdapters.mjs.map +1 -0
  82. package/dist/esm/llm/stream/smoother.mjs +365 -0
  83. package/dist/esm/llm/stream/smoother.mjs.map +1 -0
  84. package/dist/esm/llm/vertexai/index.mjs +13 -1
  85. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  86. package/dist/esm/main.mjs +13 -11
  87. package/dist/esm/messages/format.mjs +40 -23
  88. package/dist/esm/messages/format.mjs.map +1 -1
  89. package/dist/esm/run.mjs +83 -16
  90. package/dist/esm/run.mjs.map +1 -1
  91. package/dist/esm/session/AgentSession.mjs +37 -2
  92. package/dist/esm/session/AgentSession.mjs.map +1 -1
  93. package/dist/esm/stream.mjs +1 -1
  94. package/dist/esm/summarization/node.mjs +6 -3
  95. package/dist/esm/summarization/node.mjs.map +1 -1
  96. package/dist/esm/tools/BashExecutor.mjs +1 -1
  97. package/dist/esm/tools/CodeExecutor.mjs +1 -1
  98. package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
  99. package/dist/esm/tools/ToolNode.mjs +317 -95
  100. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  101. package/dist/esm/tools/ToolSearch.mjs +1 -1
  102. package/dist/esm/tools/subagent/SubagentExecutor.mjs +665 -81
  103. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  104. package/dist/esm/tools/subagent/SubagentReplay.mjs +168 -0
  105. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -0
  106. package/dist/esm/tools/toolOutputReferences.mjs +20 -0
  107. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  108. package/dist/esm/utils/index.mjs +2 -2
  109. package/dist/esm/utils/tokens.mjs +76 -30
  110. package/dist/esm/utils/tokens.mjs.map +1 -1
  111. package/dist/types/graphs/Graph.d.ts +19 -1
  112. package/dist/types/hooks/HookRegistry.d.ts +10 -1
  113. package/dist/types/hooks/executeHooks.d.ts +5 -1
  114. package/dist/types/hooks/index.d.ts +2 -2
  115. package/dist/types/hooks/types.d.ts +12 -0
  116. package/dist/types/index.d.ts +3 -0
  117. package/dist/types/llm/google/index.d.ts +2 -0
  118. package/dist/types/llm/mistral/index.d.ts +11 -0
  119. package/dist/types/llm/openai/index.d.ts +20 -4
  120. package/dist/types/llm/openrouter/index.d.ts +4 -1
  121. package/dist/types/llm/stream/chunkAdapters.d.ts +48 -0
  122. package/dist/types/llm/stream/smoother.d.ts +95 -0
  123. package/dist/types/llm/vertexai/index.d.ts +2 -0
  124. package/dist/types/run.d.ts +4 -1
  125. package/dist/types/session/AgentSession.d.ts +1 -0
  126. package/dist/types/tools/ToolNode.d.ts +23 -15
  127. package/dist/types/tools/subagent/SubagentExecutor.d.ts +49 -7
  128. package/dist/types/tools/subagent/SubagentReplay.d.ts +81 -0
  129. package/dist/types/tools/toolOutputReferences.d.ts +12 -0
  130. package/dist/types/types/graph.d.ts +5 -5
  131. package/dist/types/types/hitl.d.ts +15 -0
  132. package/dist/types/types/llm.d.ts +21 -14
  133. package/dist/types/utils/tokens.d.ts +10 -0
  134. package/package.json +6 -2
  135. package/src/graphs/Graph.ts +257 -52
  136. package/src/graphs/__tests__/Graph.breakerLifecycle.test.ts +48 -9
  137. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1 -1
  138. package/src/graphs/__tests__/Graph.subagentResumeState.test.ts +80 -0
  139. package/src/hooks/HookRegistry.ts +151 -1
  140. package/src/hooks/__tests__/HookRegistry.test.ts +96 -0
  141. package/src/hooks/__tests__/executeHooks.test.ts +160 -0
  142. package/src/hooks/executeHooks.ts +133 -15
  143. package/src/hooks/index.ts +3 -1
  144. package/src/hooks/types.ts +16 -0
  145. package/src/index.ts +8 -0
  146. package/src/llm/anthropic/index.ts +85 -354
  147. package/src/llm/bedrock/index.ts +174 -390
  148. package/src/llm/bedrock/llm.spec.ts +2 -0
  149. package/src/llm/bedrock/streamSealDispatch.test.ts +76 -0
  150. package/src/llm/custom-chat-models.smoke.test.ts +16 -1
  151. package/src/llm/google/index.ts +17 -18
  152. package/src/llm/google/streamSmoothing.test.ts +121 -0
  153. package/src/llm/mistral/index.ts +33 -0
  154. package/src/llm/mistral/streamSmoothing.test.ts +97 -0
  155. package/src/llm/openai/deepseek.test.ts +56 -0
  156. package/src/llm/openai/index.ts +119 -126
  157. package/src/llm/openrouter/index.ts +4 -1
  158. package/src/llm/providers.ts +3 -3
  159. package/src/llm/stream/chunkAdapters.test.ts +202 -0
  160. package/src/llm/stream/chunkAdapters.ts +317 -0
  161. package/src/llm/stream/reassembly.test.ts +241 -0
  162. package/src/llm/stream/smoother.bench.test.ts +155 -0
  163. package/src/llm/stream/smoother.test.ts +519 -0
  164. package/src/llm/stream/smoother.ts +574 -0
  165. package/src/llm/vertexai/index.ts +17 -1
  166. package/src/llm/vertexai/streamSmoothing.test.ts +109 -0
  167. package/src/messages/format.ts +54 -26
  168. package/src/messages/formatAgentMessages.reducer.test.ts +162 -0
  169. package/src/messages/formatAgentMessages.steer.test.ts +16 -11
  170. package/src/messages/formatAgentMessages.test.ts +7 -2
  171. package/src/run.ts +164 -18
  172. package/src/session/AgentSession.ts +52 -2
  173. package/src/session/__tests__/JsonlSessionStore.test.ts +53 -0
  174. package/src/specs/subagent.test.ts +44 -0
  175. package/src/specs/tokens.test.ts +159 -14
  176. package/src/summarization/__tests__/node.test.ts +32 -14
  177. package/src/summarization/node.ts +15 -11
  178. package/src/tools/ToolNode.ts +631 -157
  179. package/src/tools/__tests__/SubagentExecutor.test.ts +590 -7
  180. package/src/tools/__tests__/SubagentReplay.test.ts +300 -0
  181. package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +208 -2
  182. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +486 -2
  183. package/src/tools/__tests__/hitl.test.ts +234 -5
  184. package/src/tools/__tests__/subagentHooks.test.ts +1040 -62
  185. package/src/tools/__tests__/toolOutputReferences.test.ts +19 -2
  186. package/src/tools/subagent/SubagentExecutor.ts +1438 -136
  187. package/src/tools/subagent/SubagentReplay.ts +575 -0
  188. package/src/tools/toolOutputReferences.ts +40 -1
  189. package/src/types/graph.ts +5 -5
  190. package/src/types/hitl.ts +16 -0
  191. package/src/types/llm.ts +53 -36
  192. package/src/utils/tokens.ts +115 -30
@@ -21,21 +21,17 @@ import type {
21
21
  AnthropicRequestOptions,
22
22
  AnthropicMessageStreamEvent,
23
23
  } from '@/llm/anthropic/types';
24
+ import type { SmoothItem } from '@/llm/stream/smoother';
24
25
  import type { AnthropicUsageData } from './utils/message_outputs';
25
26
  import {
26
27
  _convertMessagesToAnthropicPayload,
27
28
  stripUnsupportedAssistantPrefill,
28
29
  } from './utils/message_inputs';
29
30
  import { _makeMessageChunkFromAnthropicEvent } from './utils/message_outputs';
31
+ import { smoothStream, resolveStreamDelay, isSignalAborted } from '@/llm/stream/smoother';
30
32
  import { convertAnthropicStream } from './utils/stream_events';
31
33
  import { handleToolChoice } from './utils/tools';
32
34
 
33
- const DEFAULT_STREAM_DELAY = 25;
34
- const MAX_STREAM_QUEUE_CHUNKS = 256;
35
- const MAX_STREAM_QUEUE_TEXT_CHARS = 8192;
36
- const STREAM_CHUNK_MIN_SIZE = 4;
37
- const STREAM_BOUNDARIES = new Set([' ', '.', ',', '!', '?', ';', ':']);
38
-
39
35
  type StreamTokenType = 'string' | 'input' | 'content';
40
36
 
41
37
  interface AnthropicStreamUsage {
@@ -268,83 +264,6 @@ function getSamplingParams({
268
264
  };
269
265
  }
270
266
 
271
- function findStreamChunkBoundary(text: string, minSize: number): number {
272
- if (minSize >= text.length) {
273
- return text.length;
274
- }
275
-
276
- for (let position = minSize; position < text.length; position++) {
277
- if (STREAM_BOUNDARIES.has(text[position])) {
278
- return position + 1;
279
- }
280
- }
281
-
282
- return text.length;
283
- }
284
-
285
- function splitStreamToken(text: string): string[] {
286
- const chunks: string[] = [];
287
- let currentIndex = 0;
288
-
289
- while (currentIndex < text.length) {
290
- const remainingText = text.slice(currentIndex);
291
- const chunkSize = findStreamChunkBoundary(
292
- remainingText,
293
- STREAM_CHUNK_MIN_SIZE
294
- );
295
- chunks.push(text.slice(currentIndex, currentIndex + chunkSize));
296
- currentIndex += chunkSize;
297
- }
298
-
299
- return chunks;
300
- }
301
-
302
- function getCadencedStreamDelay({
303
- targetDelay,
304
- lastVisibleTextAt,
305
- now,
306
- }: {
307
- targetDelay: number;
308
- lastVisibleTextAt?: number;
309
- now: number;
310
- }): number {
311
- if (targetDelay <= 0 || lastVisibleTextAt == null) {
312
- return 0;
313
- }
314
- return Math.max(0, targetDelay - (now - lastVisibleTextAt));
315
- }
316
-
317
- async function waitForStreamDelay(
318
- delay: number,
319
- signal?: AbortSignal
320
- ): Promise<void> {
321
- if (delay <= 0 || isSignalAborted(signal)) {
322
- return;
323
- }
324
- await new Promise<void>((resolve) => {
325
- const timeoutRef: { current?: ReturnType<typeof setTimeout> } = {};
326
- const onAbort = (): void => {
327
- if (timeoutRef.current) {
328
- clearTimeout(timeoutRef.current);
329
- }
330
- signal?.removeEventListener('abort', onAbort);
331
- resolve();
332
- };
333
- timeoutRef.current = setTimeout(() => {
334
- signal?.removeEventListener('abort', onAbort);
335
- resolve();
336
- }, delay);
337
- signal?.addEventListener('abort', onAbort, { once: true });
338
- if (isSignalAborted(signal)) {
339
- onAbort();
340
- }
341
- });
342
- }
343
-
344
- function isSignalAborted(signal?: AbortSignal): boolean {
345
- return signal?.aborted === true;
346
- }
347
-
348
267
  async function* abortableAnthropicStream(
349
268
  source: AnthropicEventStream,
350
269
  signal?: AbortSignal
@@ -525,11 +444,9 @@ type CustomAnthropicInvocationParams = {
525
444
  output_config?: AnthropicOutputConfig;
526
445
  };
527
446
 
528
- type QueuedGenerationChunk = {
447
+ type AnthropicEmittedChunk = {
529
448
  chunk: ChatGenerationChunk;
530
449
  token: string;
531
- smooth: boolean;
532
- textLength: number;
533
450
  };
534
451
 
535
452
  export class CustomAnthropic extends ChatAnthropicMessages {
@@ -543,10 +460,7 @@ export class CustomAnthropic extends ChatAnthropicMessages {
543
460
  super(fields);
544
461
  this.resetTokenEvents();
545
462
  this.setDirectFields(fields);
546
- this._lc_stream_delay = Math.max(
547
- 0,
548
- fields?._lc_stream_delay ?? DEFAULT_STREAM_DELAY
549
- );
463
+ this._lc_stream_delay = resolveStreamDelay(fields?._lc_stream_delay);
550
464
  this.outputConfig = fields?.outputConfig;
551
465
  this.inferenceGeo = fields?.inferenceGeo;
552
466
  this.contextManagement = fields?.contextManagement;
@@ -764,292 +678,109 @@ export class CustomAnthropic extends ChatAnthropicMessages {
764
678
  cacheReadInputTokens: 0,
765
679
  outputTokens: 0,
766
680
  };
767
- const queuedChunks: QueuedGenerationChunk[] = [];
768
- const producerState: {
769
- done: boolean;
770
- error?: unknown;
771
- } = { done: false };
772
- let queuedChunkIndex = 0;
773
- let bufferedTextLength = 0;
774
- let consumerClosed = false;
775
- let notifyConsumer: (() => void) | undefined;
776
- let notifyProducer: (() => void) | undefined;
777
-
778
- const notifyConsumerForChunk = (): void => {
779
- notifyConsumer?.();
780
- notifyConsumer = undefined;
781
- };
782
-
783
- const notifyProducerForSpace = (): void => {
784
- notifyProducer?.();
785
- notifyProducer = undefined;
786
- };
787
-
788
- const hasQueuedChunks = (): boolean =>
789
- queuedChunkIndex < queuedChunks.length;
790
-
791
- const getQueuedChunkCount = (): number =>
792
- queuedChunks.length - queuedChunkIndex;
793
-
794
- const isQueueAtCapacity = (): boolean =>
795
- getQueuedChunkCount() >= MAX_STREAM_QUEUE_CHUNKS ||
796
- bufferedTextLength >= MAX_STREAM_QUEUE_TEXT_CHARS;
797
-
798
- const waitForNextChunk = async (): Promise<void> => {
799
- if (
800
- hasQueuedChunks() ||
801
- producerState.done ||
802
- producerState.error != null
803
- ) {
804
- return;
805
- }
806
- await new Promise<void>((resolve) => {
807
- notifyConsumer = resolve;
808
- });
809
- };
810
-
811
- const waitForQueueSpace = async (): Promise<void> => {
812
- while (
813
- isQueueAtCapacity() &&
814
- !consumerClosed &&
815
- !isSignalAborted(options.signal)
816
- ) {
817
- await new Promise<void>((resolve) => {
818
- const signal = options.signal;
819
- const onAbort = (): void => {
820
- signal?.removeEventListener('abort', onAbort);
821
- resolve();
822
- };
823
- const onSpace = (): void => {
824
- signal?.removeEventListener('abort', onAbort);
825
- resolve();
826
- };
827
- notifyProducer = onSpace;
828
- signal?.addEventListener('abort', onAbort, { once: true });
829
- if (isSignalAborted(signal)) {
830
- onAbort();
831
- }
832
- });
833
- }
834
- };
835
-
836
- const dequeue = (): QueuedGenerationChunk | undefined => {
837
- if (!hasQueuedChunks()) {
838
- return undefined;
839
- }
840
- const queuedChunk = queuedChunks[queuedChunkIndex];
841
- queuedChunkIndex++;
842
- if (
843
- queuedChunkIndex > 128 &&
844
- queuedChunkIndex * 2 >= queuedChunks.length
845
- ) {
846
- queuedChunks.splice(0, queuedChunkIndex);
847
- queuedChunkIndex = 0;
848
- }
849
- return queuedChunk;
850
- };
851
-
852
- const enqueue = async (
853
- queuedChunk: QueuedGenerationChunk
854
- ): Promise<void> => {
855
- await waitForQueueSpace();
856
- if (consumerClosed || isSignalAborted(options.signal)) {
857
- stream.controller.abort();
858
- throw new Error('AbortError: User aborted the request.');
859
- }
860
- queuedChunks.push(queuedChunk);
861
- if (queuedChunk.smooth) {
862
- bufferedTextLength += queuedChunk.textLength;
863
- }
864
- notifyConsumerForChunk();
865
- };
866
-
867
- const enqueueChunk = async ({
868
- token,
869
- chunk,
870
- smooth,
871
- }: {
872
- token: string;
873
- chunk: AIMessageChunk;
874
- smooth: boolean;
875
- }): Promise<void> => {
876
- await enqueue({
877
- token,
878
- smooth,
879
- textLength: smooth ? token.length : 0,
880
- chunk: this.createGenerationChunk({
881
- token,
882
- chunk,
883
- shouldStreamUsage,
884
- }),
885
- });
886
- };
887
-
888
- const enqueueTextChunks = (
681
+ const toEmittedChunk = (
889
682
  token: string,
890
- tokenType: StreamTokenType,
891
683
  chunk: AIMessageChunk
892
- ): Promise<void> => {
893
- if (token === '') {
894
- return Promise.resolve();
895
- }
896
- if (this._lc_stream_delay <= 0) {
897
- return enqueueChunk({ token, chunk, smooth: false });
898
- }
899
-
900
- const tokenChunks = splitStreamToken(token);
901
- if (tokenChunks.length <= 1) {
902
- return enqueueChunk({ token, chunk, smooth: true });
903
- }
904
-
905
- let emittedUsage = false;
906
- return tokenChunks.reduce(async (previous, currentToken) => {
907
- await previous;
908
- const newChunk = cloneChunk(currentToken, tokenType, chunk);
909
- const chunkForToken =
910
- emittedUsage && newChunk.usage_metadata != null
911
- ? new AIMessageChunk(
912
- Object.assign({}, newChunk, { usage_metadata: undefined })
913
- )
914
- : newChunk;
915
-
916
- await enqueueChunk({
917
- token: currentToken,
918
- chunk: chunkForToken,
919
- smooth: true,
920
- });
921
-
922
- if (newChunk.usage_metadata != null && !emittedUsage) {
923
- emittedUsage = true;
924
- }
925
- }, Promise.resolve());
926
- };
684
+ ): AnthropicEmittedChunk => ({
685
+ token,
686
+ chunk: this.createGenerationChunk({ token, chunk, shouldStreamUsage }),
687
+ });
927
688
 
928
- const producer = (async (): Promise<void> => {
929
- try {
930
- for await (const data of stream) {
931
- if (isSignalAborted(options.signal)) {
932
- stream.controller.abort();
933
- throw new Error('AbortError: User aborted the request.');
689
+ const source = (async function* (): AsyncGenerator<
690
+ SmoothItem<AnthropicEmittedChunk>
691
+ > {
692
+ for await (const data of stream) {
693
+ const result = _makeMessageChunkFromAnthropicEvent(
694
+ data as Anthropic.Beta.Messages.BetaRawMessageStreamEvent,
695
+ {
696
+ streamUsage: shouldStreamUsage,
697
+ coerceContentToString,
934
698
  }
699
+ );
700
+ if (!result) {
701
+ continue;
702
+ }
935
703
 
936
- const result = _makeMessageChunkFromAnthropicEvent(
937
- data as Anthropic.Beta.Messages.BetaRawMessageStreamEvent,
938
- {
939
- streamUsage: shouldStreamUsage,
940
- coerceContentToString,
941
- }
704
+ let { chunk } = result;
705
+ if (data.type === 'message_start') {
706
+ streamUsage = {
707
+ ...streamUsage,
708
+ inputTokens: data.message.usage.input_tokens,
709
+ outputTokens: data.message.usage.output_tokens,
710
+ cacheCreationInputTokens:
711
+ data.message.usage.cache_creation_input_tokens ?? 0,
712
+ cacheReadInputTokens:
713
+ data.message.usage.cache_read_input_tokens ?? 0,
714
+ };
715
+ }
716
+ if (data.type === 'message_delta') {
717
+ const incremental = withIncrementalMessageDeltaUsage(
718
+ chunk,
719
+ streamUsage,
720
+ data.usage
942
721
  );
943
- if (!result) {
944
- continue;
945
- }
946
-
947
- let { chunk } = result;
948
- if (data.type === 'message_start') {
949
- streamUsage = {
950
- ...streamUsage,
951
- inputTokens: data.message.usage.input_tokens,
952
- outputTokens: data.message.usage.output_tokens,
953
- cacheCreationInputTokens:
954
- data.message.usage.cache_creation_input_tokens ?? 0,
955
- cacheReadInputTokens:
956
- data.message.usage.cache_read_input_tokens ?? 0,
957
- };
958
- }
959
- if (data.type === 'message_delta') {
960
- const incremental = withIncrementalMessageDeltaUsage(
961
- chunk,
962
- streamUsage,
963
- data.usage
964
- );
965
- chunk = incremental.chunk;
966
- streamUsage = incremental.usage;
967
- }
968
-
969
- const [token = '', tokenType] = extractToken(chunk);
970
- if (
971
- !tokenType ||
972
- tokenType === 'input' ||
973
- (token === '' && (chunk.usage_metadata != null || chunk.id != null))
974
- ) {
975
- await enqueueChunk({ token, chunk, smooth: false });
976
- continue;
977
- }
978
-
979
- await enqueueTextChunks(token, tokenType, chunk);
722
+ chunk = incremental.chunk;
723
+ streamUsage = incremental.usage;
980
724
  }
981
- } catch (error) {
982
- producerState.error = error;
983
- } finally {
984
- producerState.done = true;
985
- notifyConsumerForChunk();
986
- }
987
- })();
988
725
 
989
- let hasEmittedText = false;
990
- let lastVisibleTextAt: number | undefined;
991
- let keepStreaming = true;
992
- try {
993
- while (keepStreaming) {
994
- if (isSignalAborted(options.signal)) {
995
- stream.controller.abort();
996
- throw new Error('AbortError: User aborted the request.');
726
+ const [token = '', tokenType] = extractToken(chunk);
727
+ if (
728
+ !tokenType ||
729
+ tokenType === 'input' ||
730
+ (token === '' && (chunk.usage_metadata != null || chunk.id != null))
731
+ ) {
732
+ yield {
733
+ text: '',
734
+ smooth: false,
735
+ emit: (): AnthropicEmittedChunk => toEmittedChunk(token, chunk),
736
+ };
737
+ continue;
997
738
  }
998
739
 
999
- await waitForNextChunk();
1000
- const queuedChunk = dequeue();
1001
-
1002
- if (!queuedChunk) {
1003
- if (producerState.error != null) {
1004
- throw producerState.error;
1005
- }
1006
- if (producerState.done) {
1007
- keepStreaming = false;
1008
- }
740
+ if (token === '') {
1009
741
  continue;
1010
742
  }
1011
743
 
1012
- if (queuedChunk.smooth) {
1013
- bufferedTextLength = Math.max(
1014
- 0,
1015
- bufferedTextLength - queuedChunk.textLength
1016
- );
1017
- notifyProducerForSpace();
1018
- await waitForStreamDelay(
1019
- getCadencedStreamDelay({
1020
- targetDelay: hasEmittedText ? this._lc_stream_delay : 0,
1021
- lastVisibleTextAt,
1022
- now: Date.now(),
1023
- }),
1024
- options.signal
1025
- );
1026
- if (isSignalAborted(options.signal)) {
1027
- stream.controller.abort();
1028
- throw new Error('AbortError: User aborted the request.');
1029
- }
1030
- hasEmittedText = true;
1031
- lastVisibleTextAt = Date.now();
1032
- } else {
1033
- notifyProducerForSpace();
1034
- }
744
+ yield {
745
+ text: token,
746
+ smooth: true,
747
+ emit: (piece): AnthropicEmittedChunk => {
748
+ if (piece.isFirst && piece.isLast) {
749
+ return toEmittedChunk(token, chunk);
750
+ }
751
+ const cloned = cloneChunk(piece.text, tokenType, chunk);
752
+ const chunkForPiece =
753
+ !piece.isFirst && cloned.usage_metadata != null
754
+ ? new AIMessageChunk(
755
+ Object.assign({}, cloned, { usage_metadata: undefined })
756
+ )
757
+ : cloned;
758
+ return toEmittedChunk(piece.text, chunkForPiece);
759
+ },
760
+ };
761
+ }
762
+ })();
763
+
764
+ const smoothed = smoothStream({
765
+ source,
766
+ delayMs: this._lc_stream_delay,
767
+ signal: options.signal,
768
+ abortUpstream: () => stream.controller.abort(),
769
+ });
1035
770
 
1036
- yield queuedChunk.chunk;
771
+ try {
772
+ for await (const emitted of smoothed) {
773
+ yield emitted.chunk;
1037
774
  await runManager?.handleLLMNewToken(
1038
- queuedChunk.token,
775
+ emitted.token,
1039
776
  undefined,
1040
777
  undefined,
1041
778
  undefined,
1042
779
  undefined,
1043
- { chunk: queuedChunk.chunk }
780
+ { chunk: emitted.chunk }
1044
781
  );
1045
782
  }
1046
783
  } finally {
1047
- consumerClosed = true;
1048
- if (!producerState.done) {
1049
- stream.controller.abort();
1050
- notifyProducerForSpace();
1051
- }
1052
- await producer;
1053
784
  this.resetTokenEvents();
1054
785
  }
1055
786
  }