@librechat/agents 2.3.92 → 2.3.94

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.
@@ -3,14 +3,29 @@ import { nanoid } from 'nanoid';
3
3
  import { concat } from '@langchain/core/utils/stream';
4
4
  import { ToolNode } from '@langchain/langgraph/prebuilt';
5
5
  import { ChatVertexAI } from '@langchain/google-vertexai';
6
- import { START, END, StateGraph } from '@langchain/langgraph';
6
+ import { START, END, StateGraph } from '@langchain/langgraph';
7
7
  import { ChatOpenAI, AzureChatOpenAI } from '@langchain/openai';
8
8
  import { Runnable, RunnableConfig } from '@langchain/core/runnables';
9
9
  import { dispatchCustomEvent } from '@langchain/core/callbacks/dispatch';
10
- import { AIMessageChunk, ToolMessage, SystemMessage } from '@langchain/core/messages';
11
- import type { BaseMessage, BaseMessageFields, UsageMetadata } from '@langchain/core/messages';
10
+ import {
11
+ AIMessageChunk,
12
+ ToolMessage,
13
+ SystemMessage,
14
+ } from '@langchain/core/messages';
15
+ import type {
16
+ BaseMessage,
17
+ BaseMessageFields,
18
+ UsageMetadata,
19
+ } from '@langchain/core/messages';
12
20
  import type * as t from '@/types';
13
- import { Providers, GraphEvents, GraphNodeKeys, StepTypes, Callback, ContentTypes } from '@/common';
21
+ import {
22
+ Providers,
23
+ GraphEvents,
24
+ GraphNodeKeys,
25
+ StepTypes,
26
+ Callback,
27
+ ContentTypes,
28
+ } from '@/common';
14
29
  import type { ToolCall } from '@langchain/core/messages/tool';
15
30
  import { getChatModelClass, manualToolStreamProviders } from '@/llm/providers';
16
31
  import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
@@ -21,20 +36,31 @@ import {
21
36
  convertMessagesToContent,
22
37
  formatAnthropicArtifactContent,
23
38
  } from '@/messages';
24
- import { resetIfNotEmpty, isOpenAILike, isGoogleLike, joinKeys, sleep } from '@/utils';
39
+ import {
40
+ resetIfNotEmpty,
41
+ isOpenAILike,
42
+ isGoogleLike,
43
+ joinKeys,
44
+ sleep,
45
+ } from '@/utils';
25
46
  import { createFakeStreamingLLM } from '@/llm/fake';
26
47
  import { HandlerRegistry } from '@/events';
27
48
 
28
49
  const { AGENT, TOOLS } = GraphNodeKeys;
29
50
  export type GraphNode = GraphNodeKeys | typeof START;
30
- export type ClientCallback<T extends unknown[]> = (graph: StandardGraph, ...args: T) => void;
51
+ export type ClientCallback<T extends unknown[]> = (
52
+ graph: StandardGraph,
53
+ ...args: T
54
+ ) => void;
31
55
  export type ClientCallbacks = {
32
56
  [Callback.TOOL_ERROR]?: ClientCallback<[Error, string]>;
33
57
  [Callback.TOOL_START]?: ClientCallback<unknown[]>;
34
58
  [Callback.TOOL_END]?: ClientCallback<unknown[]>;
35
- }
59
+ };
36
60
  export type SystemCallbacks = {
37
- [K in keyof ClientCallbacks]: ClientCallbacks[K] extends ClientCallback<infer Args>
61
+ [K in keyof ClientCallbacks]: ClientCallbacks[K] extends ClientCallback<
62
+ infer Args
63
+ >
38
64
  ? (...args: Args) => void
39
65
  : never;
40
66
  };
@@ -51,18 +77,29 @@ export abstract class Graph<
51
77
  abstract getRunMessages(): BaseMessage[] | undefined;
52
78
  abstract getContentParts(): t.MessageContentComplex[] | undefined;
53
79
  abstract generateStepId(stepKey: string): [string, number];
54
- abstract getKeyList(metadata: Record<string, unknown> | undefined): (string | number | undefined)[];
80
+ abstract getKeyList(
81
+ metadata: Record<string, unknown> | undefined
82
+ ): (string | number | undefined)[];
55
83
  abstract getStepKey(metadata: Record<string, unknown> | undefined): string;
56
84
  abstract checkKeyList(keyList: (string | number | undefined)[]): boolean;
57
- abstract getStepIdByKey(stepKey: string, index?: number): string
85
+ abstract getStepIdByKey(stepKey: string, index?: number): string;
58
86
  abstract getRunStep(stepId: string): t.RunStep | undefined;
59
87
  abstract dispatchRunStep(stepKey: string, stepDetails: t.StepDetails): string;
60
88
  abstract dispatchRunStepDelta(id: string, delta: t.ToolCallDelta): void;
61
89
  abstract dispatchMessageDelta(id: string, delta: t.MessageDelta): void;
62
- abstract dispatchReasoningDelta(stepId: string, delta: t.ReasoningDelta): void;
63
- abstract handleToolCallCompleted(data: t.ToolEndData, metadata?: Record<string, unknown>): void;
64
-
65
- abstract createCallModel(): (state: T, config?: RunnableConfig) => Promise<Partial<T>>;
90
+ abstract dispatchReasoningDelta(
91
+ stepId: string,
92
+ delta: t.ReasoningDelta
93
+ ): void;
94
+ abstract handleToolCallCompleted(
95
+ data: t.ToolEndData,
96
+ metadata?: Record<string, unknown>
97
+ ): void;
98
+
99
+ abstract createCallModel(): (
100
+ state: T,
101
+ config?: RunnableConfig
102
+ ) => Promise<Partial<T>>;
66
103
  abstract createWorkflow(): t.CompiledWorkflow<T>;
67
104
  lastToken?: string;
68
105
  tokenTypeSwitch?: 'reasoning' | 'content';
@@ -86,10 +123,7 @@ export abstract class Graph<
86
123
  signal?: AbortSignal;
87
124
  }
88
125
 
89
- export class StandardGraph extends Graph<
90
- t.BaseGraphState,
91
- GraphNode
92
- > {
126
+ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
93
127
  private graphState: t.GraphStateChannels<t.BaseGraphState>;
94
128
  clientOptions: t.ClientOptions;
95
129
  boundModel: Runnable;
@@ -118,7 +152,7 @@ export class StandardGraph extends Graph<
118
152
  clientOptions,
119
153
  toolEnd = false,
120
154
  additional_instructions = '',
121
- } : t.StandardGraphInput) {
155
+ }: t.StandardGraphInput) {
122
156
  super();
123
157
  this.runId = runId;
124
158
  this.tools = tools;
@@ -136,10 +170,20 @@ export class StandardGraph extends Graph<
136
170
 
137
171
  let finalInstructions: string | BaseMessageFields = instructions ?? '';
138
172
  if (additional_instructions) {
139
- finalInstructions = finalInstructions ? `${finalInstructions}\n\n${additional_instructions}` : additional_instructions;
173
+ finalInstructions = finalInstructions
174
+ ? `${finalInstructions}\n\n${additional_instructions}`
175
+ : additional_instructions;
140
176
  }
141
177
 
142
- if (finalInstructions && provider === Providers.ANTHROPIC && (clientOptions as t.AnthropicClientOptions).clientOptions?.defaultHeaders?.['anthropic-beta']?.includes('prompt-caching')) {
178
+ if (
179
+ finalInstructions &&
180
+ provider === Providers.ANTHROPIC &&
181
+ (
182
+ clientOptions as t.AnthropicClientOptions
183
+ ).clientOptions?.defaultHeaders?.['anthropic-beta']?.includes(
184
+ 'prompt-caching'
185
+ )
186
+ ) {
143
187
  finalInstructions = {
144
188
  content: [
145
189
  {
@@ -167,10 +211,22 @@ export class StandardGraph extends Graph<
167
211
  }
168
212
  this.stepKeyIds = resetIfNotEmpty(this.stepKeyIds, new Map());
169
213
  this.toolCallStepIds = resetIfNotEmpty(this.toolCallStepIds, new Map());
170
- this.messageIdsByStepKey = resetIfNotEmpty(this.messageIdsByStepKey, new Map());
171
- this.messageStepHasToolCalls = resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
172
- this.prelimMessageIdsByStepKey = resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
173
- this.currentTokenType = resetIfNotEmpty(this.currentTokenType, ContentTypes.TEXT);
214
+ this.messageIdsByStepKey = resetIfNotEmpty(
215
+ this.messageIdsByStepKey,
216
+ new Map()
217
+ );
218
+ this.messageStepHasToolCalls = resetIfNotEmpty(
219
+ this.prelimMessageIdsByStepKey,
220
+ new Map()
221
+ );
222
+ this.prelimMessageIdsByStepKey = resetIfNotEmpty(
223
+ this.prelimMessageIdsByStepKey,
224
+ new Map()
225
+ );
226
+ this.currentTokenType = resetIfNotEmpty(
227
+ this.currentTokenType,
228
+ ContentTypes.TEXT
229
+ );
174
230
  this.lastToken = resetIfNotEmpty(this.lastToken, undefined);
175
231
  this.tokenTypeSwitch = resetIfNotEmpty(this.tokenTypeSwitch, undefined);
176
232
  this.indexTokenCountMap = resetIfNotEmpty(this.indexTokenCountMap, {});
@@ -230,7 +286,9 @@ export class StandardGraph extends Graph<
230
286
  return [newStepId, stepIndex];
231
287
  }
232
288
 
233
- getKeyList(metadata: Record<string, unknown> | undefined): (string | number | undefined)[] {
289
+ getKeyList(
290
+ metadata: Record<string, unknown> | undefined
291
+ ): (string | number | undefined)[] {
234
292
  if (!metadata) return [];
235
293
 
236
294
  const keyList = [
@@ -283,7 +341,9 @@ export class StandardGraph extends Graph<
283
341
  };
284
342
  }
285
343
 
286
- initializeTools(): CustomToolNode<t.BaseGraphState> | ToolNode<t.BaseGraphState> {
344
+ initializeTools():
345
+ | CustomToolNode<t.BaseGraphState>
346
+ | ToolNode<t.BaseGraphState> {
287
347
  // return new ToolNode<t.BaseGraphState>(this.tools);
288
348
  return new CustomToolNode<t.BaseGraphState>({
289
349
  tools: this.tools || [],
@@ -297,20 +357,36 @@ export class StandardGraph extends Graph<
297
357
  const ChatModelClass = getChatModelClass(this.provider);
298
358
  const model = new ChatModelClass(this.clientOptions);
299
359
 
300
- if (isOpenAILike(this.provider) && (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)) {
301
- model.temperature = (this.clientOptions as t.OpenAIClientOptions).temperature as number;
360
+ if (
361
+ isOpenAILike(this.provider) &&
362
+ (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)
363
+ ) {
364
+ model.temperature = (this.clientOptions as t.OpenAIClientOptions)
365
+ .temperature as number;
302
366
  model.topP = (this.clientOptions as t.OpenAIClientOptions).topP as number;
303
- model.frequencyPenalty = (this.clientOptions as t.OpenAIClientOptions).frequencyPenalty as number;
304
- model.presencePenalty = (this.clientOptions as t.OpenAIClientOptions).presencePenalty as number;
367
+ model.frequencyPenalty = (this.clientOptions as t.OpenAIClientOptions)
368
+ .frequencyPenalty as number;
369
+ model.presencePenalty = (this.clientOptions as t.OpenAIClientOptions)
370
+ .presencePenalty as number;
305
371
  model.n = (this.clientOptions as t.OpenAIClientOptions).n as number;
306
- } else if (this.provider === Providers.VERTEXAI && model instanceof ChatVertexAI) {
307
- model.temperature = (this.clientOptions as t.VertexAIClientOptions).temperature as number;
308
- model.topP = (this.clientOptions as t.VertexAIClientOptions).topP as number;
309
- model.topK = (this.clientOptions as t.VertexAIClientOptions).topK as number;
310
- model.topLogprobs = (this.clientOptions as t.VertexAIClientOptions).topLogprobs as number;
311
- model.frequencyPenalty = (this.clientOptions as t.VertexAIClientOptions).frequencyPenalty as number;
312
- model.presencePenalty = (this.clientOptions as t.VertexAIClientOptions).presencePenalty as number;
313
- model.maxOutputTokens = (this.clientOptions as t.VertexAIClientOptions).maxOutputTokens as number;
372
+ } else if (
373
+ this.provider === Providers.VERTEXAI &&
374
+ model instanceof ChatVertexAI
375
+ ) {
376
+ model.temperature = (this.clientOptions as t.VertexAIClientOptions)
377
+ .temperature as number;
378
+ model.topP = (this.clientOptions as t.VertexAIClientOptions)
379
+ .topP as number;
380
+ model.topK = (this.clientOptions as t.VertexAIClientOptions)
381
+ .topK as number;
382
+ model.topLogprobs = (this.clientOptions as t.VertexAIClientOptions)
383
+ .topLogprobs as number;
384
+ model.frequencyPenalty = (this.clientOptions as t.VertexAIClientOptions)
385
+ .frequencyPenalty as number;
386
+ model.presencePenalty = (this.clientOptions as t.VertexAIClientOptions)
387
+ .presencePenalty as number;
388
+ model.maxOutputTokens = (this.clientOptions as t.VertexAIClientOptions)
389
+ .maxOutputTokens as number;
314
390
  }
315
391
 
316
392
  if (!this.tools || this.tools.length === 0) {
@@ -319,7 +395,11 @@ export class StandardGraph extends Graph<
319
395
 
320
396
  return (model as t.ModelWithTools).bindTools(this.tools);
321
397
  }
322
- overrideTestModel(responses: string[], sleep?: number, toolCalls?: ToolCall[]): void {
398
+ overrideTestModel(
399
+ responses: string[],
400
+ sleep?: number,
401
+ toolCalls?: ToolCall[]
402
+ ): void {
323
403
  this.boundModel = createFakeStreamingLLM({
324
404
  responses,
325
405
  sleep,
@@ -330,27 +410,39 @@ export class StandardGraph extends Graph<
330
410
  getNewModel({
331
411
  clientOptions = {},
332
412
  omitOriginalOptions,
333
- } : {
413
+ }: {
334
414
  clientOptions?: t.ClientOptions;
335
- omitOriginalOptions?: string[]
415
+ omitOriginalOptions?: Set<string>;
336
416
  }): t.ChatModelInstance {
337
417
  const ChatModelClass = getChatModelClass(this.provider);
338
- const _options = omitOriginalOptions ? Object.fromEntries(
339
- Object.entries(this.clientOptions).filter(([key]) => !omitOriginalOptions.includes(key)),
340
- ) : this.clientOptions;
418
+ const _options = omitOriginalOptions
419
+ ? Object.fromEntries(
420
+ Object.entries(this.clientOptions).filter(
421
+ ([key]) => !omitOriginalOptions.has(key)
422
+ )
423
+ )
424
+ : this.clientOptions;
341
425
  const options = Object.assign(_options, clientOptions);
342
426
  return new ChatModelClass(options);
343
427
  }
344
428
 
345
429
  storeUsageMetadata(finalMessage?: BaseMessage): void {
346
- if (finalMessage && 'usage_metadata' in finalMessage && finalMessage.usage_metadata) {
430
+ if (
431
+ finalMessage &&
432
+ 'usage_metadata' in finalMessage &&
433
+ finalMessage.usage_metadata
434
+ ) {
347
435
  this.currentUsage = finalMessage.usage_metadata as Partial<UsageMetadata>;
348
436
  }
349
437
  }
350
438
 
351
439
  createCallModel() {
352
- return async (state: t.BaseGraphState, config?: RunnableConfig): Promise<Partial<t.BaseGraphState>> => {
353
- const { provider = '' } = (config?.configurable as t.GraphConfig | undefined) ?? {} ;
440
+ return async (
441
+ state: t.BaseGraphState,
442
+ config?: RunnableConfig
443
+ ): Promise<Partial<t.BaseGraphState>> => {
444
+ const { provider = '' } =
445
+ (config?.configurable as t.GraphConfig | undefined) ?? {};
354
446
  if (!config || !provider) {
355
447
  throw new Error(`No ${config ? 'provider' : 'config'} provided`);
356
448
  }
@@ -361,19 +453,19 @@ export class StandardGraph extends Graph<
361
453
  const { messages } = state;
362
454
 
363
455
  let messagesToUse = messages;
364
- if (!this.pruneMessages && this.tokenCounter && this.maxContextTokens != null && this.indexTokenCountMap[0] != null) {
365
- const isAnthropicWithThinking = (
366
- (
367
- (
368
- this.provider === Providers.ANTHROPIC && (this.clientOptions as t.AnthropicClientOptions).thinking != null
369
- )
370
- ||
371
- (this.provider === Providers.BEDROCK && (
372
- (this.clientOptions as t.BedrockAnthropicInput).additionalModelRequestFields?.['thinking'] != null
373
- )
374
- )
375
- )
376
- );
456
+ if (
457
+ !this.pruneMessages &&
458
+ this.tokenCounter &&
459
+ this.maxContextTokens != null &&
460
+ this.indexTokenCountMap[0] != null
461
+ ) {
462
+ const isAnthropicWithThinking =
463
+ (this.provider === Providers.ANTHROPIC &&
464
+ (this.clientOptions as t.AnthropicClientOptions).thinking !=
465
+ null) ||
466
+ (this.provider === Providers.BEDROCK &&
467
+ (this.clientOptions as t.BedrockAnthropicInput)
468
+ .additionalModelRequestFields?.['thinking'] != null);
377
469
 
378
470
  this.pruneMessages = createPruneMessages({
379
471
  provider: this.provider,
@@ -395,14 +487,20 @@ export class StandardGraph extends Graph<
395
487
  }
396
488
 
397
489
  const finalMessages = messagesToUse;
398
- const lastMessageX = finalMessages.length >= 2 ? finalMessages[finalMessages.length - 2] : null;
399
- const lastMessageY = finalMessages.length >= 1 ? finalMessages[finalMessages.length - 1] : null;
490
+ const lastMessageX =
491
+ finalMessages.length >= 2
492
+ ? finalMessages[finalMessages.length - 2]
493
+ : null;
494
+ const lastMessageY =
495
+ finalMessages.length >= 1
496
+ ? finalMessages[finalMessages.length - 1]
497
+ : null;
400
498
 
401
499
  if (
402
- provider === Providers.BEDROCK
403
- && lastMessageX instanceof AIMessageChunk
404
- && lastMessageY instanceof ToolMessage
405
- && typeof lastMessageX.content === 'string'
500
+ provider === Providers.BEDROCK &&
501
+ lastMessageX instanceof AIMessageChunk &&
502
+ lastMessageY instanceof ToolMessage &&
503
+ typeof lastMessageX.content === 'string'
406
504
  ) {
407
505
  finalMessages[finalMessages.length - 2].content = '';
408
506
  }
@@ -421,7 +519,8 @@ export class StandardGraph extends Graph<
421
519
  if (this.lastStreamCall != null && this.streamBuffer != null) {
422
520
  const timeSinceLastCall = Date.now() - this.lastStreamCall;
423
521
  if (timeSinceLastCall < this.streamBuffer) {
424
- const timeToWait = Math.ceil((this.streamBuffer - timeSinceLastCall) / 1000) * 1000;
522
+ const timeToWait =
523
+ Math.ceil((this.streamBuffer - timeSinceLastCall) / 1000) * 1000;
425
524
  await sleep(timeToWait);
426
525
  }
427
526
  }
@@ -429,7 +528,10 @@ export class StandardGraph extends Graph<
429
528
  this.lastStreamCall = Date.now();
430
529
 
431
530
  let result: Partial<t.BaseGraphState>;
432
- if ((this.tools?.length ?? 0) > 0 && manualToolStreamProviders.has(provider)) {
531
+ if (
532
+ (this.tools?.length ?? 0) > 0 &&
533
+ manualToolStreamProviders.has(provider)
534
+ ) {
433
535
  const stream = await this.boundModel.stream(finalMessages, config);
434
536
  let finalChunk: AIMessageChunk | undefined;
435
537
  for await (const chunk of stream) {
@@ -444,14 +546,19 @@ export class StandardGraph extends Graph<
444
546
  finalChunk = modifyDeltaProperties(this.provider, finalChunk);
445
547
  result = { messages: [finalChunk as AIMessageChunk] };
446
548
  } else {
447
- const finalMessage = (await this.boundModel.invoke(finalMessages, config)) as AIMessageChunk;
549
+ const finalMessage = (await this.boundModel.invoke(
550
+ finalMessages,
551
+ config
552
+ )) as AIMessageChunk;
448
553
  if ((finalMessage.tool_calls?.length ?? 0) > 0) {
449
- finalMessage.tool_calls = finalMessage.tool_calls?.filter((tool_call) => {
450
- if (!tool_call.name) {
451
- return false;
554
+ finalMessage.tool_calls = finalMessage.tool_calls?.filter(
555
+ (tool_call) => {
556
+ if (!tool_call.name) {
557
+ return false;
558
+ }
559
+ return true;
452
560
  }
453
- return true;
454
- });
561
+ );
455
562
  }
456
563
  result = { messages: [finalMessage] };
457
564
  }
@@ -462,7 +569,10 @@ export class StandardGraph extends Graph<
462
569
  }
463
570
 
464
571
  createWorkflow(): t.CompiledWorkflow<t.BaseGraphState> {
465
- const routeMessage = (state: t.BaseGraphState, config?: RunnableConfig): string => {
572
+ const routeMessage = (
573
+ state: t.BaseGraphState,
574
+ config?: RunnableConfig
575
+ ): string => {
466
576
  this.config = config;
467
577
  // const lastMessage = state.messages[state.messages.length - 1] as AIMessage;
468
578
  // if (!lastMessage?.tool_calls?.length) {
@@ -525,7 +635,10 @@ export class StandardGraph extends Graph<
525
635
  return stepId;
526
636
  }
527
637
 
528
- handleToolCallCompleted(data: t.ToolEndData, metadata?: Record<string, unknown>): void {
638
+ handleToolCallCompleted(
639
+ data: t.ToolEndData,
640
+ metadata?: Record<string, unknown>
641
+ ): void {
529
642
  if (!this.config) {
530
643
  throw new Error('No config provided');
531
644
  }
@@ -551,26 +664,31 @@ export class StandardGraph extends Graph<
551
664
  args: typeof args === 'string' ? args : JSON.stringify(args),
552
665
  name: output.name ?? '',
553
666
  id: output.tool_call_id,
554
- output: typeof output.content === 'string'
555
- ? output.content
556
- : JSON.stringify(output.content),
667
+ output:
668
+ typeof output.content === 'string'
669
+ ? output.content
670
+ : JSON.stringify(output.content),
557
671
  progress: 1,
558
672
  };
559
673
 
560
674
  this.handlerRegistry?.getHandler(GraphEvents.ON_RUN_STEP_COMPLETED)?.handle(
561
675
  GraphEvents.ON_RUN_STEP_COMPLETED,
562
- { result: {
563
- id: stepId,
564
- index: runStep.index,
565
- type: 'tool_call',
566
- tool_call
567
- } as t.ToolCompleteEvent,
676
+ {
677
+ result: {
678
+ id: stepId,
679
+ index: runStep.index,
680
+ type: 'tool_call',
681
+ tool_call,
682
+ } as t.ToolCompleteEvent,
568
683
  },
569
684
  metadata,
570
- this,
685
+ this
571
686
  );
572
687
  }
573
- handleToolCallError(data: t.ToolErrorData, metadata?: Record<string, unknown>): void {
688
+ handleToolCallError(
689
+ data: t.ToolErrorData,
690
+ metadata?: Record<string, unknown>
691
+ ): void {
574
692
  if (!this.config) {
575
693
  throw new Error('No config provided');
576
694
  }
@@ -602,15 +720,16 @@ export class StandardGraph extends Graph<
602
720
 
603
721
  this.handlerRegistry?.getHandler(GraphEvents.ON_RUN_STEP_COMPLETED)?.handle(
604
722
  GraphEvents.ON_RUN_STEP_COMPLETED,
605
- { result: {
606
- id: stepId,
607
- index: runStep.index,
608
- type: 'tool_call',
609
- tool_call
610
- } as t.ToolCompleteEvent,
723
+ {
724
+ result: {
725
+ id: stepId,
726
+ index: runStep.index,
727
+ type: 'tool_call',
728
+ tool_call,
729
+ } as t.ToolCompleteEvent,
611
730
  },
612
731
  metadata,
613
- this,
732
+ this
614
733
  );
615
734
  }
616
735
 
@@ -624,7 +743,11 @@ export class StandardGraph extends Graph<
624
743
  id,
625
744
  delta,
626
745
  };
627
- dispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
746
+ dispatchCustomEvent(
747
+ GraphEvents.ON_RUN_STEP_DELTA,
748
+ runStepDelta,
749
+ this.config
750
+ );
628
751
  }
629
752
 
630
753
  dispatchMessageDelta(id: string, delta: t.MessageDelta): void {
@@ -635,7 +758,11 @@ export class StandardGraph extends Graph<
635
758
  id,
636
759
  delta,
637
760
  };
638
- dispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
761
+ dispatchCustomEvent(
762
+ GraphEvents.ON_MESSAGE_DELTA,
763
+ messageDelta,
764
+ this.config
765
+ );
639
766
  }
640
767
 
641
768
  dispatchReasoningDelta = (stepId: string, delta: t.ReasoningDelta): void => {
@@ -646,6 +773,10 @@ export class StandardGraph extends Graph<
646
773
  id: stepId,
647
774
  delta,
648
775
  };
649
- dispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
776
+ dispatchCustomEvent(
777
+ GraphEvents.ON_REASONING_DELTA,
778
+ reasoningDelta,
779
+ this.config
780
+ );
650
781
  };
651
782
  }
@@ -341,6 +341,7 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
341
341
  totalTokens = currentUsage.total_tokens;
342
342
  }
343
343
 
344
+ const newOutputs = new Set<number>();
344
345
  for (let i = lastTurnStartIndex; i < params.messages.length; i++) {
345
346
  const message = params.messages[i];
346
347
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
@@ -349,6 +350,9 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
349
350
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
350
351
  } else if (indexTokenCountMap[i] === undefined) {
351
352
  indexTokenCountMap[i] = factoryParams.tokenCounter(message);
353
+ if (currentUsage) {
354
+ newOutputs.add(i);
355
+ }
352
356
  totalTokens += indexTokenCountMap[i];
353
357
  }
354
358
  }
@@ -366,6 +370,9 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
366
370
  if (i === 0 && params.messages[0].getType() === 'system') {
367
371
  continue;
368
372
  }
373
+ if (newOutputs.has(i)) {
374
+ continue;
375
+ }
369
376
  totalIndexTokens += indexTokenCountMap[i];
370
377
  }
371
378
 
@@ -380,13 +387,16 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
380
387
  }
381
388
 
382
389
  for (let i = lastCutOffIndex; i < params.messages.length; i++) {
390
+ if (newOutputs.has(i)) {
391
+ continue;
392
+ }
383
393
  indexTokenCountMap[i] = Math.round(indexTokenCountMap[i] * ratio);
384
394
  }
385
395
  }
386
396
  }
387
397
 
388
398
  lastTurnStartIndex = params.messages.length;
389
- if (totalTokens <= factoryParams.maxTokens) {
399
+ if (lastCutOffIndex === 0 && totalTokens <= factoryParams.maxTokens) {
390
400
  return { context: params.messages, indexTokenCountMap };
391
401
  }
392
402