@librechat/agents 3.3.12 → 3.4.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/cjs/graphs/Graph.cjs +10 -0
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +1 -0
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/langfuseSpanRegistry.cjs +6 -3
- package/dist/cjs/langfuseSpanRegistry.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +35 -206
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +121 -241
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +19 -12
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/mistral/index.cjs +26 -0
- package/dist/cjs/llm/mistral/index.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +82 -80
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +19 -19
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/stream/chunkAdapters.cjs +198 -0
- package/dist/cjs/llm/stream/chunkAdapters.cjs.map +1 -0
- package/dist/cjs/llm/stream/smoother.cjs +369 -0
- package/dist/cjs/llm/stream/smoother.cjs.map +1 -0
- package/dist/cjs/llm/vertexai/index.cjs +13 -1
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +18 -10
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +34 -2
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +76 -29
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +10 -0
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +1 -0
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/langfuseSpanRegistry.mjs +6 -3
- package/dist/esm/langfuseSpanRegistry.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +34 -205
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +120 -240
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +19 -12
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/mistral/index.mjs +26 -0
- package/dist/esm/llm/mistral/index.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +82 -80
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +3 -3
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/stream/chunkAdapters.mjs +195 -0
- package/dist/esm/llm/stream/chunkAdapters.mjs.map +1 -0
- package/dist/esm/llm/stream/smoother.mjs +365 -0
- package/dist/esm/llm/stream/smoother.mjs.map +1 -0
- package/dist/esm/llm/vertexai/index.mjs +13 -1
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +4 -2
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +34 -2
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +76 -30
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +3 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/llm/google/index.d.ts +2 -0
- package/dist/types/llm/mistral/index.d.ts +11 -0
- package/dist/types/llm/openai/index.d.ts +20 -4
- package/dist/types/llm/openrouter/index.d.ts +4 -1
- package/dist/types/llm/stream/chunkAdapters.d.ts +48 -0
- package/dist/types/llm/stream/smoother.d.ts +95 -0
- package/dist/types/llm/vertexai/index.d.ts +2 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +3 -0
- package/dist/types/types/graph.d.ts +5 -0
- package/dist/types/types/llm.d.ts +21 -14
- package/dist/types/utils/tokens.d.ts +10 -0
- package/package.json +2 -2
- package/src/graphs/Graph.ts +11 -0
- package/src/index.ts +8 -0
- package/src/instrumentation.ts +1 -0
- package/src/langfuseSpanRegistry.ts +9 -0
- package/src/llm/anthropic/index.ts +85 -354
- package/src/llm/bedrock/index.ts +174 -390
- package/src/llm/bedrock/llm.spec.ts +2 -0
- package/src/llm/bedrock/streamSealDispatch.test.ts +76 -0
- package/src/llm/custom-chat-models.smoke.test.ts +16 -1
- package/src/llm/google/index.ts +17 -18
- package/src/llm/google/streamSmoothing.test.ts +121 -0
- package/src/llm/mistral/index.ts +33 -0
- package/src/llm/mistral/streamSmoothing.test.ts +97 -0
- package/src/llm/openai/deepseek.test.ts +56 -0
- package/src/llm/openai/index.ts +119 -126
- package/src/llm/openrouter/index.ts +4 -1
- package/src/llm/providers.ts +3 -3
- package/src/llm/stream/chunkAdapters.test.ts +202 -0
- package/src/llm/stream/chunkAdapters.ts +317 -0
- package/src/llm/stream/reassembly.test.ts +241 -0
- package/src/llm/stream/smoother.bench.test.ts +155 -0
- package/src/llm/stream/smoother.test.ts +519 -0
- package/src/llm/stream/smoother.ts +574 -0
- package/src/llm/vertexai/index.ts +17 -1
- package/src/llm/vertexai/streamSmoothing.test.ts +109 -0
- package/src/specs/langfuse-instrumentation.test.ts +26 -0
- package/src/specs/langfuse-span-registry.test.ts +17 -0
- package/src/specs/subagent.test.ts +44 -0
- package/src/specs/summarization.test.ts +5 -2
- package/src/specs/tokens.test.ts +159 -14
- package/src/tools/__tests__/SubagentExecutor.test.ts +48 -1
- package/src/tools/subagent/SubagentExecutor.ts +69 -5
- package/src/types/graph.ts +5 -0
- package/src/types/llm.ts +53 -36
- 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
|
|
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 =
|
|
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
|
|
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
|
-
):
|
|
893
|
-
|
|
894
|
-
|
|
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
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
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
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
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
|
-
|
|
944
|
-
|
|
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
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
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
|
-
|
|
771
|
+
try {
|
|
772
|
+
for await (const emitted of smoothed) {
|
|
773
|
+
yield emitted.chunk;
|
|
1037
774
|
await runManager?.handleLLMNewToken(
|
|
1038
|
-
|
|
775
|
+
emitted.token,
|
|
1039
776
|
undefined,
|
|
1040
777
|
undefined,
|
|
1041
778
|
undefined,
|
|
1042
779
|
undefined,
|
|
1043
|
-
{ 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
|
}
|