@librechat/agents 3.1.75 → 3.1.77-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +22 -3
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hitl/askUserQuestion.cjs +67 -0
- package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -0
- package/dist/cjs/hooks/HookRegistry.cjs +54 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/createToolPolicyHook.cjs +115 -0
- package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -0
- package/dist/cjs/hooks/executeHooks.cjs +40 -1
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/langchain/google-common.cjs +3 -0
- package/dist/cjs/langchain/google-common.cjs.map +1 -0
- package/dist/cjs/langchain/index.cjs +86 -0
- package/dist/cjs/langchain/index.cjs.map +1 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs +3 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs.map +1 -0
- package/dist/cjs/langchain/messages/tool.cjs +3 -0
- package/dist/cjs/langchain/messages/tool.cjs.map +1 -0
- package/dist/cjs/langchain/messages.cjs +51 -0
- package/dist/cjs/langchain/messages.cjs.map +1 -0
- package/dist/cjs/langchain/openai.cjs +3 -0
- package/dist/cjs/langchain/openai.cjs.map +1 -0
- package/dist/cjs/langchain/prompts.cjs +11 -0
- package/dist/cjs/langchain/prompts.cjs.map +1 -0
- package/dist/cjs/langchain/runnables.cjs +19 -0
- package/dist/cjs/langchain/runnables.cjs.map +1 -0
- package/dist/cjs/langchain/tools.cjs +23 -0
- package/dist/cjs/langchain/tools.cjs.map +1 -0
- package/dist/cjs/langchain/utils/env.cjs +11 -0
- package/dist/cjs/langchain/utils/env.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/index.cjs +145 -52
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +21 -14
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +84 -70
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +1 -1
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +213 -3
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +2 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +5 -4
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +519 -655
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +20 -458
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +57 -175
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +5 -3
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +112 -3
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +2 -1
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +7 -6
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +73 -15
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/langchain.cjs +26 -0
- package/dist/cjs/messages/langchain.cjs.map +1 -0
- package/dist/cjs/messages/prune.cjs +7 -6
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +400 -42
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +556 -56
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +55 -66
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-scraper.cjs +189 -0
- package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -0
- package/dist/cjs/tools/search/tavily-search.cjs +372 -0
- package/dist/cjs/tools/search/tavily-search.cjs.map +1 -0
- package/dist/cjs/tools/search/tool.cjs +26 -4
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +10 -3
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +22 -3
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hitl/askUserQuestion.mjs +65 -0
- package/dist/esm/hitl/askUserQuestion.mjs.map +1 -0
- package/dist/esm/hooks/HookRegistry.mjs +54 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/createToolPolicyHook.mjs +113 -0
- package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -0
- package/dist/esm/hooks/executeHooks.mjs +40 -1
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -0
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/langchain/google-common.mjs +2 -0
- package/dist/esm/langchain/google-common.mjs.map +1 -0
- package/dist/esm/langchain/index.mjs +5 -0
- package/dist/esm/langchain/index.mjs.map +1 -0
- package/dist/esm/langchain/language_models/chat_models.mjs +2 -0
- package/dist/esm/langchain/language_models/chat_models.mjs.map +1 -0
- package/dist/esm/langchain/messages/tool.mjs +2 -0
- package/dist/esm/langchain/messages/tool.mjs.map +1 -0
- package/dist/esm/langchain/messages.mjs +2 -0
- package/dist/esm/langchain/messages.mjs.map +1 -0
- package/dist/esm/langchain/openai.mjs +2 -0
- package/dist/esm/langchain/openai.mjs.map +1 -0
- package/dist/esm/langchain/prompts.mjs +2 -0
- package/dist/esm/langchain/prompts.mjs.map +1 -0
- package/dist/esm/langchain/runnables.mjs +2 -0
- package/dist/esm/langchain/runnables.mjs.map +1 -0
- package/dist/esm/langchain/tools.mjs +2 -0
- package/dist/esm/langchain/tools.mjs.map +1 -0
- package/dist/esm/langchain/utils/env.mjs +2 -0
- package/dist/esm/langchain/utils/env.mjs.map +1 -0
- package/dist/esm/llm/anthropic/index.mjs +146 -54
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +21 -14
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +84 -71
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +1 -1
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +214 -4
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs +2 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +5 -4
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +520 -656
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +23 -459
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +57 -175
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +5 -3
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +7 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +2 -1
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +7 -6
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +73 -15
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/langchain.mjs +23 -0
- package/dist/esm/messages/langchain.mjs.map +1 -0
- package/dist/esm/messages/prune.mjs +7 -6
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +400 -42
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +557 -57
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +55 -66
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-scraper.mjs +186 -0
- package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -0
- package/dist/esm/tools/search/tavily-search.mjs +370 -0
- package/dist/esm/tools/search/tavily-search.mjs.map +1 -0
- package/dist/esm/tools/search/tool.mjs +26 -4
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +10 -3
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +7 -0
- package/dist/types/hitl/askUserQuestion.d.ts +55 -0
- package/dist/types/hitl/index.d.ts +6 -0
- package/dist/types/hooks/HookRegistry.d.ts +58 -0
- package/dist/types/hooks/createToolPolicyHook.d.ts +87 -0
- package/dist/types/hooks/index.d.ts +4 -1
- package/dist/types/hooks/types.d.ts +109 -3
- package/dist/types/index.d.ts +10 -0
- package/dist/types/langchain/google-common.d.ts +1 -0
- package/dist/types/langchain/index.d.ts +8 -0
- package/dist/types/langchain/language_models/chat_models.d.ts +1 -0
- package/dist/types/langchain/messages/tool.d.ts +1 -0
- package/dist/types/langchain/messages.d.ts +2 -0
- package/dist/types/langchain/openai.d.ts +1 -0
- package/dist/types/langchain/prompts.d.ts +1 -0
- package/dist/types/langchain/runnables.d.ts +2 -0
- package/dist/types/langchain/tools.d.ts +2 -0
- package/dist/types/langchain/utils/env.d.ts +1 -0
- package/dist/types/llm/anthropic/index.d.ts +22 -9
- package/dist/types/llm/anthropic/types.d.ts +5 -1
- package/dist/types/llm/anthropic/utils/message_outputs.d.ts +13 -6
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +1 -1
- package/dist/types/llm/openai/index.d.ts +21 -24
- package/dist/types/llm/openrouter/index.d.ts +11 -9
- package/dist/types/llm/vertexai/index.d.ts +1 -0
- package/dist/types/messages/cache.d.ts +4 -1
- package/dist/types/messages/format.d.ts +4 -1
- package/dist/types/messages/langchain.d.ts +27 -0
- package/dist/types/run.d.ts +117 -1
- package/dist/types/tools/ToolNode.d.ts +26 -1
- package/dist/types/tools/search/tavily-scraper.d.ts +19 -0
- package/dist/types/tools/search/tavily-search.d.ts +4 -0
- package/dist/types/tools/search/types.d.ts +99 -5
- package/dist/types/tools/search/utils.d.ts +2 -2
- package/dist/types/types/graph.d.ts +23 -37
- package/dist/types/types/hitl.d.ts +272 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/llm.d.ts +3 -3
- package/dist/types/types/run.d.ts +33 -0
- package/dist/types/types/stream.d.ts +1 -1
- package/dist/types/types/tools.d.ts +19 -0
- package/package.json +80 -17
- package/src/graphs/Graph.ts +33 -4
- package/src/graphs/__tests__/composition.smoke.test.ts +188 -0
- package/src/hitl/askUserQuestion.ts +72 -0
- package/src/hitl/index.ts +7 -0
- package/src/hooks/HookRegistry.ts +71 -0
- package/src/hooks/__tests__/createToolPolicyHook.test.ts +259 -0
- package/src/hooks/createToolPolicyHook.ts +184 -0
- package/src/hooks/executeHooks.ts +50 -1
- package/src/hooks/index.ts +6 -0
- package/src/hooks/types.ts +112 -0
- package/src/index.ts +22 -0
- package/src/langchain/google-common.ts +1 -0
- package/src/langchain/index.ts +8 -0
- package/src/langchain/language_models/chat_models.ts +1 -0
- package/src/langchain/messages/tool.ts +5 -0
- package/src/langchain/messages.ts +21 -0
- package/src/langchain/openai.ts +1 -0
- package/src/langchain/prompts.ts +1 -0
- package/src/langchain/runnables.ts +7 -0
- package/src/langchain/tools.ts +8 -0
- package/src/langchain/utils/env.ts +1 -0
- package/src/llm/anthropic/index.ts +252 -84
- package/src/llm/anthropic/llm.spec.ts +751 -102
- package/src/llm/anthropic/types.ts +9 -1
- package/src/llm/anthropic/utils/message_inputs.ts +37 -19
- package/src/llm/anthropic/utils/message_outputs.ts +119 -101
- package/src/llm/bedrock/index.ts +2 -2
- package/src/llm/bedrock/llm.spec.ts +341 -0
- package/src/llm/bedrock/utils/message_inputs.ts +303 -4
- package/src/llm/bedrock/utils/message_outputs.ts +2 -1
- package/src/llm/custom-chat-models.smoke.test.ts +836 -0
- package/src/llm/google/llm.spec.ts +339 -57
- package/src/llm/google/utils/common.ts +53 -48
- package/src/llm/openai/contentBlocks.test.ts +346 -0
- package/src/llm/openai/index.ts +856 -833
- package/src/llm/openai/utils/index.ts +107 -78
- package/src/llm/openai/utils/messages.test.ts +159 -0
- package/src/llm/openrouter/index.ts +124 -247
- package/src/llm/openrouter/reasoning.test.ts +8 -1
- package/src/llm/vertexai/index.ts +11 -5
- package/src/llm/vertexai/llm.spec.ts +28 -1
- package/src/messages/cache.test.ts +4 -3
- package/src/messages/cache.ts +3 -2
- package/src/messages/core.ts +16 -9
- package/src/messages/format.ts +96 -16
- package/src/messages/formatAgentMessages.test.ts +166 -1
- package/src/messages/langchain.ts +39 -0
- package/src/messages/prune.ts +12 -8
- package/src/run.ts +456 -47
- package/src/scripts/caching.ts +2 -3
- package/src/specs/summarization.test.ts +51 -58
- package/src/tools/ToolNode.ts +706 -63
- package/src/tools/__tests__/hitl.test.ts +3593 -0
- package/src/tools/search/search.ts +83 -73
- package/src/tools/search/tavily-scraper.ts +235 -0
- package/src/tools/search/tavily-search.ts +424 -0
- package/src/tools/search/tavily.test.ts +965 -0
- package/src/tools/search/tool.ts +36 -26
- package/src/tools/search/types.ts +133 -8
- package/src/tools/search/utils.ts +13 -5
- package/src/types/graph.ts +32 -87
- package/src/types/hitl.ts +303 -0
- package/src/types/index.ts +1 -0
- package/src/types/llm.ts +3 -3
- package/src/types/run.ts +33 -0
- package/src/types/stream.ts +1 -1
- package/src/types/tools.ts +19 -0
- package/src/utils/llmConfig.ts +1 -6
package/src/messages/format.ts
CHANGED
|
@@ -7,13 +7,19 @@ import {
|
|
|
7
7
|
HumanMessage,
|
|
8
8
|
SystemMessage,
|
|
9
9
|
} from '@langchain/core/messages';
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
MessageContent,
|
|
12
|
+
MessageContentImageUrl,
|
|
13
|
+
} from '@langchain/core/messages';
|
|
11
14
|
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
12
15
|
import type {
|
|
16
|
+
BedrockReasoningContentText,
|
|
13
17
|
ExtendedMessageContent,
|
|
18
|
+
GoogleReasoningContentText,
|
|
14
19
|
MessageContentComplex,
|
|
15
20
|
ReasoningContentText,
|
|
16
21
|
SummaryContentBlock,
|
|
22
|
+
ThinkingContentText,
|
|
17
23
|
ToolCallContent,
|
|
18
24
|
ToolCallPart,
|
|
19
25
|
TPayload,
|
|
@@ -22,6 +28,7 @@ import type {
|
|
|
22
28
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
23
29
|
import { emitAgentLog } from '@/utils/events';
|
|
24
30
|
import { Providers, ContentTypes, Constants } from '@/common';
|
|
31
|
+
import { toLangChainContent, toLangChainMessageFields } from './langchain';
|
|
25
32
|
|
|
26
33
|
interface MediaMessageParams {
|
|
27
34
|
message: {
|
|
@@ -210,7 +217,7 @@ export const formatMessage = ({
|
|
|
210
217
|
return mediaMessage;
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
return new HumanMessage(mediaMessage);
|
|
220
|
+
return new HumanMessage(toLangChainMessageFields(mediaMessage));
|
|
214
221
|
}
|
|
215
222
|
|
|
216
223
|
if (!langChain) {
|
|
@@ -218,11 +225,11 @@ export const formatMessage = ({
|
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
if (role === 'user') {
|
|
221
|
-
return new HumanMessage(formattedMessage);
|
|
228
|
+
return new HumanMessage(toLangChainMessageFields(formattedMessage));
|
|
222
229
|
} else if (role === 'assistant') {
|
|
223
|
-
return new AIMessage(formattedMessage);
|
|
230
|
+
return new AIMessage(toLangChainMessageFields(formattedMessage));
|
|
224
231
|
} else {
|
|
225
|
-
return new SystemMessage(formattedMessage);
|
|
232
|
+
return new SystemMessage(toLangChainMessageFields(formattedMessage));
|
|
226
233
|
}
|
|
227
234
|
};
|
|
228
235
|
|
|
@@ -276,18 +283,86 @@ export const formatFromLangChain = (
|
|
|
276
283
|
};
|
|
277
284
|
};
|
|
278
285
|
|
|
286
|
+
interface FormatAssistantMessageOptions {
|
|
287
|
+
preserveReasoningContent?: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
interface FormatAgentMessagesOptions {
|
|
291
|
+
provider?: Providers;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function extractReasoningContent(
|
|
295
|
+
part: MessageContentComplex | undefined | null
|
|
296
|
+
): string {
|
|
297
|
+
if (part == null || typeof part !== 'object') {
|
|
298
|
+
return '';
|
|
299
|
+
}
|
|
300
|
+
if (part.type === ContentTypes.THINK) {
|
|
301
|
+
const think = (part as ReasoningContentText).think;
|
|
302
|
+
return typeof think === 'string' ? think : '';
|
|
303
|
+
}
|
|
304
|
+
if (part.type === ContentTypes.THINKING) {
|
|
305
|
+
const thinking = (part as ThinkingContentText).thinking;
|
|
306
|
+
return typeof thinking === 'string' ? thinking : '';
|
|
307
|
+
}
|
|
308
|
+
if (part.type === ContentTypes.REASONING) {
|
|
309
|
+
const reasoning = (part as GoogleReasoningContentText).reasoning;
|
|
310
|
+
return typeof reasoning === 'string' ? reasoning : '';
|
|
311
|
+
}
|
|
312
|
+
if (part.type === ContentTypes.REASONING_CONTENT) {
|
|
313
|
+
const reasoningText = (part as BedrockReasoningContentText).reasoningText;
|
|
314
|
+
return typeof reasoningText.text === 'string' ? reasoningText.text : '';
|
|
315
|
+
}
|
|
316
|
+
return '';
|
|
317
|
+
}
|
|
318
|
+
|
|
279
319
|
/**
|
|
280
320
|
* Helper function to format an assistant message
|
|
281
321
|
* @param message The message to format
|
|
322
|
+
* @param options Optional formatting options
|
|
282
323
|
* @returns Array of formatted messages
|
|
283
324
|
*/
|
|
284
325
|
function formatAssistantMessage(
|
|
285
|
-
message: Partial<TMessage
|
|
326
|
+
message: Partial<TMessage>,
|
|
327
|
+
options?: FormatAssistantMessageOptions
|
|
286
328
|
): Array<AIMessage | ToolMessage> {
|
|
287
329
|
const formattedMessages: Array<AIMessage | ToolMessage> = [];
|
|
288
330
|
let currentContent: MessageContentComplex[] = [];
|
|
289
331
|
let lastAIMessage: AIMessage | null = null;
|
|
290
332
|
let hasReasoning = false;
|
|
333
|
+
let pendingReasoningContent = '';
|
|
334
|
+
const shouldPreserveReasoningContent =
|
|
335
|
+
options?.preserveReasoningContent === true;
|
|
336
|
+
|
|
337
|
+
const takePendingReasoningContent = (): string | undefined => {
|
|
338
|
+
if (!shouldPreserveReasoningContent || !pendingReasoningContent) {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
const reasoningContent = pendingReasoningContent;
|
|
342
|
+
pendingReasoningContent = '';
|
|
343
|
+
return reasoningContent;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const createAIMessage = (content: MessageContent): AIMessage => {
|
|
347
|
+
const reasoningContent = takePendingReasoningContent();
|
|
348
|
+
return new AIMessage({
|
|
349
|
+
content,
|
|
350
|
+
...(reasoningContent != null && {
|
|
351
|
+
additional_kwargs: { reasoning_content: reasoningContent },
|
|
352
|
+
}),
|
|
353
|
+
});
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const attachPendingReasoningContent = (aiMessage: AIMessage): void => {
|
|
357
|
+
const reasoningContent = takePendingReasoningContent();
|
|
358
|
+
if (reasoningContent == null) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
aiMessage.additional_kwargs.reasoning_content =
|
|
362
|
+
typeof aiMessage.additional_kwargs.reasoning_content === 'string'
|
|
363
|
+
? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}`
|
|
364
|
+
: reasoningContent;
|
|
365
|
+
};
|
|
291
366
|
|
|
292
367
|
if (Array.isArray(message.content)) {
|
|
293
368
|
for (const part of message.content as Array<
|
|
@@ -310,15 +385,13 @@ function formatAssistantMessage(
|
|
|
310
385
|
}, '');
|
|
311
386
|
content =
|
|
312
387
|
`${content}\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();
|
|
313
|
-
lastAIMessage =
|
|
388
|
+
lastAIMessage = createAIMessage(content);
|
|
314
389
|
formattedMessages.push(lastAIMessage);
|
|
315
390
|
currentContent = [];
|
|
316
391
|
continue;
|
|
317
392
|
}
|
|
318
393
|
// Create a new AIMessage with this text and prepare for tool calls
|
|
319
|
-
lastAIMessage =
|
|
320
|
-
content: part.text != null ? part.text : '',
|
|
321
|
-
});
|
|
394
|
+
lastAIMessage = createAIMessage(part.text != null ? part.text : '');
|
|
322
395
|
formattedMessages.push(lastAIMessage);
|
|
323
396
|
} else if (part.type === ContentTypes.TOOL_CALL) {
|
|
324
397
|
// Skip malformed tool call entries without tool_call property
|
|
@@ -343,8 +416,10 @@ function formatAssistantMessage(
|
|
|
343
416
|
|
|
344
417
|
if (!lastAIMessage) {
|
|
345
418
|
// "Heal" the payload by creating an AIMessage to precede the tool call
|
|
346
|
-
lastAIMessage =
|
|
419
|
+
lastAIMessage = createAIMessage('');
|
|
347
420
|
formattedMessages.push(lastAIMessage);
|
|
421
|
+
} else {
|
|
422
|
+
attachPendingReasoningContent(lastAIMessage);
|
|
348
423
|
}
|
|
349
424
|
|
|
350
425
|
const tool_call: ToolCallPart = _tool_call;
|
|
@@ -376,10 +451,12 @@ function formatAssistantMessage(
|
|
|
376
451
|
} else if (
|
|
377
452
|
part.type === ContentTypes.THINK ||
|
|
378
453
|
part.type === ContentTypes.THINKING ||
|
|
454
|
+
part.type === ContentTypes.REASONING ||
|
|
379
455
|
part.type === ContentTypes.REASONING_CONTENT ||
|
|
380
456
|
part.type === 'redacted_thinking'
|
|
381
457
|
) {
|
|
382
458
|
hasReasoning = true;
|
|
459
|
+
pendingReasoningContent += extractReasoningContent(part);
|
|
383
460
|
continue;
|
|
384
461
|
} else if (
|
|
385
462
|
part.type === ContentTypes.ERROR ||
|
|
@@ -410,10 +487,10 @@ function formatAssistantMessage(
|
|
|
410
487
|
.trim();
|
|
411
488
|
|
|
412
489
|
if (content) {
|
|
413
|
-
formattedMessages.push(
|
|
490
|
+
formattedMessages.push(createAIMessage(content));
|
|
414
491
|
}
|
|
415
492
|
} else if (currentContent.length > 0) {
|
|
416
|
-
formattedMessages.push(
|
|
493
|
+
formattedMessages.push(createAIMessage(toLangChainContent(currentContent)));
|
|
417
494
|
}
|
|
418
495
|
|
|
419
496
|
return formattedMessages;
|
|
@@ -829,7 +906,8 @@ export const formatAgentMessages = (
|
|
|
829
906
|
/** Pre-resolved skill bodies keyed by skill name. When present, HumanMessages
|
|
830
907
|
* are reconstructed after skill ToolMessages to restore skill instructions
|
|
831
908
|
* that were only in LangGraph state during the original run. */
|
|
832
|
-
skills?: Map<string, string
|
|
909
|
+
skills?: Map<string, string>,
|
|
910
|
+
options?: FormatAgentMessagesOptions
|
|
833
911
|
): {
|
|
834
912
|
messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
|
|
835
913
|
indexTokenCountMap?: Record<number, number>;
|
|
@@ -1077,7 +1155,9 @@ export const formatAgentMessages = (
|
|
|
1077
1155
|
}
|
|
1078
1156
|
}
|
|
1079
1157
|
|
|
1080
|
-
const formattedMessages = formatAssistantMessage(processedMessage
|
|
1158
|
+
const formattedMessages = formatAssistantMessage(processedMessage, {
|
|
1159
|
+
preserveReasoningContent: options?.provider === Providers.DEEPSEEK,
|
|
1160
|
+
});
|
|
1081
1161
|
if (sourceMessageId != null && sourceMessageId !== '') {
|
|
1082
1162
|
for (const formattedMessage of formattedMessages) {
|
|
1083
1163
|
formattedMessage.id = sourceMessageId;
|
|
@@ -1542,7 +1622,7 @@ export function ensureThinkingBlockInMessages(
|
|
|
1542
1622
|
'ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage' +
|
|
1543
1623
|
` (${parts.length} msgs at index ${i}, no thinking block in chain)`
|
|
1544
1624
|
);
|
|
1545
|
-
result.push(new HumanMessage({ content: parts }));
|
|
1625
|
+
result.push(new HumanMessage({ content: toLangChainContent(parts) }));
|
|
1546
1626
|
i = j;
|
|
1547
1627
|
} else {
|
|
1548
1628
|
// Keep the message as is
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from '@langchain/core/messages';
|
|
7
7
|
import type { MessageContentComplex, TPayload } from '@/types';
|
|
8
8
|
import { formatAgentMessages } from './format';
|
|
9
|
-
import { ContentTypes } from '@/common';
|
|
9
|
+
import { ContentTypes, Providers } from '@/common';
|
|
10
10
|
|
|
11
11
|
describe('formatAgentMessages', () => {
|
|
12
12
|
it('should format simple user and AI messages', () => {
|
|
@@ -967,6 +967,171 @@ describe('formatAgentMessages', () => {
|
|
|
967
967
|
);
|
|
968
968
|
});
|
|
969
969
|
|
|
970
|
+
it('should preserve hidden reasoning_content for DeepSeek assistant messages', () => {
|
|
971
|
+
const payload: TPayload = [
|
|
972
|
+
{
|
|
973
|
+
role: 'assistant',
|
|
974
|
+
content: [
|
|
975
|
+
{
|
|
976
|
+
type: ContentTypes.THINK,
|
|
977
|
+
[ContentTypes.THINK]: 'Need calculator.',
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
type: ContentTypes.TEXT,
|
|
981
|
+
[ContentTypes.TEXT]: 'Using calculator.',
|
|
982
|
+
tool_call_ids: ['call_1'],
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
type: ContentTypes.TOOL_CALL,
|
|
986
|
+
tool_call: {
|
|
987
|
+
id: 'call_1',
|
|
988
|
+
name: 'calculator',
|
|
989
|
+
args: '{"input":"127 * 453"}',
|
|
990
|
+
output: '57531',
|
|
991
|
+
},
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
type: ContentTypes.THINK,
|
|
995
|
+
[ContentTypes.THINK]: 'Calculator returned 57531.',
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
type: ContentTypes.TEXT,
|
|
999
|
+
[ContentTypes.TEXT]: '127 * 453 = 57531.',
|
|
1000
|
+
},
|
|
1001
|
+
],
|
|
1002
|
+
},
|
|
1003
|
+
];
|
|
1004
|
+
|
|
1005
|
+
const defaultResult = formatAgentMessages(payload);
|
|
1006
|
+
expect(
|
|
1007
|
+
(defaultResult.messages[0] as AIMessage).additional_kwargs
|
|
1008
|
+
.reasoning_content
|
|
1009
|
+
).toBeUndefined();
|
|
1010
|
+
|
|
1011
|
+
const result = formatAgentMessages(
|
|
1012
|
+
payload,
|
|
1013
|
+
undefined,
|
|
1014
|
+
undefined,
|
|
1015
|
+
undefined,
|
|
1016
|
+
{ provider: Providers.DEEPSEEK }
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
expect(result.messages).toHaveLength(3);
|
|
1020
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
1021
|
+
expect(result.messages[1]).toBeInstanceOf(ToolMessage);
|
|
1022
|
+
expect(result.messages[2]).toBeInstanceOf(AIMessage);
|
|
1023
|
+
|
|
1024
|
+
const toolCallMessage = result.messages[0] as AIMessage;
|
|
1025
|
+
const finalMessage = result.messages[2] as AIMessage;
|
|
1026
|
+
|
|
1027
|
+
expect(toolCallMessage.content).toBe('Using calculator.');
|
|
1028
|
+
expect(toolCallMessage.tool_calls).toHaveLength(1);
|
|
1029
|
+
expect(toolCallMessage.additional_kwargs.reasoning_content).toBe(
|
|
1030
|
+
'Need calculator.'
|
|
1031
|
+
);
|
|
1032
|
+
expect(finalMessage.content).toBe('127 * 453 = 57531.');
|
|
1033
|
+
expect(finalMessage.additional_kwargs.reasoning_content).toBe(
|
|
1034
|
+
'Calculator returned 57531.'
|
|
1035
|
+
);
|
|
1036
|
+
});
|
|
1037
|
+
|
|
1038
|
+
it('should preserve DeepSeek reasoning from supported hidden content blocks', () => {
|
|
1039
|
+
const payload: TPayload = [
|
|
1040
|
+
{
|
|
1041
|
+
role: 'assistant',
|
|
1042
|
+
content: [
|
|
1043
|
+
{
|
|
1044
|
+
type: ContentTypes.THINK,
|
|
1045
|
+
[ContentTypes.THINK]: 'Think. ',
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
type: ContentTypes.THINKING,
|
|
1049
|
+
thinking: 'Thinking. ',
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
type: ContentTypes.REASONING,
|
|
1053
|
+
reasoning: 'Reasoning. ',
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
type: ContentTypes.REASONING_CONTENT,
|
|
1057
|
+
reasoningText: { text: 'Reasoning content.' },
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
type: ContentTypes.TEXT,
|
|
1061
|
+
[ContentTypes.TEXT]: 'Done.',
|
|
1062
|
+
},
|
|
1063
|
+
],
|
|
1064
|
+
},
|
|
1065
|
+
];
|
|
1066
|
+
|
|
1067
|
+
const result = formatAgentMessages(
|
|
1068
|
+
payload,
|
|
1069
|
+
undefined,
|
|
1070
|
+
undefined,
|
|
1071
|
+
undefined,
|
|
1072
|
+
{ provider: Providers.DEEPSEEK }
|
|
1073
|
+
);
|
|
1074
|
+
|
|
1075
|
+
expect(result.messages).toHaveLength(1);
|
|
1076
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
1077
|
+
expect(result.messages[0].content).toBe('Done.');
|
|
1078
|
+
expect(
|
|
1079
|
+
(result.messages[0] as AIMessage).additional_kwargs.reasoning_content
|
|
1080
|
+
).toBe('Think. Thinking. Reasoning. Reasoning content.');
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
it('should attach later DeepSeek reasoning to an existing tool-call assistant message', () => {
|
|
1084
|
+
const payload: TPayload = [
|
|
1085
|
+
{
|
|
1086
|
+
role: 'assistant',
|
|
1087
|
+
content: [
|
|
1088
|
+
{
|
|
1089
|
+
type: ContentTypes.THINK,
|
|
1090
|
+
[ContentTypes.THINK]: 'Need calculator. ',
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
type: ContentTypes.TEXT,
|
|
1094
|
+
[ContentTypes.TEXT]: 'Using calculator.',
|
|
1095
|
+
tool_call_ids: ['call_1'],
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
type: ContentTypes.THINK,
|
|
1099
|
+
[ContentTypes.THINK]: 'Preparing tool call.',
|
|
1100
|
+
},
|
|
1101
|
+
{
|
|
1102
|
+
type: ContentTypes.TOOL_CALL,
|
|
1103
|
+
tool_call: {
|
|
1104
|
+
id: 'call_1',
|
|
1105
|
+
name: 'calculator',
|
|
1106
|
+
args: '{"input":"127 * 453"}',
|
|
1107
|
+
output: '57531',
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
],
|
|
1111
|
+
},
|
|
1112
|
+
];
|
|
1113
|
+
|
|
1114
|
+
const result = formatAgentMessages(
|
|
1115
|
+
payload,
|
|
1116
|
+
undefined,
|
|
1117
|
+
undefined,
|
|
1118
|
+
undefined,
|
|
1119
|
+
{ provider: Providers.DEEPSEEK }
|
|
1120
|
+
);
|
|
1121
|
+
|
|
1122
|
+
expect(result.messages).toHaveLength(2);
|
|
1123
|
+
expect(result.messages[0]).toBeInstanceOf(AIMessage);
|
|
1124
|
+
expect(result.messages[1]).toBeInstanceOf(ToolMessage);
|
|
1125
|
+
|
|
1126
|
+
const toolCallMessage = result.messages[0] as AIMessage;
|
|
1127
|
+
|
|
1128
|
+
expect(toolCallMessage.content).toBe('Using calculator.');
|
|
1129
|
+
expect(toolCallMessage.tool_calls).toHaveLength(1);
|
|
1130
|
+
expect(toolCallMessage.additional_kwargs.reasoning_content).toBe(
|
|
1131
|
+
'Need calculator. Preparing tool call.'
|
|
1132
|
+
);
|
|
1133
|
+
});
|
|
1134
|
+
|
|
970
1135
|
it('should strip thinking blocks and join TEXT parts as string', () => {
|
|
971
1136
|
const payload = [
|
|
972
1137
|
{
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { MessageContent } from '@langchain/core/messages';
|
|
2
|
+
import type * as t from '@/types';
|
|
3
|
+
|
|
4
|
+
type LibreChatMessageContent =
|
|
5
|
+
| MessageContent
|
|
6
|
+
| string
|
|
7
|
+
| t.MessageContentComplex[]
|
|
8
|
+
| t.ExtendedMessageContent[];
|
|
9
|
+
|
|
10
|
+
type WithLangChainContent<T extends { content: LibreChatMessageContent }> =
|
|
11
|
+
Omit<T, 'content'> & {
|
|
12
|
+
content: MessageContent;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Bridges LibreChat's extended content blocks to LangChain 1.x MessageContent.
|
|
17
|
+
*
|
|
18
|
+
* LangChain 1.x narrowed message constructor types around ContentBlock, while
|
|
19
|
+
* LibreChat still carries provider-specific blocks through the same content
|
|
20
|
+
* field. This helper keeps the runtime shape unchanged during the dependency
|
|
21
|
+
* upgrade; tracking issue: https://github.com/danny-avila/agents/issues/130.
|
|
22
|
+
*/
|
|
23
|
+
export function toLangChainContent(
|
|
24
|
+
content: LibreChatMessageContent
|
|
25
|
+
): MessageContent {
|
|
26
|
+
return content as MessageContent;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Applies the same LangChain 1.x content bridge to message constructor fields.
|
|
31
|
+
*
|
|
32
|
+
* Keep this cast-only helper local to constructor boundaries so follow-up work
|
|
33
|
+
* can replace it with aligned content types or explicit conversion logic.
|
|
34
|
+
*/
|
|
35
|
+
export function toLangChainMessageFields<
|
|
36
|
+
T extends { content: LibreChatMessageContent },
|
|
37
|
+
>(message: T): WithLangChainContent<T> {
|
|
38
|
+
return message as WithLangChainContent<T>;
|
|
39
|
+
}
|
package/src/messages/prune.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { resolveContextPruningSettings } from './contextPruningSettings';
|
|
20
20
|
import { ContentTypes, Providers, Constants } from '@/common';
|
|
21
21
|
import { applyContextPruning } from './contextPruning';
|
|
22
|
+
import { toLangChainContent } from './langchain';
|
|
22
23
|
|
|
23
24
|
function sumTokenCounts(
|
|
24
25
|
tokenMap: Record<string, number | undefined>,
|
|
@@ -343,7 +344,7 @@ function stripOrphanToolUseBlocks(
|
|
|
343
344
|
|
|
344
345
|
return new AIMessage({
|
|
345
346
|
...message,
|
|
346
|
-
content: keptContent,
|
|
347
|
+
content: toLangChainContent(keptContent),
|
|
347
348
|
tool_calls: keptToolCalls.length > 0 ? keptToolCalls : undefined,
|
|
348
349
|
});
|
|
349
350
|
}
|
|
@@ -542,7 +543,7 @@ function addThinkingBlock(
|
|
|
542
543
|
content.unshift(thinkingBlock);
|
|
543
544
|
return new AIMessage({
|
|
544
545
|
...message,
|
|
545
|
-
content,
|
|
546
|
+
content: toLangChainContent(content),
|
|
546
547
|
});
|
|
547
548
|
}
|
|
548
549
|
|
|
@@ -817,7 +818,7 @@ export function getMessagesWithinTokenLimit({
|
|
|
817
818
|
|
|
818
819
|
thinkingStartIndex = originalLength - 1 - assistantIndex;
|
|
819
820
|
const thinkingTokenCount = tokenCounter(
|
|
820
|
-
new AIMessage({ content: [thinkingBlock] })
|
|
821
|
+
new AIMessage({ content: toLangChainContent([thinkingBlock]) })
|
|
821
822
|
);
|
|
822
823
|
const newRemainingCount = remainingContextTokens - thinkingTokenCount;
|
|
823
824
|
const newMessage = addThinkingBlock(
|
|
@@ -856,7 +857,7 @@ export function getMessagesWithinTokenLimit({
|
|
|
856
857
|
}
|
|
857
858
|
}
|
|
858
859
|
|
|
859
|
-
const firstMessage
|
|
860
|
+
const firstMessage = newContext[newContext.length - 1];
|
|
860
861
|
const firstMessageType = newContext[newContext.length - 1].getType();
|
|
861
862
|
if (firstMessageType === 'tool') {
|
|
862
863
|
startType = ['ai', 'human'];
|
|
@@ -887,7 +888,10 @@ export function getMessagesWithinTokenLimit({
|
|
|
887
888
|
}
|
|
888
889
|
|
|
889
890
|
if (firstMessageType === 'ai') {
|
|
890
|
-
const newMessage = addThinkingBlock(
|
|
891
|
+
const newMessage = addThinkingBlock(
|
|
892
|
+
firstMessage as AIMessage,
|
|
893
|
+
thinkingBlock
|
|
894
|
+
);
|
|
891
895
|
newContext[newContext.length - 1] = newMessage;
|
|
892
896
|
} else {
|
|
893
897
|
newContext.push(thinkingMessage);
|
|
@@ -1178,7 +1182,7 @@ export function preFlightTruncateToolCallInputs(params: {
|
|
|
1178
1182
|
|
|
1179
1183
|
messages[i] = new AIMessage({
|
|
1180
1184
|
...aiMsg,
|
|
1181
|
-
content: newContent,
|
|
1185
|
+
content: toLangChainContent(newContent),
|
|
1182
1186
|
tool_calls: newToolCalls.length > 0 ? newToolCalls : undefined,
|
|
1183
1187
|
});
|
|
1184
1188
|
indexTokenCountMap[i] = tokenCounter(messages[i]);
|
|
@@ -1290,7 +1294,7 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
|
|
|
1290
1294
|
|
|
1291
1295
|
params.messages[i] = new AIMessage({
|
|
1292
1296
|
...message,
|
|
1293
|
-
content: [thinkingBlock],
|
|
1297
|
+
content: toLangChainContent([thinkingBlock]),
|
|
1294
1298
|
additional_kwargs: {
|
|
1295
1299
|
...message.additional_kwargs,
|
|
1296
1300
|
reasoning_content: undefined,
|
|
@@ -1966,7 +1970,7 @@ export function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {
|
|
|
1966
1970
|
});
|
|
1967
1971
|
emergencyMessages[i] = new AIMessage({
|
|
1968
1972
|
...aiMsg,
|
|
1969
|
-
content: newContent,
|
|
1973
|
+
content: toLangChainContent(newContent),
|
|
1970
1974
|
tool_calls: newToolCalls.length > 0 ? newToolCalls : undefined,
|
|
1971
1975
|
});
|
|
1972
1976
|
indexTokenCountMap[i] = factoryParams.tokenCounter(
|