illuma-agents 1.0.9 → 1.0.11
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/LICENSE +1 -1
- package/dist/cjs/agents/AgentContext.cjs +228 -27
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +2 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +3 -0
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +29 -19
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +1 -1
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +1 -1
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +122 -7
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +1 -1
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +108 -6
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +87 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +176 -2
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +18 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +149 -54
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +85 -0
- package/dist/cjs/messages/tools.cjs.map +1 -0
- package/dist/cjs/stream.cjs +20 -0
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +4 -0
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +438 -0
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -0
- package/dist/cjs/tools/ToolNode.cjs +54 -6
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearchRegex.cjs +455 -0
- package/dist/cjs/tools/ToolSearchRegex.cjs.map +1 -0
- package/dist/cjs/tools/search/tool.cjs +21 -1
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs +5 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +228 -27
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +2 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +4 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +29 -19
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +1 -1
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +1 -1
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +122 -7
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +1 -1
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +109 -7
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +88 -2
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +176 -2
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/main.mjs +3 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +149 -54
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs +82 -0
- package/dist/esm/messages/tools.mjs.map +1 -0
- package/dist/esm/stream.mjs +20 -0
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +4 -0
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +430 -0
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -0
- package/dist/esm/tools/ToolNode.mjs +54 -6
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearchRegex.mjs +448 -0
- package/dist/esm/tools/ToolSearchRegex.mjs.map +1 -0
- package/dist/esm/tools/search/tool.mjs +21 -1
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/utils/run.mjs +5 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +65 -5
- package/dist/types/common/enum.d.ts +2 -0
- package/dist/types/graphs/Graph.d.ts +3 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/llm/anthropic/index.d.ts +1 -1
- package/dist/types/llm/bedrock/index.d.ts +31 -4
- package/dist/types/llm/google/index.d.ts +1 -1
- package/dist/types/llm/openai/index.d.ts +4 -3
- package/dist/types/llm/openai/utils/index.d.ts +10 -1
- package/dist/types/llm/openrouter/index.d.ts +5 -2
- package/dist/types/messages/cache.d.ts +23 -8
- package/dist/types/messages/index.d.ts +1 -0
- package/dist/types/messages/tools.d.ts +17 -0
- package/dist/types/test/mockTools.d.ts +28 -0
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +91 -0
- package/dist/types/tools/ToolNode.d.ts +10 -2
- package/dist/types/tools/ToolSearchRegex.d.ts +80 -0
- package/dist/types/types/graph.d.ts +7 -1
- package/dist/types/types/tools.d.ts +138 -0
- package/package.json +8 -3
- package/src/agents/AgentContext.ts +267 -27
- package/src/agents/__tests__/AgentContext.test.ts +805 -0
- package/src/common/enum.ts +2 -0
- package/src/events.ts +5 -1
- package/src/graphs/Graph.ts +35 -20
- package/src/index.ts +2 -0
- package/src/instrumentation.ts +1 -1
- package/src/llm/anthropic/index.ts +2 -2
- package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +473 -0
- package/src/llm/bedrock/index.ts +150 -13
- package/src/llm/google/index.ts +2 -2
- package/src/llm/google/llm.spec.ts +3 -1
- package/src/llm/openai/index.ts +135 -9
- package/src/llm/openai/utils/index.ts +116 -1
- package/src/llm/openrouter/index.ts +224 -3
- package/src/messages/__tests__/tools.test.ts +473 -0
- package/src/messages/cache.ts +163 -61
- package/src/messages/index.ts +1 -0
- package/src/messages/tools.ts +99 -0
- package/src/scripts/code_exec_ptc.ts +334 -0
- package/src/scripts/programmatic_exec.ts +396 -0
- package/src/scripts/programmatic_exec_agent.ts +231 -0
- package/src/scripts/tool_search_regex.ts +162 -0
- package/src/specs/thinking-prune.test.ts +52 -118
- package/src/stream.ts +26 -0
- package/src/test/mockTools.ts +366 -0
- package/src/tools/CodeExecutor.ts +4 -0
- package/src/tools/ProgrammaticToolCalling.ts +558 -0
- package/src/tools/ToolNode.ts +60 -7
- package/src/tools/ToolSearchRegex.ts +535 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.ts +318 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +853 -0
- package/src/tools/__tests__/ToolSearchRegex.integration.test.ts +161 -0
- package/src/tools/__tests__/ToolSearchRegex.test.ts +232 -0
- package/src/tools/search/jina-reranker.test.ts +16 -16
- package/src/tools/search/tool.ts +23 -1
- package/src/types/graph.ts +7 -1
- package/src/types/tools.ts +166 -0
- package/src/utils/llmConfig.ts +8 -2
- package/src/utils/run.ts +5 -1
- package/src/tools/search/direct-url.test.ts +0 -530
|
@@ -6,6 +6,7 @@ var outputs = require('@langchain/core/outputs');
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Optimized ChatBedrockConverse wrapper that fixes contentBlockIndex conflicts
|
|
9
|
+
* and adds prompt caching support for Bedrock Converse API.
|
|
9
10
|
*
|
|
10
11
|
* Bedrock sends the same contentBlockIndex for both text and tool_use content blocks,
|
|
11
12
|
* causing LangChain's merge logic to fail with "field[contentBlockIndex] already exists"
|
|
@@ -15,18 +16,97 @@ var outputs = require('@langchain/core/outputs');
|
|
|
15
16
|
* The contentBlockIndex field is only used internally by Bedrock's streaming protocol
|
|
16
17
|
* and isn't needed by application logic - the index field on tool_call_chunks serves
|
|
17
18
|
* the purpose of tracking tool call ordering.
|
|
19
|
+
*
|
|
20
|
+
* PROMPT CACHING:
|
|
21
|
+
* When promptCache: true is set, this wrapper adds cachePoint markers to the tools array
|
|
22
|
+
* to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be
|
|
23
|
+
* cached and reused across requests, reducing latency and costs.
|
|
24
|
+
*
|
|
25
|
+
* CACHE TOKEN EXTRACTION:
|
|
26
|
+
* LangChain AWS doesn't extract cacheReadInputTokens/cacheWriteInputTokens from Bedrock's
|
|
27
|
+
* response. This wrapper adds input_token_details to usage_metadata with cache information.
|
|
18
28
|
*/
|
|
19
29
|
class CustomChatBedrockConverse extends aws.ChatBedrockConverse {
|
|
30
|
+
promptCache;
|
|
20
31
|
constructor(fields) {
|
|
21
32
|
super(fields);
|
|
33
|
+
this.promptCache = fields?.promptCache ?? false;
|
|
22
34
|
}
|
|
23
35
|
static lc_name() {
|
|
24
|
-
return '
|
|
36
|
+
return 'LibreChatBedrockConverse';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Override invocationParams to add cachePoint to tools when promptCache is enabled.
|
|
40
|
+
* This enables Bedrock prompt caching for tool definitions.
|
|
41
|
+
*
|
|
42
|
+
* STRATEGY: Separate cachePoints for core tools and MCP tools
|
|
43
|
+
* - Core tools (web_search, execute_code, etc.) are stable → cache first
|
|
44
|
+
* - MCP tools (have '_mcp_' in name) are dynamic → cache separately after
|
|
45
|
+
* - This allows core tools to stay cached when MCP selection changes
|
|
46
|
+
*
|
|
47
|
+
* NOTE: Only Claude models support cachePoint - Nova and other models will reject it.
|
|
48
|
+
*/
|
|
49
|
+
invocationParams(options) {
|
|
50
|
+
const params = super.invocationParams(options);
|
|
51
|
+
// Add cachePoint to tools array if promptCache is enabled and tools exist
|
|
52
|
+
// Only Claude models support cachePoint - check model name
|
|
53
|
+
const modelId = this.model?.toLowerCase() ?? '';
|
|
54
|
+
const isClaudeModel = modelId.includes('claude') || modelId.includes('anthropic');
|
|
55
|
+
if (this.promptCache &&
|
|
56
|
+
isClaudeModel &&
|
|
57
|
+
params.toolConfig?.tools &&
|
|
58
|
+
Array.isArray(params.toolConfig.tools) &&
|
|
59
|
+
params.toolConfig.tools.length > 0) {
|
|
60
|
+
// Separate core tools from MCP tools
|
|
61
|
+
// MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')
|
|
62
|
+
const coreTools = [];
|
|
63
|
+
const mcpTools = [];
|
|
64
|
+
const coreToolNames = [];
|
|
65
|
+
const mcpToolNames = [];
|
|
66
|
+
for (const tool of params.toolConfig.tools) {
|
|
67
|
+
// Check if tool has a name property with '_mcp_' pattern
|
|
68
|
+
const toolName = tool?.toolSpec?.name ?? '';
|
|
69
|
+
if (toolName.includes('_mcp_')) {
|
|
70
|
+
mcpTools.push(tool);
|
|
71
|
+
mcpToolNames.push(toolName);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
coreTools.push(tool);
|
|
75
|
+
coreToolNames.push(toolName);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Always log cache structure (INFO level for tracking)
|
|
79
|
+
console.log(`[Cache] 🔧 Tools | Core: [${coreToolNames.join(', ')}] (${coreTools.length}) | MCP: [${mcpToolNames.join(', ')}] (${mcpTools.length})`);
|
|
80
|
+
// Build tools array with strategic cachePoints:
|
|
81
|
+
// [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]
|
|
82
|
+
const toolsWithCache = [];
|
|
83
|
+
let cachePointCount = 0;
|
|
84
|
+
// Add core tools with cachePoint (if any)
|
|
85
|
+
if (coreTools.length > 0) {
|
|
86
|
+
toolsWithCache.push(...coreTools);
|
|
87
|
+
toolsWithCache.push({ cachePoint: { type: 'default' } });
|
|
88
|
+
cachePointCount++;
|
|
89
|
+
}
|
|
90
|
+
// Add MCP tools with their own cachePoint (if any)
|
|
91
|
+
if (mcpTools.length > 0) {
|
|
92
|
+
toolsWithCache.push(...mcpTools);
|
|
93
|
+
toolsWithCache.push({ cachePoint: { type: 'default' } });
|
|
94
|
+
cachePointCount++;
|
|
95
|
+
}
|
|
96
|
+
// If no tools at all (shouldn't happen but safety check)
|
|
97
|
+
if (toolsWithCache.length === 0) {
|
|
98
|
+
toolsWithCache.push({ cachePoint: { type: 'default' } });
|
|
99
|
+
cachePointCount++;
|
|
100
|
+
}
|
|
101
|
+
console.log(`[Cache] 📍 Tool cachePoints: ${cachePointCount} | Order: [${coreToolNames.length > 0 ? 'CoreTools→CP' : ''}${mcpToolNames.length > 0 ? '→MCPTools→CP' : ''}]`);
|
|
102
|
+
params.toolConfig.tools = toolsWithCache;
|
|
103
|
+
}
|
|
104
|
+
return params;
|
|
25
105
|
}
|
|
26
106
|
/**
|
|
27
|
-
* Override _streamResponseChunks to
|
|
28
|
-
*
|
|
29
|
-
*
|
|
107
|
+
* Override _streamResponseChunks to:
|
|
108
|
+
* 1. Strip contentBlockIndex from response_metadata to prevent merge conflicts
|
|
109
|
+
* 2. Extract cacheReadInputTokens/cacheWriteInputTokens and add to usage_metadata
|
|
30
110
|
*/
|
|
31
111
|
async *_streamResponseChunks(messages$1, options, runManager) {
|
|
32
112
|
const baseStream = super._streamResponseChunks(messages$1, options, runManager);
|
|
@@ -35,15 +115,50 @@ class CustomChatBedrockConverse extends aws.ChatBedrockConverse {
|
|
|
35
115
|
if (chunk.message instanceof messages.AIMessageChunk &&
|
|
36
116
|
chunk.message.response_metadata &&
|
|
37
117
|
typeof chunk.message.response_metadata === 'object') {
|
|
38
|
-
|
|
39
|
-
|
|
118
|
+
const responseMetadata = chunk.message.response_metadata;
|
|
119
|
+
let needsModification = false;
|
|
120
|
+
let cleanedMetadata = responseMetadata;
|
|
121
|
+
// Check if contentBlockIndex exists anywhere in response_metadata
|
|
122
|
+
const hasContentBlockIndex = this.hasContentBlockIndex(responseMetadata);
|
|
40
123
|
if (hasContentBlockIndex) {
|
|
41
|
-
|
|
124
|
+
cleanedMetadata = this.removeContentBlockIndex(responseMetadata);
|
|
125
|
+
needsModification = true;
|
|
126
|
+
}
|
|
127
|
+
// Extract cache tokens from metadata.usage (Bedrock streaming format)
|
|
128
|
+
// The metadata chunk contains usage with cacheReadInputTokens/cacheWriteInputTokens
|
|
129
|
+
const metadata = responseMetadata.metadata;
|
|
130
|
+
const usage = (metadata?.usage ?? responseMetadata.usage);
|
|
131
|
+
let enhancedUsageMetadata = chunk.message.usage_metadata;
|
|
132
|
+
if (usage) {
|
|
133
|
+
const cacheRead = usage.cacheReadInputTokens ?? 0;
|
|
134
|
+
const cacheWrite = usage.cacheWriteInputTokens ?? 0;
|
|
135
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
136
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
137
|
+
if (cacheRead > 0 || cacheWrite > 0) {
|
|
138
|
+
// Always log cache results for tracking
|
|
139
|
+
const cacheStatus = cacheRead > 0 && cacheWrite === 0 ? '✅ HIT' :
|
|
140
|
+
cacheWrite > 0 && cacheRead === 0 ? '📝 WRITE' :
|
|
141
|
+
cacheRead > 0 && cacheWrite > 0 ? '🔄 PARTIAL' : '❌ MISS';
|
|
142
|
+
console.log(`[Cache] ${cacheStatus} | read=${cacheRead} | write=${cacheWrite} | input=${inputTokens} | output=${outputTokens}`);
|
|
143
|
+
needsModification = true;
|
|
144
|
+
enhancedUsageMetadata = {
|
|
145
|
+
input_tokens: chunk.message.usage_metadata?.input_tokens ?? inputTokens,
|
|
146
|
+
output_tokens: chunk.message.usage_metadata?.output_tokens ?? outputTokens,
|
|
147
|
+
total_tokens: chunk.message.usage_metadata?.total_tokens ?? usage.totalTokens ?? 0,
|
|
148
|
+
input_token_details: {
|
|
149
|
+
cache_read: cacheRead,
|
|
150
|
+
cache_creation: cacheWrite,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (needsModification) {
|
|
42
156
|
yield new outputs.ChatGenerationChunk({
|
|
43
157
|
text: chunk.text,
|
|
44
158
|
message: new messages.AIMessageChunk({
|
|
45
159
|
...chunk.message,
|
|
46
160
|
response_metadata: cleanedMetadata,
|
|
161
|
+
usage_metadata: enhancedUsageMetadata,
|
|
47
162
|
}),
|
|
48
163
|
generationInfo: chunk.generationInfo,
|
|
49
164
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes contentBlockIndex conflicts\n *\n * Bedrock sends the same contentBlockIndex for both text and tool_use content blocks,\n * causing LangChain's merge logic to fail with \"field[contentBlockIndex] already exists\"\n * errors. This wrapper simply strips contentBlockIndex from response_metadata to avoid\n * the conflict.\n *\n * The contentBlockIndex field is only used internally by Bedrock's streaming protocol\n * and isn't needed by application logic - the index field on tool_call_chunks serves\n * the purpose of tracking tool call ordering.\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\n\nexport class CustomChatBedrockConverse extends ChatBedrockConverse {\n constructor(fields?: ChatBedrockConverseInput) {\n super(fields);\n }\n\n static lc_name(): string {\n return 'IllumaBedrockConverse';\n }\n\n /**\n * Override _streamResponseChunks to strip contentBlockIndex from response_metadata\n * This prevents LangChain's merge conflicts when the same index is used for\n * different content types (text vs tool calls)\n */\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const baseStream = super._streamResponseChunks(\n messages,\n options,\n runManager\n );\n\n for await (const chunk of baseStream) {\n // Only process if we have response_metadata\n if (\n chunk.message instanceof AIMessageChunk &&\n (chunk.message as Partial<AIMessageChunk>).response_metadata &&\n typeof chunk.message.response_metadata === 'object'\n ) {\n // Check if contentBlockIndex exists anywhere in response_metadata (top level or nested)\n const hasContentBlockIndex = this.hasContentBlockIndex(\n chunk.message.response_metadata\n );\n\n if (hasContentBlockIndex) {\n const cleanedMetadata = this.removeContentBlockIndex(\n chunk.message.response_metadata\n ) as Record<string, unknown>;\n\n yield new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...chunk.message,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n continue;\n }\n }\n\n yield chunk;\n }\n }\n\n /**\n * Check if contentBlockIndex exists at any level in the object\n */\n private hasContentBlockIndex(obj: unknown): boolean {\n if (obj === null || obj === undefined || typeof obj !== 'object') {\n return false;\n }\n\n if ('contentBlockIndex' in obj) {\n return true;\n }\n\n for (const value of Object.values(obj)) {\n if (typeof value === 'object' && value !== null) {\n if (this.hasContentBlockIndex(value)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Recursively remove contentBlockIndex from all levels of an object\n */\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","messages","AIMessageChunk","ChatGenerationChunk"],"mappings":";;;;;;AAAA;;;;;;;;;;;AAWG;AASG,MAAO,yBAA0B,SAAQA,uBAAmB,CAAA;AAChE,IAAA,WAAA,CAAY,MAAiC,EAAA;QAC3C,KAAK,CAAC,MAAM,CAAC;;AAGf,IAAA,OAAO,OAAO,GAAA;AACZ,QAAA,OAAO,uBAAuB;;AAGhC;;;;AAIG;IACH,OAAO,qBAAqB,CAC1BC,UAAuB,EACvB,OAAkC,EAClC,UAAqC,EAAA;AAErC,QAAA,MAAM,UAAU,GAAG,KAAK,CAAC,qBAAqB,CAC5CA,UAAQ,EACR,OAAO,EACP,UAAU,CACX;AAED,QAAA,WAAW,MAAM,KAAK,IAAI,UAAU,EAAE;;AAEpC,YAAA,IACE,KAAK,CAAC,OAAO,YAAYC,uBAAc;gBACtC,KAAK,CAAC,OAAmC,CAAC,iBAAiB;gBAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,iBAAiB,KAAK,QAAQ,EACnD;;AAEA,gBAAA,MAAM,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CACpD,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAChC;gBAED,IAAI,oBAAoB,EAAE;AACxB,oBAAA,MAAM,eAAe,GAAG,IAAI,CAAC,uBAAuB,CAClD,KAAK,CAAC,OAAO,CAAC,iBAAiB,CACL;oBAE5B,MAAM,IAAIC,2BAAmB,CAAC;wBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,OAAO,EAAE,IAAID,uBAAc,CAAC;4BAC1B,GAAG,KAAK,CAAC,OAAO;AAChB,4BAAA,iBAAiB,EAAE,eAAe;yBACnC,CAAC;wBACF,cAAc,EAAE,KAAK,CAAC,cAAc;AACrC,qBAAA,CAAC;oBACF;;;AAIJ,YAAA,MAAM,KAAK;;;AAIf;;AAEG;AACK,IAAA,oBAAoB,CAAC,GAAY,EAAA;AACvC,QAAA,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAChE,YAAA,OAAO,KAAK;;AAGd,QAAA,IAAI,mBAAmB,IAAI,GAAG,EAAE;AAC9B,YAAA,OAAO,IAAI;;QAGb,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;AAC/C,gBAAA,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE;AACpC,oBAAA,OAAO,IAAI;;;;AAKjB,QAAA,OAAO,KAAK;;AAGd;;AAEG;AACK,IAAA,uBAAuB,CAAC,GAAY,EAAA;QAC1C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE;AACrC,YAAA,OAAO,GAAG;;AAGZ,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACtB,YAAA,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;;AAG9D,QAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;YAC3B,MAAM,OAAO,GAA4B,EAAE;AAC3C,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AAC9C,gBAAA,IAAI,GAAG,KAAK,mBAAmB,EAAE;oBAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC;;;AAGtD,YAAA,OAAO,OAAO;;AAGhB,QAAA,OAAO,GAAG;;AAEb;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes contentBlockIndex conflicts\n * and adds prompt caching support for Bedrock Converse API.\n *\n * Bedrock sends the same contentBlockIndex for both text and tool_use content blocks,\n * causing LangChain's merge logic to fail with \"field[contentBlockIndex] already exists\"\n * errors. This wrapper simply strips contentBlockIndex from response_metadata to avoid\n * the conflict.\n *\n * The contentBlockIndex field is only used internally by Bedrock's streaming protocol\n * and isn't needed by application logic - the index field on tool_call_chunks serves\n * the purpose of tracking tool call ordering.\n *\n * PROMPT CACHING:\n * When promptCache: true is set, this wrapper adds cachePoint markers to the tools array\n * to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be\n * cached and reused across requests, reducing latency and costs.\n *\n * CACHE TOKEN EXTRACTION:\n * LangChain AWS doesn't extract cacheReadInputTokens/cacheWriteInputTokens from Bedrock's\n * response. This wrapper adds input_token_details to usage_metadata with cache information.\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\n\n/** Extended input type with promptCache option */\nexport interface CustomChatBedrockConverseInput extends ChatBedrockConverseInput {\n promptCache?: boolean;\n}\n\nexport class CustomChatBedrockConverse extends ChatBedrockConverse {\n promptCache: boolean;\n\n constructor(fields?: CustomChatBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache ?? false;\n }\n\n static lc_name(): string {\n return 'LibreChatBedrockConverse';\n }\n\n /**\n * Override invocationParams to add cachePoint to tools when promptCache is enabled.\n * This enables Bedrock prompt caching for tool definitions.\n * \n * STRATEGY: Separate cachePoints for core tools and MCP tools\n * - Core tools (web_search, execute_code, etc.) are stable → cache first\n * - MCP tools (have '_mcp_' in name) are dynamic → cache separately after\n * - This allows core tools to stay cached when MCP selection changes\n * \n * NOTE: Only Claude models support cachePoint - Nova and other models will reject it.\n */\n invocationParams(\n options?: this['ParsedCallOptions']\n ): ReturnType<ChatBedrockConverse['invocationParams']> {\n const params = super.invocationParams(options);\n\n // Add cachePoint to tools array if promptCache is enabled and tools exist\n // Only Claude models support cachePoint - check model name\n const modelId = this.model?.toLowerCase() ?? '';\n const isClaudeModel = modelId.includes('claude') || modelId.includes('anthropic');\n\n if (\n this.promptCache &&\n isClaudeModel &&\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools) &&\n params.toolConfig.tools.length > 0\n ) {\n // Separate core tools from MCP tools\n // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')\n const coreTools: typeof params.toolConfig.tools = [];\n const mcpTools: typeof params.toolConfig.tools = [];\n const coreToolNames: string[] = [];\n const mcpToolNames: string[] = [];\n \n for (const tool of params.toolConfig.tools) {\n // Check if tool has a name property with '_mcp_' pattern\n const toolName = (tool as { toolSpec?: { name?: string } })?.toolSpec?.name ?? '';\n if (toolName.includes('_mcp_')) {\n mcpTools.push(tool);\n mcpToolNames.push(toolName);\n } else {\n coreTools.push(tool);\n coreToolNames.push(toolName);\n }\n }\n\n // Always log cache structure (INFO level for tracking)\n console.log(`[Cache] 🔧 Tools | Core: [${coreToolNames.join(', ')}] (${coreTools.length}) | MCP: [${mcpToolNames.join(', ')}] (${mcpTools.length})`);\n\n // Build tools array with strategic cachePoints:\n // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]\n const toolsWithCache: typeof params.toolConfig.tools = [];\n let cachePointCount = 0;\n \n // Add core tools with cachePoint (if any)\n if (coreTools.length > 0) {\n toolsWithCache.push(...coreTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n cachePointCount++;\n }\n \n // Add MCP tools with their own cachePoint (if any)\n if (mcpTools.length > 0) {\n toolsWithCache.push(...mcpTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n cachePointCount++;\n }\n \n // If no tools at all (shouldn't happen but safety check)\n if (toolsWithCache.length === 0) {\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n cachePointCount++;\n }\n \n console.log(`[Cache] 📍 Tool cachePoints: ${cachePointCount} | Order: [${coreToolNames.length > 0 ? 'CoreTools→CP' : ''}${mcpToolNames.length > 0 ? '→MCPTools→CP' : ''}]`);\n \n params.toolConfig.tools = toolsWithCache;\n }\n\n return params;\n }\n\n /**\n * Override _streamResponseChunks to:\n * 1. Strip contentBlockIndex from response_metadata to prevent merge conflicts\n * 2. Extract cacheReadInputTokens/cacheWriteInputTokens and add to usage_metadata\n */\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const baseStream = super._streamResponseChunks(\n messages,\n options,\n runManager\n );\n\n for await (const chunk of baseStream) {\n // Only process if we have response_metadata\n if (\n chunk.message instanceof AIMessageChunk &&\n (chunk.message as Partial<AIMessageChunk>).response_metadata &&\n typeof chunk.message.response_metadata === 'object'\n ) {\n const responseMetadata = chunk.message.response_metadata as Record<string, unknown>;\n let needsModification = false;\n let cleanedMetadata = responseMetadata;\n\n // Check if contentBlockIndex exists anywhere in response_metadata\n const hasContentBlockIndex = this.hasContentBlockIndex(responseMetadata);\n if (hasContentBlockIndex) {\n cleanedMetadata = this.removeContentBlockIndex(responseMetadata) as Record<string, unknown>;\n needsModification = true;\n }\n\n // Extract cache tokens from metadata.usage (Bedrock streaming format)\n // The metadata chunk contains usage with cacheReadInputTokens/cacheWriteInputTokens\n const metadata = responseMetadata.metadata as Record<string, unknown> | undefined;\n const usage = (metadata?.usage ?? responseMetadata.usage) as Record<string, unknown> | undefined;\n \n let enhancedUsageMetadata: UsageMetadata | undefined = chunk.message.usage_metadata;\n \n if (usage) {\n const cacheRead = (usage.cacheReadInputTokens as number) ?? 0;\n const cacheWrite = (usage.cacheWriteInputTokens as number) ?? 0;\n const inputTokens = (usage.inputTokens as number) ?? 0;\n const outputTokens = (usage.outputTokens as number) ?? 0;\n \n if (cacheRead > 0 || cacheWrite > 0) {\n // Always log cache results for tracking\n const cacheStatus = cacheRead > 0 && cacheWrite === 0 ? '✅ HIT' : \n cacheWrite > 0 && cacheRead === 0 ? '📝 WRITE' :\n cacheRead > 0 && cacheWrite > 0 ? '🔄 PARTIAL' : '❌ MISS';\n console.log(`[Cache] ${cacheStatus} | read=${cacheRead} | write=${cacheWrite} | input=${inputTokens} | output=${outputTokens}`);\n \n needsModification = true;\n enhancedUsageMetadata = {\n input_tokens: chunk.message.usage_metadata?.input_tokens ?? inputTokens,\n output_tokens: chunk.message.usage_metadata?.output_tokens ?? outputTokens,\n total_tokens: chunk.message.usage_metadata?.total_tokens ?? (usage.totalTokens as number) ?? 0,\n input_token_details: {\n cache_read: cacheRead,\n cache_creation: cacheWrite,\n },\n };\n }\n }\n\n if (needsModification) {\n yield new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...chunk.message,\n response_metadata: cleanedMetadata,\n usage_metadata: enhancedUsageMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n continue;\n }\n }\n\n yield chunk;\n }\n }\n\n /**\n * Check if contentBlockIndex exists at any level in the object\n */\n private hasContentBlockIndex(obj: unknown): boolean {\n if (obj === null || obj === undefined || typeof obj !== 'object') {\n return false;\n }\n\n if ('contentBlockIndex' in obj) {\n return true;\n }\n\n for (const value of Object.values(obj)) {\n if (typeof value === 'object' && value !== null) {\n if (this.hasContentBlockIndex(value)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Recursively remove contentBlockIndex from all levels of an object\n */\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","messages","AIMessageChunk","ChatGenerationChunk"],"mappings":"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"}
|
|
@@ -83,7 +83,7 @@ class CustomChatGoogleGenerativeAI extends googleGenai.ChatGoogleGenerativeAI {
|
|
|
83
83
|
this.streamUsage = fields.streamUsage ?? this.streamUsage;
|
|
84
84
|
}
|
|
85
85
|
static lc_name() {
|
|
86
|
-
return '
|
|
86
|
+
return 'LibreChatGoogleGenerativeAI';
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
89
|
* Helper function to convert Gemini API usage metadata to LangChain format
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/llm/google/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport { GoogleGenerativeAI as GenerativeAI } from '@google/generative-ai';\nimport type {\n GenerateContentRequest,\n SafetySetting,\n} from '@google/generative-ai';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport type { GeminiGenerationConfig } from '@langchain/google-common';\nimport type { GeminiApiUsageMetadata, InputTokenDetails } from './types';\nimport type { GoogleClientOptions } from '@/types';\nimport {\n convertResponseContentToChatGenerationChunk,\n convertBaseMessagesToContent,\n mapGenerateContentResultToChatResult,\n} from './utils/common';\n\nexport class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {\n thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];\n\n /**\n * Override to add gemini-3 model support for multimodal and function calling thought signatures\n */\n get _isMultimodalModel(): boolean {\n return (\n this.model.startsWith('gemini-1.5') ||\n this.model.startsWith('gemini-2') ||\n (this.model.startsWith('gemma-3-') &&\n !this.model.startsWith('gemma-3-1b')) ||\n this.model.startsWith('gemini-3')\n );\n }\n\n constructor(fields: GoogleClientOptions) {\n super(fields);\n\n this.model = fields.model.replace(/^models\\//, '');\n\n this.maxOutputTokens = fields.maxOutputTokens ?? this.maxOutputTokens;\n\n if (this.maxOutputTokens != null && this.maxOutputTokens < 0) {\n throw new Error('`maxOutputTokens` must be a positive integer');\n }\n\n this.temperature = fields.temperature ?? this.temperature;\n if (\n this.temperature != null &&\n (this.temperature < 0 || this.temperature > 2)\n ) {\n throw new Error('`temperature` must be in the range of [0.0,2.0]');\n }\n\n this.topP = fields.topP ?? this.topP;\n if (this.topP != null && this.topP < 0) {\n throw new Error('`topP` must be a positive integer');\n }\n\n if (this.topP != null && this.topP > 1) {\n throw new Error('`topP` must be below 1.');\n }\n\n this.topK = fields.topK ?? this.topK;\n if (this.topK != null && this.topK < 0) {\n throw new Error('`topK` must be a positive integer');\n }\n\n this.stopSequences = fields.stopSequences ?? this.stopSequences;\n\n this.apiKey = fields.apiKey ?? getEnvironmentVariable('GOOGLE_API_KEY');\n if (this.apiKey == null || this.apiKey === '') {\n throw new Error(\n 'Please set an API key for Google GenerativeAI ' +\n 'in the environment variable GOOGLE_API_KEY ' +\n 'or in the `apiKey` field of the ' +\n 'ChatGoogleGenerativeAI constructor'\n );\n }\n\n this.safetySettings = fields.safetySettings ?? this.safetySettings;\n if (this.safetySettings && this.safetySettings.length > 0) {\n const safetySettingsSet = new Set(\n this.safetySettings.map((s) => s.category)\n );\n if (safetySettingsSet.size !== this.safetySettings.length) {\n throw new Error(\n 'The categories in `safetySettings` array must be unique'\n );\n }\n }\n\n this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;\n\n this.streaming = fields.streaming ?? this.streaming;\n this.json = fields.json;\n\n // @ts-ignore - Accessing private property from parent class\n this.client = new GenerativeAI(this.apiKey).getGenerativeModel(\n {\n model: this.model,\n safetySettings: this.safetySettings as SafetySetting[],\n generationConfig: {\n stopSequences: this.stopSequences,\n maxOutputTokens: this.maxOutputTokens,\n temperature: this.temperature,\n topP: this.topP,\n topK: this.topK,\n ...(this.json != null\n ? { responseMimeType: 'application/json' }\n : {}),\n },\n },\n {\n apiVersion: fields.apiVersion,\n baseUrl: fields.baseUrl,\n customHeaders: fields.customHeaders,\n }\n );\n this.streamUsage = fields.streamUsage ?? this.streamUsage;\n }\n\n static lc_name(): 'IllumaGoogleGenerativeAI' {\n return 'IllumaGoogleGenerativeAI';\n }\n\n /**\n * Helper function to convert Gemini API usage metadata to LangChain format\n * Includes support for cached tokens and tier-based tracking for gemini-3-pro-preview\n */\n private _convertToUsageMetadata(\n usageMetadata: GeminiApiUsageMetadata | undefined,\n model: string\n ): UsageMetadata | undefined {\n if (!usageMetadata) {\n return undefined;\n }\n\n const output: UsageMetadata = {\n input_tokens: usageMetadata.promptTokenCount ?? 0,\n output_tokens:\n (usageMetadata.candidatesTokenCount ?? 0) +\n (usageMetadata.thoughtsTokenCount ?? 0),\n total_tokens: usageMetadata.totalTokenCount ?? 0,\n };\n\n if (usageMetadata.cachedContentTokenCount) {\n output.input_token_details ??= {};\n output.input_token_details.cache_read =\n usageMetadata.cachedContentTokenCount;\n }\n\n // gemini-3-pro-preview has bracket based tracking of tokens per request\n if (model === 'gemini-3-pro-preview') {\n const over200k = Math.max(\n 0,\n (usageMetadata.promptTokenCount ?? 0) - 200000\n );\n const cachedOver200k = Math.max(\n 0,\n (usageMetadata.cachedContentTokenCount ?? 0) - 200000\n );\n if (over200k) {\n output.input_token_details = {\n ...output.input_token_details,\n over_200k: over200k,\n } as InputTokenDetails;\n }\n if (cachedOver200k) {\n output.input_token_details = {\n ...output.input_token_details,\n cache_read_over_200k: cachedOver200k,\n } as InputTokenDetails;\n }\n }\n\n return output;\n }\n\n invocationParams(\n options?: this['ParsedCallOptions']\n ): Omit<GenerateContentRequest, 'contents'> {\n const params = super.invocationParams(options);\n if (this.thinkingConfig) {\n /** @ts-ignore */\n this.client.generationConfig = {\n /** @ts-ignore */\n ...this.client.generationConfig,\n /** @ts-ignore */\n thinkingConfig: this.thinkingConfig,\n };\n }\n return params;\n }\n\n async _generate(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): Promise<import('@langchain/core/outputs').ChatResult> {\n const prompt = convertBaseMessagesToContent(\n messages,\n this._isMultimodalModel,\n this.useSystemInstruction,\n this.model\n );\n let actualPrompt = prompt;\n if (prompt?.[0].role === 'system') {\n const [systemInstruction] = prompt;\n /** @ts-ignore */\n this.client.systemInstruction = systemInstruction;\n actualPrompt = prompt.slice(1);\n }\n const parameters = this.invocationParams(options);\n const request = {\n ...parameters,\n contents: actualPrompt,\n };\n\n const res = await this.caller.callWithOptions(\n { signal: options.signal },\n async () =>\n /** @ts-ignore */\n this.client.generateContent(request)\n );\n\n const response = res.response;\n const usageMetadata = this._convertToUsageMetadata(\n /** @ts-ignore */\n response.usageMetadata,\n this.model\n );\n\n /** @ts-ignore */\n const generationResult = mapGenerateContentResultToChatResult(response, {\n usageMetadata,\n });\n\n await runManager?.handleLLMNewToken(\n generationResult.generations[0].text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n undefined\n );\n return generationResult;\n }\n\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const prompt = convertBaseMessagesToContent(\n messages,\n this._isMultimodalModel,\n this.useSystemInstruction,\n this.model\n );\n let actualPrompt = prompt;\n if (prompt?.[0].role === 'system') {\n const [systemInstruction] = prompt;\n /** @ts-ignore */\n this.client.systemInstruction = systemInstruction;\n actualPrompt = prompt.slice(1);\n }\n const parameters = this.invocationParams(options);\n const request = {\n ...parameters,\n contents: actualPrompt,\n };\n const stream = await this.caller.callWithOptions(\n { signal: options.signal },\n async () => {\n /** @ts-ignore */\n const { stream } = await this.client.generateContentStream(request);\n return stream;\n }\n );\n\n let index = 0;\n let lastUsageMetadata: UsageMetadata | undefined;\n for await (const response of stream) {\n if (\n 'usageMetadata' in response &&\n this.streamUsage !== false &&\n options.streamUsage !== false\n ) {\n lastUsageMetadata = this._convertToUsageMetadata(\n response.usageMetadata as GeminiApiUsageMetadata | undefined,\n this.model\n );\n }\n\n const chunk = convertResponseContentToChatGenerationChunk(response, {\n usageMetadata: undefined,\n index,\n });\n index += 1;\n if (!chunk) {\n continue;\n }\n\n yield chunk;\n await runManager?.handleLLMNewToken(\n chunk.text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk }\n );\n }\n\n if (lastUsageMetadata) {\n const finalChunk = new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n usage_metadata: lastUsageMetadata,\n }),\n });\n yield finalChunk;\n await runManager?.handleLLMNewToken(\n finalChunk.text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: finalChunk }\n );\n }\n }\n}\n"],"names":["ChatGoogleGenerativeAI","getEnvironmentVariable","GenerativeAI","convertBaseMessagesToContent","mapGenerateContentResultToChatResult","messages","convertResponseContentToChatGenerationChunk","ChatGenerationChunk","AIMessageChunk"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/llm/google/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport { ChatGenerationChunk } from '@langchain/core/outputs';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport { GoogleGenerativeAI as GenerativeAI } from '@google/generative-ai';\nimport type {\n GenerateContentRequest,\n SafetySetting,\n} from '@google/generative-ai';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport type { GeminiGenerationConfig } from '@langchain/google-common';\nimport type { GeminiApiUsageMetadata, InputTokenDetails } from './types';\nimport type { GoogleClientOptions } from '@/types';\nimport {\n convertResponseContentToChatGenerationChunk,\n convertBaseMessagesToContent,\n mapGenerateContentResultToChatResult,\n} from './utils/common';\n\nexport class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {\n thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];\n\n /**\n * Override to add gemini-3 model support for multimodal and function calling thought signatures\n */\n get _isMultimodalModel(): boolean {\n return (\n this.model.startsWith('gemini-1.5') ||\n this.model.startsWith('gemini-2') ||\n (this.model.startsWith('gemma-3-') &&\n !this.model.startsWith('gemma-3-1b')) ||\n this.model.startsWith('gemini-3')\n );\n }\n\n constructor(fields: GoogleClientOptions) {\n super(fields);\n\n this.model = fields.model.replace(/^models\\//, '');\n\n this.maxOutputTokens = fields.maxOutputTokens ?? this.maxOutputTokens;\n\n if (this.maxOutputTokens != null && this.maxOutputTokens < 0) {\n throw new Error('`maxOutputTokens` must be a positive integer');\n }\n\n this.temperature = fields.temperature ?? this.temperature;\n if (\n this.temperature != null &&\n (this.temperature < 0 || this.temperature > 2)\n ) {\n throw new Error('`temperature` must be in the range of [0.0,2.0]');\n }\n\n this.topP = fields.topP ?? this.topP;\n if (this.topP != null && this.topP < 0) {\n throw new Error('`topP` must be a positive integer');\n }\n\n if (this.topP != null && this.topP > 1) {\n throw new Error('`topP` must be below 1.');\n }\n\n this.topK = fields.topK ?? this.topK;\n if (this.topK != null && this.topK < 0) {\n throw new Error('`topK` must be a positive integer');\n }\n\n this.stopSequences = fields.stopSequences ?? this.stopSequences;\n\n this.apiKey = fields.apiKey ?? getEnvironmentVariable('GOOGLE_API_KEY');\n if (this.apiKey == null || this.apiKey === '') {\n throw new Error(\n 'Please set an API key for Google GenerativeAI ' +\n 'in the environment variable GOOGLE_API_KEY ' +\n 'or in the `apiKey` field of the ' +\n 'ChatGoogleGenerativeAI constructor'\n );\n }\n\n this.safetySettings = fields.safetySettings ?? this.safetySettings;\n if (this.safetySettings && this.safetySettings.length > 0) {\n const safetySettingsSet = new Set(\n this.safetySettings.map((s) => s.category)\n );\n if (safetySettingsSet.size !== this.safetySettings.length) {\n throw new Error(\n 'The categories in `safetySettings` array must be unique'\n );\n }\n }\n\n this.thinkingConfig = fields.thinkingConfig ?? this.thinkingConfig;\n\n this.streaming = fields.streaming ?? this.streaming;\n this.json = fields.json;\n\n // @ts-ignore - Accessing private property from parent class\n this.client = new GenerativeAI(this.apiKey).getGenerativeModel(\n {\n model: this.model,\n safetySettings: this.safetySettings as SafetySetting[],\n generationConfig: {\n stopSequences: this.stopSequences,\n maxOutputTokens: this.maxOutputTokens,\n temperature: this.temperature,\n topP: this.topP,\n topK: this.topK,\n ...(this.json != null\n ? { responseMimeType: 'application/json' }\n : {}),\n },\n },\n {\n apiVersion: fields.apiVersion,\n baseUrl: fields.baseUrl,\n customHeaders: fields.customHeaders,\n }\n );\n this.streamUsage = fields.streamUsage ?? this.streamUsage;\n }\n\n static lc_name(): 'LibreChatGoogleGenerativeAI' {\n return 'LibreChatGoogleGenerativeAI';\n }\n\n /**\n * Helper function to convert Gemini API usage metadata to LangChain format\n * Includes support for cached tokens and tier-based tracking for gemini-3-pro-preview\n */\n private _convertToUsageMetadata(\n usageMetadata: GeminiApiUsageMetadata | undefined,\n model: string\n ): UsageMetadata | undefined {\n if (!usageMetadata) {\n return undefined;\n }\n\n const output: UsageMetadata = {\n input_tokens: usageMetadata.promptTokenCount ?? 0,\n output_tokens:\n (usageMetadata.candidatesTokenCount ?? 0) +\n (usageMetadata.thoughtsTokenCount ?? 0),\n total_tokens: usageMetadata.totalTokenCount ?? 0,\n };\n\n if (usageMetadata.cachedContentTokenCount) {\n output.input_token_details ??= {};\n output.input_token_details.cache_read =\n usageMetadata.cachedContentTokenCount;\n }\n\n // gemini-3-pro-preview has bracket based tracking of tokens per request\n if (model === 'gemini-3-pro-preview') {\n const over200k = Math.max(\n 0,\n (usageMetadata.promptTokenCount ?? 0) - 200000\n );\n const cachedOver200k = Math.max(\n 0,\n (usageMetadata.cachedContentTokenCount ?? 0) - 200000\n );\n if (over200k) {\n output.input_token_details = {\n ...output.input_token_details,\n over_200k: over200k,\n } as InputTokenDetails;\n }\n if (cachedOver200k) {\n output.input_token_details = {\n ...output.input_token_details,\n cache_read_over_200k: cachedOver200k,\n } as InputTokenDetails;\n }\n }\n\n return output;\n }\n\n invocationParams(\n options?: this['ParsedCallOptions']\n ): Omit<GenerateContentRequest, 'contents'> {\n const params = super.invocationParams(options);\n if (this.thinkingConfig) {\n /** @ts-ignore */\n this.client.generationConfig = {\n /** @ts-ignore */\n ...this.client.generationConfig,\n /** @ts-ignore */\n thinkingConfig: this.thinkingConfig,\n };\n }\n return params;\n }\n\n async _generate(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): Promise<import('@langchain/core/outputs').ChatResult> {\n const prompt = convertBaseMessagesToContent(\n messages,\n this._isMultimodalModel,\n this.useSystemInstruction,\n this.model\n );\n let actualPrompt = prompt;\n if (prompt?.[0].role === 'system') {\n const [systemInstruction] = prompt;\n /** @ts-ignore */\n this.client.systemInstruction = systemInstruction;\n actualPrompt = prompt.slice(1);\n }\n const parameters = this.invocationParams(options);\n const request = {\n ...parameters,\n contents: actualPrompt,\n };\n\n const res = await this.caller.callWithOptions(\n { signal: options.signal },\n async () =>\n /** @ts-ignore */\n this.client.generateContent(request)\n );\n\n const response = res.response;\n const usageMetadata = this._convertToUsageMetadata(\n /** @ts-ignore */\n response.usageMetadata,\n this.model\n );\n\n /** @ts-ignore */\n const generationResult = mapGenerateContentResultToChatResult(response, {\n usageMetadata,\n });\n\n await runManager?.handleLLMNewToken(\n generationResult.generations[0].text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n undefined\n );\n return generationResult;\n }\n\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const prompt = convertBaseMessagesToContent(\n messages,\n this._isMultimodalModel,\n this.useSystemInstruction,\n this.model\n );\n let actualPrompt = prompt;\n if (prompt?.[0].role === 'system') {\n const [systemInstruction] = prompt;\n /** @ts-ignore */\n this.client.systemInstruction = systemInstruction;\n actualPrompt = prompt.slice(1);\n }\n const parameters = this.invocationParams(options);\n const request = {\n ...parameters,\n contents: actualPrompt,\n };\n const stream = await this.caller.callWithOptions(\n { signal: options.signal },\n async () => {\n /** @ts-ignore */\n const { stream } = await this.client.generateContentStream(request);\n return stream;\n }\n );\n\n let index = 0;\n let lastUsageMetadata: UsageMetadata | undefined;\n for await (const response of stream) {\n if (\n 'usageMetadata' in response &&\n this.streamUsage !== false &&\n options.streamUsage !== false\n ) {\n lastUsageMetadata = this._convertToUsageMetadata(\n response.usageMetadata as GeminiApiUsageMetadata | undefined,\n this.model\n );\n }\n\n const chunk = convertResponseContentToChatGenerationChunk(response, {\n usageMetadata: undefined,\n index,\n });\n index += 1;\n if (!chunk) {\n continue;\n }\n\n yield chunk;\n await runManager?.handleLLMNewToken(\n chunk.text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk }\n );\n }\n\n if (lastUsageMetadata) {\n const finalChunk = new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n usage_metadata: lastUsageMetadata,\n }),\n });\n yield finalChunk;\n await runManager?.handleLLMNewToken(\n finalChunk.text || '',\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: finalChunk }\n );\n }\n }\n}\n"],"names":["ChatGoogleGenerativeAI","getEnvironmentVariable","GenerativeAI","convertBaseMessagesToContent","mapGenerateContentResultToChatResult","messages","convertResponseContentToChatGenerationChunk","ChatGenerationChunk","AIMessageChunk"],"mappings":"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"}
|
|
@@ -120,7 +120,7 @@ class ChatOpenAI extends openai.ChatOpenAI {
|
|
|
120
120
|
return this.client;
|
|
121
121
|
}
|
|
122
122
|
static lc_name() {
|
|
123
|
-
return '
|
|
123
|
+
return 'LibreChatOpenAI';
|
|
124
124
|
}
|
|
125
125
|
_getClientOptions(options) {
|
|
126
126
|
if (!this.client) {
|
|
@@ -317,7 +317,7 @@ class AzureChatOpenAI extends openai.AzureChatOpenAI {
|
|
|
317
317
|
return this.client;
|
|
318
318
|
}
|
|
319
319
|
static lc_name() {
|
|
320
|
-
return '
|
|
320
|
+
return 'LibreChatAzureOpenAI';
|
|
321
321
|
}
|
|
322
322
|
/**
|
|
323
323
|
* Returns backwards compatible reasoning parameters from constructor params and call options
|
|
@@ -373,8 +373,8 @@ class AzureChatOpenAI extends openai.AzureChatOpenAI {
|
|
|
373
373
|
params.defaultHeaders = {
|
|
374
374
|
...params.defaultHeaders,
|
|
375
375
|
'User-Agent': defaultHeaders['User-Agent'] != null
|
|
376
|
-
? `${defaultHeaders['User-Agent']}:
|
|
377
|
-
: '
|
|
376
|
+
? `${defaultHeaders['User-Agent']}: librechat-azure-openai-v2`
|
|
377
|
+
: 'librechat-azure-openai-v2',
|
|
378
378
|
};
|
|
379
379
|
this.client = new CustomAzureOpenAIClient({
|
|
380
380
|
apiVersion: this.azureOpenAIApiVersion,
|
|
@@ -425,7 +425,7 @@ class ChatDeepSeek extends deepseek.ChatDeepSeek {
|
|
|
425
425
|
return this.client;
|
|
426
426
|
}
|
|
427
427
|
static lc_name() {
|
|
428
|
-
return '
|
|
428
|
+
return 'LibreChatDeepSeek';
|
|
429
429
|
}
|
|
430
430
|
_getClientOptions(options) {
|
|
431
431
|
if (!this.client) {
|
|
@@ -450,6 +450,108 @@ class ChatDeepSeek extends deepseek.ChatDeepSeek {
|
|
|
450
450
|
};
|
|
451
451
|
return requestOptions;
|
|
452
452
|
}
|
|
453
|
+
async *_streamResponseChunks(messages$1, options, runManager) {
|
|
454
|
+
const messagesMapped = index._convertMessagesToOpenAIParams(messages$1, this.model, {
|
|
455
|
+
includeReasoningContent: true,
|
|
456
|
+
});
|
|
457
|
+
const params = {
|
|
458
|
+
...this.invocationParams(options, {
|
|
459
|
+
streaming: true,
|
|
460
|
+
}),
|
|
461
|
+
messages: messagesMapped,
|
|
462
|
+
stream: true,
|
|
463
|
+
};
|
|
464
|
+
let defaultRole;
|
|
465
|
+
const streamIterable = await this.completionWithRetry(params, options);
|
|
466
|
+
let usage;
|
|
467
|
+
for await (const data of streamIterable) {
|
|
468
|
+
const choice = data.choices[0];
|
|
469
|
+
if (data.usage) {
|
|
470
|
+
usage = data.usage;
|
|
471
|
+
}
|
|
472
|
+
if (!choice) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const { delta } = choice;
|
|
476
|
+
if (!delta) {
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
const chunk = this._convertOpenAIDeltaToBaseMessageChunk(delta, data, defaultRole);
|
|
480
|
+
if ('reasoning_content' in delta) {
|
|
481
|
+
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
482
|
+
}
|
|
483
|
+
defaultRole = delta.role ?? defaultRole;
|
|
484
|
+
const newTokenIndices = {
|
|
485
|
+
prompt: options.promptIndex ?? 0,
|
|
486
|
+
completion: choice.index ?? 0,
|
|
487
|
+
};
|
|
488
|
+
if (typeof chunk.content !== 'string') {
|
|
489
|
+
// eslint-disable-next-line no-console
|
|
490
|
+
console.log('[WARNING]: Received non-string content from OpenAI. This is currently not supported.');
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
494
|
+
const generationInfo = { ...newTokenIndices };
|
|
495
|
+
if (choice.finish_reason != null) {
|
|
496
|
+
generationInfo.finish_reason = choice.finish_reason;
|
|
497
|
+
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
498
|
+
generationInfo.model_name = data.model;
|
|
499
|
+
generationInfo.service_tier = data.service_tier;
|
|
500
|
+
}
|
|
501
|
+
if (this.logprobs == true) {
|
|
502
|
+
generationInfo.logprobs = choice.logprobs;
|
|
503
|
+
}
|
|
504
|
+
const generationChunk = new outputs.ChatGenerationChunk({
|
|
505
|
+
message: chunk,
|
|
506
|
+
text: chunk.content,
|
|
507
|
+
generationInfo,
|
|
508
|
+
});
|
|
509
|
+
yield generationChunk;
|
|
510
|
+
await runManager?.handleLLMNewToken(generationChunk.text || '', newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
|
|
511
|
+
}
|
|
512
|
+
if (usage) {
|
|
513
|
+
const inputTokenDetails = {
|
|
514
|
+
...(usage.prompt_tokens_details?.audio_tokens != null && {
|
|
515
|
+
audio: usage.prompt_tokens_details.audio_tokens,
|
|
516
|
+
}),
|
|
517
|
+
...(usage.prompt_tokens_details?.cached_tokens != null && {
|
|
518
|
+
cache_read: usage.prompt_tokens_details.cached_tokens,
|
|
519
|
+
}),
|
|
520
|
+
};
|
|
521
|
+
const outputTokenDetails = {
|
|
522
|
+
...(usage.completion_tokens_details?.audio_tokens != null && {
|
|
523
|
+
audio: usage.completion_tokens_details.audio_tokens,
|
|
524
|
+
}),
|
|
525
|
+
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
526
|
+
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
527
|
+
}),
|
|
528
|
+
};
|
|
529
|
+
const generationChunk = new outputs.ChatGenerationChunk({
|
|
530
|
+
message: new messages.AIMessageChunk({
|
|
531
|
+
content: '',
|
|
532
|
+
response_metadata: {
|
|
533
|
+
usage: { ...usage },
|
|
534
|
+
},
|
|
535
|
+
usage_metadata: {
|
|
536
|
+
input_tokens: usage.prompt_tokens,
|
|
537
|
+
output_tokens: usage.completion_tokens,
|
|
538
|
+
total_tokens: usage.total_tokens,
|
|
539
|
+
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
540
|
+
input_token_details: inputTokenDetails,
|
|
541
|
+
}),
|
|
542
|
+
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
543
|
+
output_token_details: outputTokenDetails,
|
|
544
|
+
}),
|
|
545
|
+
},
|
|
546
|
+
}),
|
|
547
|
+
text: '',
|
|
548
|
+
});
|
|
549
|
+
yield generationChunk;
|
|
550
|
+
}
|
|
551
|
+
if (options.signal?.aborted === true) {
|
|
552
|
+
throw new Error('AbortError');
|
|
553
|
+
}
|
|
554
|
+
}
|
|
453
555
|
}
|
|
454
556
|
class ChatXAI extends xai.ChatXAI {
|
|
455
557
|
_lc_stream_delay;
|
|
@@ -468,7 +570,7 @@ class ChatXAI extends xai.ChatXAI {
|
|
|
468
570
|
}
|
|
469
571
|
}
|
|
470
572
|
static lc_name() {
|
|
471
|
-
return '
|
|
573
|
+
return 'LibreChatXAI';
|
|
472
574
|
}
|
|
473
575
|
get exposedClient() {
|
|
474
576
|
return this.client;
|