@librechat/agents 3.3.3 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/agents/AgentContext.cjs +2 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/constants.cjs +21 -0
- package/dist/cjs/common/constants.cjs.map +1 -1
- package/dist/cjs/events.cjs +10 -1
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +793 -111
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +3 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs +25 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs +12 -0
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +8 -0
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +38 -13
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +19 -7
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +331 -5
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +41 -5
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +25 -4
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +4 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/preempt.cjs +132 -0
- package/dist/cjs/llm/preempt.cjs.map +1 -0
- package/dist/cjs/main.cjs +36 -5
- package/dist/cjs/messages/alternation.cjs +92 -0
- package/dist/cjs/messages/alternation.cjs.map +1 -0
- package/dist/cjs/messages/cache.cjs +54 -33
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs +17 -43
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +315 -23
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +290 -60
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/handoffCue.cjs +63 -0
- package/dist/cjs/messages/handoffCue.cjs.map +1 -0
- package/dist/cjs/messages/index.cjs +4 -1
- package/dist/cjs/messages/injected.cjs +60 -0
- package/dist/cjs/messages/injected.cjs.map +1 -0
- package/dist/cjs/messages/prune.cjs +503 -127
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +80 -7
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/handlers.cjs +18 -9
- package/dist/cjs/session/handlers.cjs.map +1 -1
- package/dist/cjs/stream.cjs +35 -10
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +28 -14
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +56 -63
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/keenable-scraper.cjs +90 -0
- package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -0
- package/dist/cjs/tools/search/tool.cjs +9 -1
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/toolOutputReferences.cjs +6 -0
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +1 -1
- package/dist/cjs/utils/llm.cjs +1 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +307 -20
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/cjs/utils/toolContent.cjs +1514 -0
- package/dist/cjs/utils/toolContent.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +2 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/constants.mjs +19 -1
- package/dist/esm/common/constants.mjs.map +1 -1
- package/dist/esm/events.mjs +10 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +798 -116
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +3 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/hooks/HookRegistry.mjs +25 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/index.mjs +12 -1
- package/dist/esm/hooks/index.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -0
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +9 -1
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +38 -13
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +19 -7
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +332 -8
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +41 -5
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +25 -4
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +4 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/preempt.mjs +131 -0
- package/dist/esm/llm/preempt.mjs.map +1 -0
- package/dist/esm/main.mjs +14 -11
- package/dist/esm/messages/alternation.mjs +91 -0
- package/dist/esm/messages/alternation.mjs.map +1 -0
- package/dist/esm/messages/cache.mjs +55 -34
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs +17 -43
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +305 -24
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +290 -61
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/handoffCue.mjs +61 -0
- package/dist/esm/messages/handoffCue.mjs.map +1 -0
- package/dist/esm/messages/index.mjs +4 -1
- package/dist/esm/messages/injected.mjs +60 -0
- package/dist/esm/messages/injected.mjs.map +1 -0
- package/dist/esm/messages/prune.mjs +500 -128
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +80 -7
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/handlers.mjs +19 -10
- package/dist/esm/session/handlers.mjs.map +1 -1
- package/dist/esm/stream.mjs +34 -11
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +28 -14
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +56 -63
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/keenable-scraper.mjs +88 -0
- package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -0
- package/dist/esm/tools/search/tool.mjs +9 -1
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/toolOutputReferences.mjs +6 -0
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +1 -1
- package/dist/esm/utils/llm.mjs +1 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +307 -21
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/esm/utils/toolContent.mjs +1503 -0
- package/dist/esm/utils/toolContent.mjs.map +1 -0
- package/dist/types/common/constants.d.ts +18 -0
- package/dist/types/graphs/Graph.d.ts +139 -2
- package/dist/types/hooks/HookRegistry.d.ts +15 -0
- package/dist/types/hooks/index.d.ts +12 -1
- package/dist/types/hooks/types.d.ts +45 -6
- package/dist/types/index.d.ts +1 -1
- package/dist/types/llm/invoke.d.ts +34 -1
- package/dist/types/llm/openai/index.d.ts +4 -0
- package/dist/types/llm/openai/utils/index.d.ts +2 -0
- package/dist/types/llm/openrouter/index.d.ts +5 -0
- package/dist/types/llm/preempt.d.ts +40 -0
- package/dist/types/messages/alternation.d.ts +23 -0
- package/dist/types/messages/contextPruning.d.ts +2 -1
- package/dist/types/messages/core.d.ts +36 -0
- package/dist/types/messages/format.d.ts +6 -0
- package/dist/types/messages/handoffCue.d.ts +40 -0
- package/dist/types/messages/index.d.ts +3 -0
- package/dist/types/messages/injected.d.ts +3 -0
- package/dist/types/messages/prune.d.ts +16 -12
- package/dist/types/run.d.ts +7 -0
- package/dist/types/stream.d.ts +14 -0
- package/dist/types/tools/ToolNode.d.ts +0 -7
- package/dist/types/tools/search/keenable-scraper.d.ts +15 -0
- package/dist/types/tools/search/types.d.ts +31 -2
- package/dist/types/types/graph.d.ts +8 -1
- package/dist/types/types/run.d.ts +65 -0
- package/dist/types/types/stream.d.ts +1 -26
- package/dist/types/utils/tokens.d.ts +7 -0
- package/dist/types/utils/toolContent.d.ts +107 -0
- package/package.json +1 -1
- package/src/__tests__/stream.eagerEventExecution.test.ts +74 -0
- package/src/agents/AgentContext.ts +1 -0
- package/src/{splitStream.test.ts → aggregator.test.ts} +59 -666
- package/src/common/constants.ts +21 -0
- package/src/events.ts +15 -1
- package/src/graphs/Graph.ts +1261 -198
- package/src/graphs/MultiAgentGraph.ts +6 -1
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1139 -4
- package/src/graphs/__tests__/Graph.preemptSignal.test.ts +126 -0
- package/src/hooks/HookRegistry.ts +40 -0
- package/src/hooks/__tests__/preemptBoundary.test.ts +152 -0
- package/src/hooks/index.ts +16 -2
- package/src/hooks/types.ts +47 -3
- package/src/index.ts +1 -1
- package/src/langfuse.ts +26 -1
- package/src/llm/anthropic/utils/message_inputs.ts +158 -12
- package/src/llm/anthropic/utils/tool-id-normalization.test.ts +109 -0
- package/src/llm/bedrock/utils/message_inputs.test.ts +131 -1
- package/src/llm/bedrock/utils/message_inputs.ts +100 -24
- package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +15 -0
- package/src/llm/google/utils/common.test.ts +75 -9
- package/src/llm/google/utils/common.ts +34 -3
- package/src/llm/invoke.alternation.test.ts +87 -0
- package/src/llm/invoke.handoffCue.test.ts +112 -0
- package/src/llm/invoke.test.ts +488 -0
- package/src/llm/invoke.ts +611 -8
- package/src/llm/openai/index.ts +106 -6
- package/src/llm/openai/utils/index.ts +109 -53
- package/src/llm/openai/utils/messages.test.ts +330 -1
- package/src/llm/openrouter/index.ts +12 -2
- package/src/llm/openrouter/reasoning.test.ts +314 -0
- package/src/llm/preempt.test.ts +323 -0
- package/src/llm/preempt.ts +178 -0
- package/src/messages/__tests__/observationMasking.test.ts +93 -2
- package/src/messages/alternation.test.ts +212 -0
- package/src/messages/alternation.ts +112 -0
- package/src/messages/cache.tail.test.ts +193 -0
- package/src/messages/cache.test.ts +113 -0
- package/src/messages/cache.ts +92 -60
- package/src/messages/contextPruning.test.ts +184 -0
- package/src/messages/contextPruning.ts +49 -42
- package/src/messages/core.ts +653 -40
- package/src/messages/ensureThinkingBlock.test.ts +49 -1
- package/src/messages/foldToollessToolBlocks.test.ts +163 -5
- package/src/messages/format.ts +454 -91
- package/src/messages/formatAgentMessages.steer.test.ts +267 -0
- package/src/messages/formatAgentMessages.test.ts +604 -14
- package/src/messages/formatAgentMessages.tools.test.ts +103 -0
- package/src/messages/handoffCue.test.ts +96 -0
- package/src/messages/handoffCue.ts +78 -0
- package/src/messages/index.ts +3 -0
- package/src/messages/injected.test.ts +90 -0
- package/src/messages/injected.ts +74 -0
- package/src/messages/prune.ts +996 -183
- package/src/run.ts +91 -6
- package/src/scripts/preempt-probe.ts +330 -0
- package/src/scripts/preempt-scenarios.ts +388 -0
- package/src/session/handlers.ts +32 -12
- package/src/specs/handoffCue.test.ts +165 -0
- package/src/specs/langfuse-callbacks.test.ts +352 -2
- package/src/specs/preemptSeal.test.ts +309 -0
- package/src/specs/prune.test.ts +1083 -6
- package/src/specs/summarization-unit.test.ts +105 -0
- package/src/specs/tokens.test.ts +609 -32
- package/src/stream.dispatch.test.ts +63 -0
- package/src/stream.ts +59 -23
- package/src/summarization/__tests__/node.test.ts +77 -0
- package/src/summarization/node.ts +46 -18
- package/src/tools/ToolNode.ts +150 -99
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +148 -1
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +112 -3
- package/src/tools/__tests__/annotateMessagesForLLM.test.ts +32 -0
- package/src/tools/__tests__/directToolHooks.test.ts +255 -7
- package/src/tools/search/keenable-scraper.test.ts +153 -0
- package/src/tools/search/keenable-scraper.ts +137 -0
- package/src/tools/search/tool.ts +13 -2
- package/src/tools/search/types.ts +50 -3
- package/src/tools/toolOutputReferences.ts +6 -0
- package/src/types/graph.ts +12 -1
- package/src/types/run.ts +67 -0
- package/src/types/stream.ts +1 -42
- package/src/utils/llm.test.ts +18 -0
- package/src/utils/llm.ts +4 -1
- package/src/utils/tokens.ts +586 -31
- package/src/utils/toolContent.test.ts +1432 -0
- package/src/utils/toolContent.ts +2707 -0
- package/dist/cjs/splitStream.cjs +0 -151
- package/dist/cjs/splitStream.cjs.map +0 -1
- package/dist/esm/splitStream.mjs +0 -150
- package/dist/esm/splitStream.mjs.map +0 -1
- package/dist/types/mockStream.d.ts +0 -32
- package/dist/types/splitStream.d.ts +0 -37
- package/src/mockStream.ts +0 -99
- package/src/splitStream.ts +0 -234
package/src/llm/openai/index.ts
CHANGED
|
@@ -29,16 +29,28 @@ import type {
|
|
|
29
29
|
BaseMessageChunk,
|
|
30
30
|
UsageMetadata,
|
|
31
31
|
} from '@langchain/core/messages';
|
|
32
|
+
import type { ChatModelStreamEvent } from '@langchain/core/language_models/event';
|
|
32
33
|
import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
|
|
33
34
|
import type { ChatGeneration, ChatResult } from '@langchain/core/outputs';
|
|
34
35
|
import type { ChatXAIInput } from '@langchain/xai';
|
|
35
36
|
import type * as t from '@langchain/openai';
|
|
36
37
|
import type { SeenScalarMetadata } from './streamMetadata';
|
|
37
38
|
import type { HeaderValue, HeadersLike } from './types';
|
|
39
|
+
import type { PromptCacheTtl } from '@/messages/cache';
|
|
40
|
+
import {
|
|
41
|
+
buildAnthropicCacheControl,
|
|
42
|
+
resolvePromptCacheTtl,
|
|
43
|
+
stripAnthropicCacheControl,
|
|
44
|
+
stripBedrockCacheControl,
|
|
45
|
+
} from '@/messages/cache';
|
|
38
46
|
import {
|
|
39
47
|
STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY,
|
|
40
48
|
OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER,
|
|
41
49
|
} from '@/tools/streamedToolCallSeals';
|
|
50
|
+
import {
|
|
51
|
+
projectOpenAIResponsesToolMessageContent,
|
|
52
|
+
projectToolStreamContentForProvider,
|
|
53
|
+
} from '@/messages/core';
|
|
42
54
|
import { isReasoningModel, _convertMessagesToOpenAIParams } from './utils';
|
|
43
55
|
import { dropRepeatedScalarMetadata } from './streamMetadata';
|
|
44
56
|
|
|
@@ -102,6 +114,9 @@ type LibreChatOpenAIFields = t.ChatOpenAIFields & {
|
|
|
102
114
|
includeReasoningContent?: boolean;
|
|
103
115
|
includeReasoningDetails?: boolean;
|
|
104
116
|
convertReasoningDetailsToContent?: boolean;
|
|
117
|
+
preserveToolCacheControl?: boolean;
|
|
118
|
+
responsesPromptCache?: boolean;
|
|
119
|
+
responsesPromptCacheTtl?: PromptCacheTtl;
|
|
105
120
|
promptCacheExplicit?: boolean;
|
|
106
121
|
safety_identifier?: string;
|
|
107
122
|
};
|
|
@@ -168,6 +183,40 @@ type OpenAIManagedRequestParams = {
|
|
|
168
183
|
};
|
|
169
184
|
safety_identifier?: string;
|
|
170
185
|
};
|
|
186
|
+
|
|
187
|
+
function stripResponsesToolCacheControl<T>(tools: T): T {
|
|
188
|
+
if (!Array.isArray(tools)) {
|
|
189
|
+
return tools;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return tools.map((tool) => {
|
|
193
|
+
if (tool == null || typeof tool !== 'object') {
|
|
194
|
+
return tool;
|
|
195
|
+
}
|
|
196
|
+
const clone = { ...(tool as Record<string, unknown>) };
|
|
197
|
+
delete clone.cache_control;
|
|
198
|
+
if (
|
|
199
|
+
clone.extras != null &&
|
|
200
|
+
typeof clone.extras === 'object' &&
|
|
201
|
+
!Array.isArray(clone.extras)
|
|
202
|
+
) {
|
|
203
|
+
clone.extras = { ...(clone.extras as Record<string, unknown>) };
|
|
204
|
+
delete (clone.extras as Record<string, unknown>).cache_control;
|
|
205
|
+
}
|
|
206
|
+
return clone;
|
|
207
|
+
}) as T;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function projectOpenAIResponsesProviderMessages(
|
|
211
|
+
messages: BaseMessage[]
|
|
212
|
+
): BaseMessage[] {
|
|
213
|
+
return projectOpenAIResponsesToolMessageContent(
|
|
214
|
+
stripAnthropicCacheControl(
|
|
215
|
+
stripBedrockCacheControl(projectToolStreamContentForProvider(messages))
|
|
216
|
+
)
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
171
220
|
type ResponsesRequest =
|
|
172
221
|
| OpenAIClient.Responses.ResponseCreateParamsStreaming
|
|
173
222
|
| OpenAIClient.Responses.ResponseCreateParamsNonStreaming;
|
|
@@ -1116,6 +1165,7 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1116
1165
|
private includeReasoningContent?: boolean;
|
|
1117
1166
|
private includeReasoningDetails?: boolean;
|
|
1118
1167
|
private convertReasoningDetailsToContent?: boolean;
|
|
1168
|
+
private preserveToolCacheControl?: boolean;
|
|
1119
1169
|
private promptCacheExplicit?: boolean;
|
|
1120
1170
|
private safetyIdentifier?: string;
|
|
1121
1171
|
|
|
@@ -1125,6 +1175,7 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1125
1175
|
this.includeReasoningDetails = fields?.includeReasoningDetails;
|
|
1126
1176
|
this.convertReasoningDetailsToContent =
|
|
1127
1177
|
fields?.convertReasoningDetailsToContent;
|
|
1178
|
+
this.preserveToolCacheControl = fields?.preserveToolCacheControl;
|
|
1128
1179
|
this.promptCacheExplicit = fields?.promptCacheExplicit;
|
|
1129
1180
|
this.safetyIdentifier = fields?.safety_identifier;
|
|
1130
1181
|
}
|
|
@@ -1225,6 +1276,7 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1225
1276
|
includeReasoningContent: this.includeReasoningContent,
|
|
1226
1277
|
includeReasoningDetails: this.includeReasoningDetails,
|
|
1227
1278
|
convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
|
|
1279
|
+
preserveToolCacheControl: this.preserveToolCacheControl,
|
|
1228
1280
|
}
|
|
1229
1281
|
);
|
|
1230
1282
|
|
|
@@ -1393,6 +1445,7 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1393
1445
|
includeReasoningContent: this.includeReasoningContent,
|
|
1394
1446
|
includeReasoningDetails: this.includeReasoningDetails,
|
|
1395
1447
|
convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
|
|
1448
|
+
preserveToolCacheControl: this.preserveToolCacheControl,
|
|
1396
1449
|
});
|
|
1397
1450
|
|
|
1398
1451
|
const params = {
|
|
@@ -1533,21 +1586,52 @@ class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
|
1533
1586
|
|
|
1534
1587
|
class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
1535
1588
|
private promptCacheExplicit?: boolean;
|
|
1589
|
+
private responsesPromptCache?: boolean;
|
|
1590
|
+
private responsesPromptCacheTtl?: PromptCacheTtl;
|
|
1536
1591
|
private safetyIdentifier?: string;
|
|
1537
1592
|
|
|
1538
1593
|
constructor(fields?: LibreChatOpenAIFields) {
|
|
1539
1594
|
super(fields);
|
|
1540
1595
|
this.promptCacheExplicit = fields?.promptCacheExplicit;
|
|
1596
|
+
this.responsesPromptCache = fields?.responsesPromptCache;
|
|
1597
|
+
this.responsesPromptCacheTtl = fields?.responsesPromptCacheTtl;
|
|
1541
1598
|
this.safetyIdentifier = fields?.safety_identifier;
|
|
1542
1599
|
}
|
|
1543
1600
|
|
|
1544
1601
|
invocationParams(
|
|
1545
1602
|
options?: this['ParsedCallOptions']
|
|
1546
1603
|
): ReturnType<OriginalChatOpenAIResponses['invocationParams']> {
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1604
|
+
const cacheOptions = options as
|
|
1605
|
+
| {
|
|
1606
|
+
promptCache?: boolean;
|
|
1607
|
+
promptCacheTtl?: PromptCacheTtl;
|
|
1608
|
+
}
|
|
1609
|
+
| undefined;
|
|
1610
|
+
const promptCache = cacheOptions?.promptCache ?? this.responsesPromptCache;
|
|
1611
|
+
const cacheControl =
|
|
1612
|
+
promptCache === true
|
|
1613
|
+
? buildAnthropicCacheControl(
|
|
1614
|
+
resolvePromptCacheTtl(
|
|
1615
|
+
cacheOptions?.promptCacheTtl ?? this.responsesPromptCacheTtl
|
|
1616
|
+
)
|
|
1617
|
+
)
|
|
1618
|
+
: undefined;
|
|
1619
|
+
const baseParams = applyManagedRequestParams(
|
|
1620
|
+
super.invocationParams(options),
|
|
1621
|
+
{
|
|
1622
|
+
promptCacheExplicit: this.promptCacheExplicit,
|
|
1623
|
+
safetyIdentifier: this.safetyIdentifier,
|
|
1624
|
+
}
|
|
1625
|
+
);
|
|
1626
|
+
const params = {
|
|
1627
|
+
...baseParams,
|
|
1628
|
+
...(baseParams.tools != null && {
|
|
1629
|
+
tools: stripResponsesToolCacheControl(baseParams.tools),
|
|
1630
|
+
}),
|
|
1631
|
+
...(cacheControl != null && {
|
|
1632
|
+
cache_control: cacheControl,
|
|
1633
|
+
}),
|
|
1634
|
+
};
|
|
1551
1635
|
if (shouldIncludeEncryptedReasoning(this.model, params)) {
|
|
1552
1636
|
params.include = [
|
|
1553
1637
|
...new Set([
|
|
@@ -1592,7 +1676,11 @@ class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
|
1592
1676
|
options: this['ParsedCallOptions'],
|
|
1593
1677
|
runManager?: CallbackManagerForLLMRun
|
|
1594
1678
|
): Promise<ChatResult> {
|
|
1595
|
-
const result = await super._generate(
|
|
1679
|
+
const result = await super._generate(
|
|
1680
|
+
projectOpenAIResponsesProviderMessages(messages),
|
|
1681
|
+
options,
|
|
1682
|
+
runManager
|
|
1683
|
+
);
|
|
1596
1684
|
for (const generation of result.generations) {
|
|
1597
1685
|
attachCacheWriteUsage(generation.message);
|
|
1598
1686
|
}
|
|
@@ -1605,7 +1693,7 @@ class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
|
1605
1693
|
runManager?: CallbackManagerForLLMRun
|
|
1606
1694
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
1607
1695
|
for await (const chunk of super._streamResponseChunks(
|
|
1608
|
-
messages,
|
|
1696
|
+
projectOpenAIResponsesProviderMessages(messages),
|
|
1609
1697
|
options,
|
|
1610
1698
|
runManager
|
|
1611
1699
|
)) {
|
|
@@ -1614,6 +1702,18 @@ class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
|
1614
1702
|
}
|
|
1615
1703
|
}
|
|
1616
1704
|
|
|
1705
|
+
async *_streamChatModelEvents(
|
|
1706
|
+
messages: BaseMessage[],
|
|
1707
|
+
options: this['ParsedCallOptions'],
|
|
1708
|
+
runManager?: CallbackManagerForLLMRun
|
|
1709
|
+
): AsyncGenerator<ChatModelStreamEvent> {
|
|
1710
|
+
yield* super._streamChatModelEvents(
|
|
1711
|
+
projectOpenAIResponsesProviderMessages(messages),
|
|
1712
|
+
options,
|
|
1713
|
+
runManager
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1617
1717
|
protected _getReasoningParams(
|
|
1618
1718
|
options?: this['ParsedCallOptions']
|
|
1619
1719
|
): OpenAIClient.Reasoning | undefined {
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { type OpenAI as OpenAIClient } from 'openai';
|
|
4
4
|
import { ChatGenerationChunk } from '@langchain/core/outputs';
|
|
5
5
|
import {
|
|
6
|
-
convertLangChainToolCallToOpenAI,
|
|
7
6
|
makeInvalidToolCall,
|
|
8
7
|
parseToolCall,
|
|
9
8
|
} from '@langchain/core/output_parsers/openai_tools';
|
|
@@ -37,11 +36,23 @@ import type {
|
|
|
37
36
|
ChatOpenAIReasoningSummary,
|
|
38
37
|
} from '@langchain/openai';
|
|
39
38
|
import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
|
|
39
|
+
import {
|
|
40
|
+
getBoundedCacheControlledTextToolContent,
|
|
41
|
+
getComputerCallOutputScreenshot,
|
|
42
|
+
isComputerCallOutputMessage,
|
|
43
|
+
serializeStructuredValueBounded,
|
|
44
|
+
} from '@/utils/toolContent';
|
|
40
45
|
import {
|
|
41
46
|
STREAMED_TOOL_CALL_SEAL_METADATA_KEY,
|
|
42
47
|
STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY,
|
|
43
48
|
OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER,
|
|
44
49
|
} from '@/tools/streamedToolCallSeals';
|
|
50
|
+
import {
|
|
51
|
+
calculateMaxToolCallInputChars,
|
|
52
|
+
projectToolCallInputs,
|
|
53
|
+
serializeToolCallInput,
|
|
54
|
+
} from '@/messages/prune';
|
|
55
|
+
import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
|
|
45
56
|
import { toLangChainContent } from '@/messages/langchain';
|
|
46
57
|
|
|
47
58
|
export type { OpenAICallOptions, OpenAIChatInput };
|
|
@@ -83,6 +94,32 @@ type OpenAIRoleEnum =
|
|
|
83
94
|
type OpenAICompletionParam =
|
|
84
95
|
OpenAIClient.Chat.Completions.ChatCompletionMessageParam;
|
|
85
96
|
|
|
97
|
+
const MAX_PROVIDER_TOOL_CALL_INPUT_CHARS = calculateMaxToolCallInputChars();
|
|
98
|
+
|
|
99
|
+
function convertLangChainToolCallToBoundedOpenAI(toolCall: ToolCall): {
|
|
100
|
+
id: string;
|
|
101
|
+
type: 'function';
|
|
102
|
+
function: {
|
|
103
|
+
name: string;
|
|
104
|
+
arguments: string;
|
|
105
|
+
};
|
|
106
|
+
} {
|
|
107
|
+
if (toolCall.id == null) {
|
|
108
|
+
throw new Error('All OpenAI tool calls must have an "id" field.');
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
id: toolCall.id,
|
|
112
|
+
type: 'function',
|
|
113
|
+
function: {
|
|
114
|
+
name: toolCall.name,
|
|
115
|
+
arguments: serializeToolCallInput(
|
|
116
|
+
toolCall.args,
|
|
117
|
+
MAX_PROVIDER_TOOL_CALL_INPUT_CHARS
|
|
118
|
+
),
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
86
123
|
function extractGenericMessageCustomRole(message: ChatMessage) {
|
|
87
124
|
if (
|
|
88
125
|
message.role !== 'system' &&
|
|
@@ -300,6 +337,8 @@ export interface ConvertMessagesOptions {
|
|
|
300
337
|
includeReasoningDetails?: boolean;
|
|
301
338
|
/** Convert reasoning_details to content blocks for Claude (requires content array format) */
|
|
302
339
|
convertReasoningDetailsToContent?: boolean;
|
|
340
|
+
/** Preserve OpenRouter's canonical cache-decorated tool text block. */
|
|
341
|
+
preserveToolCacheControl?: boolean;
|
|
303
342
|
}
|
|
304
343
|
|
|
305
344
|
// Used in LangSmith, export is important here
|
|
@@ -308,9 +347,13 @@ export function _convertMessagesToOpenAIParams(
|
|
|
308
347
|
model?: string,
|
|
309
348
|
options?: ConvertMessagesOptions
|
|
310
349
|
): OpenAICompletionParam[] {
|
|
350
|
+
const projectedMessages = projectToolCallInputs(
|
|
351
|
+
messages,
|
|
352
|
+
MAX_PROVIDER_TOOL_CALL_INPUT_CHARS
|
|
353
|
+
);
|
|
311
354
|
let hasReasoningToolCallContext = false;
|
|
312
355
|
// TODO: Function messages do not support array content, fix cast
|
|
313
|
-
return
|
|
356
|
+
return projectedMessages.flatMap((message) => {
|
|
314
357
|
let role = messageToOpenAIRole(message);
|
|
315
358
|
if (role === 'system' && isReasoningModel(model)) {
|
|
316
359
|
role = 'developer';
|
|
@@ -318,22 +361,40 @@ export function _convertMessagesToOpenAIParams(
|
|
|
318
361
|
|
|
319
362
|
let hasAnthropicThinkingBlock: boolean = false;
|
|
320
363
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
364
|
+
let content: unknown;
|
|
365
|
+
if (
|
|
366
|
+
role === 'tool' &&
|
|
367
|
+
typeof message.content !== 'string' &&
|
|
368
|
+
!isComputerCallOutputMessage(message)
|
|
369
|
+
) {
|
|
370
|
+
content =
|
|
371
|
+
options?.preserveToolCacheControl === true
|
|
372
|
+
? getBoundedCacheControlledTextToolContent(
|
|
373
|
+
message.content,
|
|
374
|
+
HARD_MAX_TOOL_RESULT_CHARS
|
|
375
|
+
)
|
|
376
|
+
: undefined;
|
|
377
|
+
content ??= serializeStructuredValueBounded(
|
|
378
|
+
message.content,
|
|
379
|
+
HARD_MAX_TOOL_RESULT_CHARS
|
|
380
|
+
).content;
|
|
381
|
+
} else if (typeof message.content === 'string') {
|
|
382
|
+
content = message.content;
|
|
383
|
+
} else {
|
|
384
|
+
content = message.content.map((m) => {
|
|
385
|
+
if ('type' in m && m.type === 'thinking') {
|
|
386
|
+
hasAnthropicThinkingBlock = true;
|
|
335
387
|
return m;
|
|
336
|
-
}
|
|
388
|
+
}
|
|
389
|
+
if (isDataContentBlock(m)) {
|
|
390
|
+
return convertToProviderContentBlock(
|
|
391
|
+
m,
|
|
392
|
+
completionsApiContentBlockConverter
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return m;
|
|
396
|
+
});
|
|
397
|
+
}
|
|
337
398
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
338
399
|
const completionParam: Record<string, any> = {
|
|
339
400
|
role,
|
|
@@ -351,7 +412,7 @@ export function _convertMessagesToOpenAIParams(
|
|
|
351
412
|
if (isAIMessage(message) && !!message.tool_calls?.length) {
|
|
352
413
|
messageHasToolCalls = true;
|
|
353
414
|
completionParam.tool_calls = message.tool_calls.map(
|
|
354
|
-
|
|
415
|
+
convertLangChainToolCallToBoundedOpenAI
|
|
355
416
|
);
|
|
356
417
|
completionParam.content = hasAnthropicThinkingBlock ? content : '';
|
|
357
418
|
if (
|
|
@@ -527,7 +588,11 @@ export function _convertMessagesToOpenAIResponsesParams(
|
|
|
527
588
|
model?: string,
|
|
528
589
|
zdrEnabled?: boolean
|
|
529
590
|
): ResponsesInputItem[] {
|
|
530
|
-
|
|
591
|
+
const projectedMessages = projectToolCallInputs(
|
|
592
|
+
messages,
|
|
593
|
+
MAX_PROVIDER_TOOL_CALL_INPUT_CHARS
|
|
594
|
+
);
|
|
595
|
+
return projectedMessages.flatMap(
|
|
531
596
|
(lcMsg): ResponsesInputItem | ResponsesInputItem[] => {
|
|
532
597
|
const additional_kwargs =
|
|
533
598
|
lcMsg.additional_kwargs as BaseMessageFields['additional_kwargs'] & {
|
|
@@ -552,44 +617,29 @@ export function _convertMessagesToOpenAIResponsesParams(
|
|
|
552
617
|
|
|
553
618
|
// Handle computer call output
|
|
554
619
|
if (additional_kwargs.type === 'computer_call_output') {
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
image_url: toolMessage.content,
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
if (Array.isArray(toolMessage.content)) {
|
|
564
|
-
const oaiScreenshot = toolMessage.content.find(
|
|
565
|
-
(i) => i.type === 'computer_screenshot'
|
|
566
|
-
) as { type: 'computer_screenshot'; image_url: string };
|
|
567
|
-
|
|
568
|
-
if (oaiScreenshot) return oaiScreenshot;
|
|
569
|
-
|
|
570
|
-
const lcImage = toolMessage.content.find(
|
|
571
|
-
(i) => i.type === 'image_url'
|
|
572
|
-
) as MessageContentImageUrl;
|
|
573
|
-
|
|
574
|
-
if (lcImage) {
|
|
575
|
-
return {
|
|
576
|
-
type: 'computer_screenshot' as const,
|
|
577
|
-
image_url:
|
|
578
|
-
typeof lcImage.image_url === 'string'
|
|
579
|
-
? lcImage.image_url
|
|
580
|
-
: lcImage.image_url.url,
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
620
|
+
const screenshot = getComputerCallOutputScreenshot(
|
|
621
|
+
toolMessage.content
|
|
622
|
+
);
|
|
623
|
+
if (screenshot == null) {
|
|
585
624
|
throw new Error('Invalid computer call output');
|
|
586
|
-
}
|
|
625
|
+
}
|
|
587
626
|
|
|
588
|
-
|
|
627
|
+
const output: OpenAIClient.Responses.ResponseComputerToolCallOutputScreenshot =
|
|
628
|
+
'image_url' in screenshot
|
|
629
|
+
? {
|
|
630
|
+
type: 'computer_screenshot',
|
|
631
|
+
image_url: screenshot.image_url,
|
|
632
|
+
}
|
|
633
|
+
: {
|
|
634
|
+
type: 'computer_screenshot',
|
|
635
|
+
file_id: screenshot.file_id,
|
|
636
|
+
};
|
|
637
|
+
const computerCallOutput: ResponsesInputItem = {
|
|
589
638
|
type: 'computer_call_output',
|
|
590
639
|
output,
|
|
591
640
|
call_id: toolMessage.tool_call_id,
|
|
592
641
|
};
|
|
642
|
+
return computerCallOutput;
|
|
593
643
|
}
|
|
594
644
|
|
|
595
645
|
return {
|
|
@@ -598,7 +648,10 @@ export function _convertMessagesToOpenAIResponsesParams(
|
|
|
598
648
|
id: toolMessage.id?.startsWith('fc_') ? toolMessage.id : undefined,
|
|
599
649
|
output:
|
|
600
650
|
typeof toolMessage.content !== 'string'
|
|
601
|
-
?
|
|
651
|
+
? serializeStructuredValueBounded(
|
|
652
|
+
toolMessage.content,
|
|
653
|
+
HARD_MAX_TOOL_RESULT_CHARS
|
|
654
|
+
).content
|
|
602
655
|
: toolMessage.content,
|
|
603
656
|
};
|
|
604
657
|
}
|
|
@@ -682,7 +735,10 @@ export function _convertMessagesToOpenAIResponsesParams(
|
|
|
682
735
|
(toolCall): ResponsesInputItem => ({
|
|
683
736
|
type: 'function_call',
|
|
684
737
|
name: toolCall.name,
|
|
685
|
-
arguments:
|
|
738
|
+
arguments: serializeToolCallInput(
|
|
739
|
+
toolCall.args,
|
|
740
|
+
MAX_PROVIDER_TOOL_CALL_INPUT_CHARS
|
|
741
|
+
),
|
|
686
742
|
call_id: toolCall.id!,
|
|
687
743
|
...(zdrEnabled ? { id: functionCallIds?.[toolCall.id!] } : {}),
|
|
688
744
|
})
|