@librechat/agents 2.4.41 → 2.4.43

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 (62) hide show
  1. package/dist/cjs/common/enum.cjs +4 -2
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +5 -6
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/llm/google/index.cjs +73 -1
  6. package/dist/cjs/llm/google/index.cjs.map +1 -1
  7. package/dist/cjs/llm/google/utils/common.cjs +469 -0
  8. package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
  9. package/dist/cjs/run.cjs +4 -3
  10. package/dist/cjs/run.cjs.map +1 -1
  11. package/dist/cjs/stream.cjs +5 -2
  12. package/dist/cjs/stream.cjs.map +1 -1
  13. package/dist/cjs/utils/title.cjs +25 -20
  14. package/dist/cjs/utils/title.cjs.map +1 -1
  15. package/dist/esm/common/enum.mjs +4 -2
  16. package/dist/esm/common/enum.mjs.map +1 -1
  17. package/dist/esm/graphs/Graph.mjs +5 -6
  18. package/dist/esm/graphs/Graph.mjs.map +1 -1
  19. package/dist/esm/llm/google/index.mjs +73 -1
  20. package/dist/esm/llm/google/index.mjs.map +1 -1
  21. package/dist/esm/llm/google/utils/common.mjs +463 -0
  22. package/dist/esm/llm/google/utils/common.mjs.map +1 -0
  23. package/dist/esm/run.mjs +4 -3
  24. package/dist/esm/run.mjs.map +1 -1
  25. package/dist/esm/stream.mjs +5 -2
  26. package/dist/esm/stream.mjs.map +1 -1
  27. package/dist/esm/utils/title.mjs +25 -20
  28. package/dist/esm/utils/title.mjs.map +1 -1
  29. package/dist/types/common/enum.d.ts +5 -3
  30. package/dist/types/graphs/Graph.d.ts +3 -2
  31. package/dist/types/llm/google/index.d.ts +10 -5
  32. package/dist/types/llm/google/types.d.ts +32 -0
  33. package/dist/types/llm/google/utils/common.d.ts +19 -0
  34. package/dist/types/llm/google/utils/tools.d.ts +10 -0
  35. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
  36. package/dist/types/run.d.ts +1 -1
  37. package/dist/types/scripts/args.d.ts +2 -1
  38. package/dist/types/types/llm.d.ts +2 -0
  39. package/dist/types/types/run.d.ts +1 -0
  40. package/dist/types/types/stream.d.ts +5 -0
  41. package/package.json +1 -1
  42. package/src/common/enum.ts +4 -2
  43. package/src/graphs/Graph.ts +16 -11
  44. package/src/llm/google/index.ts +118 -8
  45. package/src/llm/google/types.ts +43 -0
  46. package/src/llm/google/utils/common.ts +632 -0
  47. package/src/llm/google/utils/tools.ts +160 -0
  48. package/src/llm/google/utils/zod_to_genai_parameters.ts +88 -0
  49. package/src/run.ts +4 -2
  50. package/src/scripts/args.ts +12 -8
  51. package/src/scripts/code_exec.ts +49 -18
  52. package/src/scripts/code_exec_files.ts +48 -17
  53. package/src/scripts/image.ts +52 -20
  54. package/src/scripts/simple.ts +1 -0
  55. package/src/specs/anthropic.simple.test.ts +88 -31
  56. package/src/specs/openai.simple.test.ts +88 -31
  57. package/src/stream.ts +5 -2
  58. package/src/types/llm.ts +2 -0
  59. package/src/types/run.ts +1 -0
  60. package/src/types/stream.ts +6 -0
  61. package/src/utils/llmConfig.ts +2 -2
  62. package/src/utils/title.ts +44 -27
@@ -8,6 +8,7 @@ import type { BindToolsInput, BaseChatModelParams } from '@langchain/core/langua
8
8
  import type { OpenAIChatInput, ChatOpenAIFields, AzureOpenAIInput, ClientOptions as OAIClientOptions } from '@langchain/openai';
9
9
  import type { BedrockChatFields } from '@langchain/community/chat_models/bedrock/web';
10
10
  import type { GoogleGenerativeAIChatInput } from '@langchain/google-genai';
11
+ import type { GeminiGenerationConfig } from '@langchain/google-common';
11
12
  import type { ChatVertexAIInput } from '@langchain/google-vertexai';
12
13
  import type { ChatDeepSeekCallOptions } from '@langchain/deepseek';
13
14
  import type { ChatOpenRouterCallOptions } from '@/llm/openrouter';
@@ -51,6 +52,7 @@ export type BedrockAnthropicInput = ChatBedrockConverseInput & {
51
52
  export type BedrockConverseClientOptions = ChatBedrockConverseInput;
52
53
  export type GoogleClientOptions = GoogleGenerativeAIChatInput & {
53
54
  customHeaders?: RequestOptions['customHeaders'];
55
+ thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];
54
56
  };
55
57
  export type DeepSeekClientOptions = ChatDeepSeekCallOptions;
56
58
  export type XAIClientOptions = ChatXAIInput;
@@ -18,6 +18,7 @@ export type BaseGraphConfig = {
18
18
  export type StandardGraphConfig = BaseGraphConfig & Omit<g.StandardGraphInput, 'provider' | 'clientOptions'>;
19
19
  export type RunTitleOptions = {
20
20
  inputText: string;
21
+ provider: e.Providers;
21
22
  contentParts: (s.MessageContentComplex | undefined)[];
22
23
  titlePrompt?: string;
23
24
  skipLanguage?: boolean;
@@ -191,6 +191,11 @@ export type ReasoningContentText = {
191
191
  type: ContentTypes.THINK;
192
192
  think: string;
193
193
  };
194
+ /** Vertex AI / Google Common - Reasoning Content Block Format */
195
+ export type GoogleReasoningContentText = {
196
+ type: ContentTypes.REASONING;
197
+ reasoning: string;
198
+ };
194
199
  /** Anthropic's Reasoning Content Block Format */
195
200
  export type ThinkingContentText = {
196
201
  type: ContentTypes.THINKING;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "2.4.41",
3
+ "version": "2.4.43",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -117,10 +117,12 @@ export enum ContentTypes {
117
117
  IMAGE_FILE = 'image_file',
118
118
  /** Anthropic */
119
119
  THINKING = 'thinking',
120
- /** Bedrock */
121
- REASONING_CONTENT = 'reasoning_content',
120
+ /** Vertex AI / Google Common */
121
+ REASONING = 'reasoning',
122
122
  /** Multi-Agent Switch */
123
123
  AGENT_UPDATE = 'agent_update',
124
+ /** Bedrock */
125
+ REASONING_CONTENT = 'reasoning_content',
124
126
  }
125
127
 
126
128
  export enum ToolCallTypes {
@@ -417,21 +417,26 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
417
417
  }
418
418
 
419
419
  getNewModel({
420
- clientOptions = {},
421
- omitOriginalOptions,
420
+ provider,
421
+ clientOptions,
422
+ omitOptions,
422
423
  }: {
424
+ provider: Providers;
423
425
  clientOptions?: t.ClientOptions;
424
- omitOriginalOptions?: Set<string>;
426
+ omitOptions?: Set<string>;
425
427
  }): t.ChatModelInstance {
426
- const ChatModelClass = getChatModelClass(this.provider);
427
- const _options = omitOriginalOptions
428
- ? Object.fromEntries(
429
- Object.entries(this.clientOptions).filter(
430
- ([key]) => !omitOriginalOptions.has(key)
428
+ const ChatModelClass = getChatModelClass(provider);
429
+ const options =
430
+ omitOptions && clientOptions == null
431
+ ? Object.assign(
432
+ Object.fromEntries(
433
+ Object.entries(this.clientOptions).filter(
434
+ ([key]) => !omitOptions.has(key)
435
+ )
436
+ ),
437
+ clientOptions
431
438
  )
432
- )
433
- : this.clientOptions;
434
- const options = Object.assign(_options, clientOptions);
439
+ : (clientOptions ?? this.clientOptions);
435
440
  return new ChatModelClass(options);
436
441
  }
437
442
 
@@ -1,15 +1,25 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
1
2
  import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
2
3
  import { getEnvironmentVariable } from '@langchain/core/utils/env';
3
4
  import { GoogleGenerativeAI as GenerativeAI } from '@google/generative-ai';
4
- import type { GoogleGenerativeAIChatInput } from '@langchain/google-genai';
5
- import type { RequestOptions, SafetySetting } from '@google/generative-ai';
5
+ import type {
6
+ GenerateContentRequest,
7
+ SafetySetting,
8
+ } from '@google/generative-ai';
9
+ import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
10
+ import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
11
+ import type { GeminiGenerationConfig } from '@langchain/google-common';
12
+ import type { ChatGenerationChunk } from '@langchain/core/outputs';
13
+ import type { GeminiApiUsageMetadata } from './types';
14
+ import type { GoogleClientOptions } from '@/types';
15
+ import {
16
+ convertResponseContentToChatGenerationChunk,
17
+ convertBaseMessagesToContent,
18
+ } from './utils/common';
6
19
 
7
20
  export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
8
- constructor(
9
- fields: GoogleGenerativeAIChatInput & {
10
- customHeaders?: RequestOptions['customHeaders'];
11
- }
12
- ) {
21
+ thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];
22
+ constructor(fields: GoogleClientOptions) {
13
23
  super(fields);
14
24
 
15
25
  this.model = fields.model.replace(/^models\//, '');
@@ -66,10 +76,11 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
66
76
  }
67
77
  }
68
78
 
79
+ this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;
80
+
69
81
  this.streaming = fields.streaming ?? this.streaming;
70
82
  this.json = fields.json;
71
83
 
72
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
73
84
  // @ts-ignore - Accessing private property from parent class
74
85
  this.client = new GenerativeAI(this.apiKey).getGenerativeModel(
75
86
  {
@@ -94,4 +105,103 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
94
105
  );
95
106
  this.streamUsage = fields.streamUsage ?? this.streamUsage;
96
107
  }
108
+
109
+ invocationParams(
110
+ options?: this['ParsedCallOptions']
111
+ ): Omit<GenerateContentRequest, 'contents'> {
112
+ const params = super.invocationParams(options);
113
+ return {
114
+ ...params,
115
+ generationConfig: {
116
+ ...params.generationConfig,
117
+
118
+ /** @ts-ignore */
119
+ thinkingConfig: this.thinkingConfig,
120
+ },
121
+ };
122
+ }
123
+
124
+ async *_streamResponseChunks(
125
+ messages: BaseMessage[],
126
+ options: this['ParsedCallOptions'],
127
+ runManager?: CallbackManagerForLLMRun
128
+ ): AsyncGenerator<ChatGenerationChunk> {
129
+ const prompt = convertBaseMessagesToContent(
130
+ messages,
131
+ this._isMultimodalModel,
132
+ this.useSystemInstruction
133
+ );
134
+ let actualPrompt = prompt;
135
+ if (prompt[0].role === 'system') {
136
+ const [systemInstruction] = prompt;
137
+ /** @ts-ignore */
138
+ this.client.systemInstruction = systemInstruction;
139
+ actualPrompt = prompt.slice(1);
140
+ }
141
+ const parameters = this.invocationParams(options);
142
+ const request = {
143
+ ...parameters,
144
+ contents: actualPrompt,
145
+ };
146
+ const stream = await this.caller.callWithOptions(
147
+ { signal: options.signal },
148
+ async () => {
149
+ /** @ts-ignore */
150
+ const { stream } = await this.client.generateContentStream(request);
151
+ return stream;
152
+ }
153
+ );
154
+
155
+ let usageMetadata: UsageMetadata | undefined;
156
+ let index = 0;
157
+ for await (const response of stream) {
158
+ if (
159
+ 'usageMetadata' in response &&
160
+ this.streamUsage !== false &&
161
+ options.streamUsage !== false
162
+ ) {
163
+ const genAIUsageMetadata = response.usageMetadata as
164
+ | GeminiApiUsageMetadata
165
+ | undefined;
166
+ const output_tokens =
167
+ (genAIUsageMetadata?.candidatesTokenCount ?? 0) +
168
+ (genAIUsageMetadata?.thoughtsTokenCount ?? 0);
169
+ if (!usageMetadata) {
170
+ usageMetadata = {
171
+ input_tokens: genAIUsageMetadata?.promptTokenCount ?? 0,
172
+ output_tokens,
173
+ total_tokens: genAIUsageMetadata?.totalTokenCount ?? 0,
174
+ };
175
+ } else {
176
+ // Under the hood, LangChain combines the prompt tokens. Google returns the updated
177
+ // total each time, so we need to find the difference between the tokens.
178
+ const outputTokenDiff = output_tokens - usageMetadata.output_tokens;
179
+ usageMetadata = {
180
+ input_tokens: 0,
181
+ output_tokens: outputTokenDiff,
182
+ total_tokens: outputTokenDiff,
183
+ };
184
+ }
185
+ }
186
+
187
+ const chunk = convertResponseContentToChatGenerationChunk(response, {
188
+ usageMetadata,
189
+ index,
190
+ });
191
+ index += 1;
192
+ if (!chunk) {
193
+ continue;
194
+ }
195
+
196
+ yield chunk;
197
+ await runManager?.handleLLMNewToken(
198
+ chunk.text || '',
199
+ undefined,
200
+ undefined,
201
+ undefined,
202
+ undefined,
203
+ { chunk }
204
+ );
205
+ }
206
+ }
97
207
  }
@@ -0,0 +1,43 @@
1
+ import {
2
+ CodeExecutionTool,
3
+ FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool,
4
+ GoogleSearchRetrievalTool,
5
+ } from '@google/generative-ai';
6
+ import { BindToolsInput } from '@langchain/core/language_models/chat_models';
7
+
8
+ export type GoogleGenerativeAIToolType =
9
+ | BindToolsInput
10
+ | GoogleGenerativeAIFunctionDeclarationsTool
11
+ | CodeExecutionTool
12
+ | GoogleSearchRetrievalTool;
13
+
14
+ /** Enum for content modality types */
15
+ enum Modality {
16
+ MODALITY_UNSPECIFIED = 'MODALITY_UNSPECIFIED',
17
+ TEXT = 'TEXT',
18
+ IMAGE = 'IMAGE',
19
+ VIDEO = 'VIDEO',
20
+ AUDIO = 'AUDIO',
21
+ DOCUMENT = 'DOCUMENT',
22
+ }
23
+
24
+ /** Interface for modality token count */
25
+ interface ModalityTokenCount {
26
+ modality: Modality;
27
+ tokenCount: number;
28
+ }
29
+
30
+ /** Main interface for Gemini API usage metadata */
31
+ export interface GeminiApiUsageMetadata {
32
+ promptTokenCount?: number;
33
+ totalTokenCount?: number;
34
+ thoughtsTokenCount?: number;
35
+ candidatesTokenCount?: number;
36
+ toolUsePromptTokenCount?: number;
37
+ cachedContentTokenCount?: number;
38
+ promptTokensDetails: ModalityTokenCount[];
39
+ candidatesTokensDetails?: ModalityTokenCount[];
40
+ cacheTokensDetails?: ModalityTokenCount[];
41
+ toolUsePromptTokensDetails?: ModalityTokenCount[];
42
+ trafficType?: string;
43
+ }